Skip to content

Sprint 16 — Visual Punch List (P0 + P1 + P2 template) - #104

Open
BrandDead wants to merge 7 commits into
main-tL2525from
feat/sprint16-visual-punchlist-applied
Open

Sprint 16 — Visual Punch List (P0 + P1 + P2 template)#104
BrandDead wants to merge 7 commits into
main-tL2525from
feat/sprint16-visual-punchlist-applied

Conversation

@BrandDead

@BrandDead BrandDead commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Sprint 16 — Visual Punch List (P0 + P1 + P2 template)

Closes out the remaining visual punch list against the reference art set
(18 mockups: role contact cards, member creation v2, Las Olas topdown,
drive-by POV + HUD concept, world-concept plate).

What landed

P0

  • Loading screen → AgeGate/splash. bg_loading_screen_v001 now sits
    behind the AgeGate panel (with a legibility scrim), and a new
    SplashScreen component replaces the bare Loading... div during the
    auth check. Demo mode still skips AgeGate by design.
  • Las Olas topdown → demo seed. demoSeed.ts now points at
    block_lasolas_topdown_v001.webp; block_lasolas_1208_001 is
    registered in the environment manifest (street plates reuse stripplaza
    night/day until Las Olas street art lands).
  • Drive-by backdrop. Found + fixed the root cause of the solid-color
    background: the engine preloaded four /assets/*.jpg paths that don't
    exist (real files are /assets/runtime/*.webp), so it always fell
    back to procedural. Paths repaired, and the new in-car POV plate
    (bg_driveby_pov_v001) draws cover-fit under targets/FX — matches the
    drive-by HUD concept art shot-for-shot. Procedural stays as the
    no-asset fallback.

P1

  • OS shell wallpaper. bg_os_wallpaper_v001 (portrait aerial) wired
    into .os-shell::before — and into the six other stylesheets that
    referenced the same dead bg_desktop.jpg path (Contacts, Settings,
    Casino, AlchemyLab, App.css, theme.css). All of these rendered black
    before.
  • RoleContactCard. Mockup-accurate card: neon ring portrait, grunge
    name, role chip, LEVEL hex, two segmented stat bars, SEND TO BLOCK /
    CALL BACK. Wired into the Contacts active tab; open-profile and
    backdoor behavior preserved; send-to-block routes to the map with a
    pick-a-corner notification.
  • MemberCreation. Full-screen flow from the v2 mockup: starter
    attributes (heart / loyalty / speed / nerve / potential) with reroll,
    role rail (dealer / shooter / enforcer / recruit / k9), the
    "ONLY RECRUITS CAN PROMOTE → DEALER or SHOOTER" ribbon, name entry,
    fullbody sprite preview. First option in the Add Member modal.

P2

  • Role contact cards for Dealer, Enforcer, Lookout, K9 (+ Shooter,
    Recruit) ship as theme entries in ROLE_CARD_THEMES — one template,
    per-role neon + stat labels. Adding future roles is one entry.

Verification

  • tsc --noEmit: 0 new errors (5 pre-existing on main-tL2525:
    BlockOverlay GeoJSON ×2, CanvasStreetRendererV3 role map, TrapApp
    status comparison, assetResolver role map — the last two role-map ones
    are recruit/k9/police missing from Record<MemberRole, string> maps
    and are worth a small follow-up fix)
  • vitest run: 581/581 pass
  • node scripts/assets/audit.mjs: PASSED — 5.35 MB / 20 MB budget;
    4 non-blocking W_ORPHAN warnings for the new plates until masters
    are registered via assets:process (see APPLY notes)
  • vite build: succeeds

Known gaps / fast-follows (not blocking)

  • Drive-by window raise/lower mechanic from the HUD concept isn't in
    the engine yet — good Sprint 17 candidate.
  • RoleContactCard stat mappings are provisional (closest existing
    GangMember fields) until role-specific stats (hustle, talk game, bite
    force…) land in progression.
  • Las Olas street-level plates still pending; stripplaza night/day
    remain the street fallback.
  • Full role profile cards (XP bar, product/weapon proficiency,
    gifts, special gifts) from the v2 mockups are a natural next component
    on top of ROLE_CARD_THEMES.

Note

Low Risk
Mostly presentational assets and new optional crew UI; member creation only extends existing addMember paths with no auth or payment changes.

Overview
Sprint 16 aligns the client with the reference art set: loading/shell backdrops, Las Olas as the demo hero block, drive-by visuals, and crew UI from the mockups.

Boot & chrome: Auth wait now uses a cinematic SplashScreen (shared loading_screen_v001 plate with AgeGate). Dead bg_desktop.jpg references across several screens are replaced with os_shell_wallpaper_v001, restoring non-black backgrounds.

Map & drive-by: Demo seed and assetManifest register block_lasolas_1208_001 with Las Olas topdown art. Drive-by preloads /assets/runtime/*.webp (fixing missing .jpg paths) and composites a static in-car POV plate under gameplay.

Crew: Active contacts use RoleContactCard (per-role neon theme, segmented stats, SEND TO BLOCK → map, profile/backdoor preserved). Member Creation is a full-screen flow (reroll attributes, role pick, name) wired from Add Member and mapped into GangMember stats via segmentsToStat.

Small follow-ups in the same PR: recruit / k9 / police entries in role color/resolver maps, BlockOverlay GeoJSON typing relaxed, one NPC enforcer in seed data.

Reviewed by Cursor Bugbot for commit 3b158af. Bugbot is set up for automated code reviews on this repo. Configure here.

Claude (theLABEL AI) and others added 7 commits August 8, 2026 22:15
- AgeGate: bg_loading_screen_v001 behind the panel with legibility scrim
- New SplashScreen component replaces the bare 'Loading...' div during
  auth check. Note: demo mode skips AgeGate; production flow shows both.
Registers block_lasolas_1208_001 in the environment manifest (street
plates reuse stripplaza night/day until Las Olas street art lands).
The engine preloaded /assets/*.jpg which never existed (real files are
/assets/runtime/*.webp) so every session fell back to the solid-color
procedural background. Paths fixed, and the new in-car POV plate now
draws cover-fit under targets/FX; procedural remains the no-asset
fallback.
bg_os_wallpaper_v001 (portrait aerial plate) replaces the broken
bg_desktop.jpg reference in OSShell and the six other screens that
pointed at the same dead path (all rendered black).
Data-driven card: neon ring portrait, role chip, LEVEL hex, two
segmented stat bars, SEND TO BLOCK / CALL BACK. ROLE_CARD_THEMES
covers dealer, shooter, enforcer, lookout, k9, recruit — P2 role
cards are the same template, one theme entry each. Stat mappings
provisional until role-specific progression stats land.
Full-screen creation: starter attributes (heart/loyalty/speed/nerve/
potential) with reroll, role rail w/ recruit-promote ribbon
(RECRUIT → DEALER or SHOOTER), name entry, fullbody sprite preview.
Contacts: new first option in Add Member modal; active tab now renders
RoleContactCard (open/backdoor preserved, send-to-block navigates to
map, call back opens profile).
@vercel

vercel Bot commented Aug 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
slide Ready Ready Preview Aug 8, 2026 10:22pm

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 3b158af. Configure here.

className={`mc-role${role === id ? ' mc-role-active' : ''}`}
style={{ ['--mc-role' as any]: accent }}
onClick={() => { setRole(id); setSpriteOk(true); }}
aria-pressed={role === id}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale sprite error clears preview

Medium Severity

Member preview uses one shared spriteOk flag and an onError handler that always sets it false. After switching roles, a late error from the previous role’s image request can flip spriteOk off while the current role’s sprite is valid, so the UI shows the icon fallback instead of the full-body art.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 3b158af. Configure here.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3b158af1b0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

message: `Pick a corner for ${contact.nickname || contact.name}`,
timestamp: new Date().toISOString(),
} as any);
navigateTo('map');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Enter placement mode before routing to the map

For every active contact, SEND TO BLOCK only posts a “Pick a corner” notification and navigates to the map. It never calls useBlockStore.setPlacementMode with this member, while TopDownBlock only places a member when isPlacementMode and pendingPlacementMemberId are set, so tapping a corner after this action does nothing and the advertised deployment flow is nonfunctional.

Useful? React with 👍 / 👎.

role?: string,
): { label: string; value: number }[] {
const theme = getRoleCardTheme(role);
const read = (k: StatKey) => Math.max(0, Math.min(100, Number(member?.[k] ?? 50)));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Read card stats from the canonical member fields

Canonical GangMember records, including the demo seed and market hires, store combat attributes under member.stats and do not define top-level shooting, dealing, driving, heatResistance, or stealth. Reading member[k] therefore silently substitutes 50 for most role-specific bars—for example, every seeded shooter shows 50 shooting regardless of its actual stats—making the new contact cards display misleading progression data.

Useful? React with 👍 / 👎.


// Sprint 16 (P0): in-car POV plate — storefront strip seen through the
// passenger window (matches the drive-by HUD concept art shot-for-shot).
const DRIVEBY_POV_BG = '/assets/runtime/generated/environments/street/bg_driveby_pov_v001.png';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Ship the POV asset referenced by the drive-by engine

The reviewed Git tree has no bg_driveby_pov_v001.png anywhere (verified with a repo-wide tree search), so this URL always returns 404 and the naturalWidth > 0 drawing branch can never run. Consequently the newly advertised in-car POV backdrop is absent in every build and the engine continues rendering only its procedural/parallax fallback.

Useful? React with 👍 / 👎.

name={contact.nickname || contact.name}
role={contact.role}
level={(member as any)?.level ?? 1}
avatarUrl={contact.customAvatarUrl}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve legacy contact avatars on the new cards

For persisted contacts that use the valid Contact.avatar field rendered by the previous ContactCard, the replacement passes only customAvatarUrl, so their saved portrait is discarded and the card falls back to a letter. Pass contact.customAvatarUrl ?? contact.avatar so upgrading to this card does not regress existing contact images.

Useful? React with 👍 / 👎.

Comment on lines +69 to +71
accent: '#ff4d6d', glow: 'rgba(255, 77, 109, 0.45)', label: 'SOLDIER',
primary: { label: 'PRIMARY', statKey: 'shooting' },
secondary: { label: 'SECONDARY', statKey: 'loyalty' },

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Add themes for every existing roster role

A driver hired from the existing Market is a valid active contact, but ROLE_CARD_THEMES has no driver entry, so this fallback labels that member SOLDIER and shows generic PRIMARY/SECONDARY bars instead of their actual role. The same regression affects other supported roles such as chemist, runner, and boss; the previous card displayed contact.role directly.

Useful? React with 👍 / 👎.

role,
status: 'active',
level: 1,
xp: segmentsToStat(a.potential) - 35, // potential seeds a small XP head start

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Seed the canonical experience field during creation

When potential grants a new member an XP head start, only the optional xp alias is populated. The progression panel, Slide rewards, and dealer game loop all read member.experience, so the member initially displays zero XP and the first normal reward is calculated from zero, discarding the promised 13–52 starting XP. Initialize experience consistently with xp here.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant