Skip to content

fix: gate empty attack launch, inset phone banner, dedupe demo contacts - #196

Merged
BrandDead merged 5 commits into
main-tL2525from
cursor/beta-attack-contacts-phone-7c60
Sep 30, 2026
Merged

BrandDead merged 5 commits into
main-tL2525from
cursor/beta-attack-contacts-phone-7c60

Conversation

@BrandDead

@BrandDead BrandDead commented Sep 30, 2026 •

Copy link
Copy Markdown
Owner

Outcome

OPS PLAN and Block Attack stay closed until a driver and a shooter are assigned. On a phone, the Nightfall banner no longer covers the header and the welcome hint no longer sits on the dock. Reseeding the demo crew leaves one contact per id.

Claimed on existing-matching search miss: #193 (created before the first edit). #175 stays open. This does not close the outside-beta gate.

Repro

Played build 444a987 was not re-played here (NOT RE-PLAYED). From the player and critic reports:

  • GG-002. OPS PLAN → select only the dummy target → Launch Attack enables with Scout, Enforcer, and Driver still empty, then Block Attack opens with empty seats. A passenger who cannot shoot (lookout or dealer) also enabled the car's Launch Attack.
  • GG-004. At 375×812, before Dismiss, the Nightfall banner covers the wordmark and the Contacts header. The welcome hint covers the dock, including MAP.
  • GG-003. Contacts on a fresh demo logs duplicate React keys for demo-dealer-1, demo-shooter-1, demo-lookout-1, and demo-enforcer-1.

Root cause

  • AttackPlanner enabled Launch Attack from a selected target alone and navigated to topdown without a driver or a shooter. TopDownShooter.canLaunch already refused an empty car, but any occupied passenger seat counted as a shooter, including a lookout or dealer who cannot fire.
  • GhostThreatBanner is position: fixed and .page-container is position: absolute; top: 0, so the header draws underneath the banner. .tutorial-hint was pinned to bottom: 0, which is the dock.
  • useGangStore.removeMember removes the member and leaves the contact. addMember always appends a contact. applyDemoSeed does that remove-then-add on every load, so the second pass mounts a second card for each demo id.

Scope

In: launch disabled state on the existing planner route and car seats; a page inset under the banner; the welcome hint offset above the dock; demo-seed contact dedupe by id.
Out: GG-001 real-world gang and street labels (founder). GG-005 retreat morale and pending-cash sentence (founder / balance). No economy or combat math. No new encounter route (#192 stays the canonical-route decision). No Supabase, auth, RLS, persistence redesign, payments, or new art. No likeness images.
Reserved files: listed on #193.

Contracts preserved

  • Launch still uses navigateTo('topdown'). The car screen still owns seat assignment. No second combat store and no applyEncounterResult writer.
  • Banner copy, dismiss-all behavior, and threat filtering are unchanged. The inset is cleared when the banner is dismissed or hidden on the Strip desk.
  • Non-demo contacts survive a reseed. Member records are still written through removeMember / addMember.

Verification

Failing before the fix, then passing:

  • Planner: target only left Launch Attack enabled (toBeDisabled failed). After: disabled, and a click does not leave planner. Enabled only after a driver and a different shooter.
  • Car: empty seats were already disabled. A lookout in the front seat left Launch Attack enabled. After: disabled until a shooter is seated.
  • Banner inset was unset (NaN). After: at least 88px while the alert is open, cleared on dismiss.
  • Welcome hint style.bottom was empty. After: 92px plus the safe-area inset.
  • Second applyDemoSeed produced 8 contacts / 4 unique ids (9 / 5 with a custom contact). After: one contact per demo id, custom contact kept.

scripts/preflight.sh (.agents/skills/slide-release-safety/scripts/preflight.sh) passed: lint 0 errors / 200 warnings (same baseline), typecheck clean, 1024 passed / 4 skipped (91 files), asset audit 7.38 MB / 20 MB, 110 entries, 0 warnings, 5 packages / 4 schemas, production build succeeded. No backend paths changed, so pytest was not run.

Phone 375×812 and desktop 1440×900: NOT RE-PLAYED. Port 3000 was left alone.

Operational impact

None. No migration, RLS, secret, scheduler, or deployment.

Known limits

Outside-beta remains blocked on #175. Gang labels on the Block Attack target list are untouched (GG-001). The retreat sentence versus morale and cash cards is untouched (GG-005). Planner role picks are not copied into the car seats; the car still requires its own driver and shooter before combat. #192 is not this PR.

Founder follow-up — hint no longer steals the Launch Attack tap

At 375×812 the welcome hint still teaches, and it no longer receives the enabled Launch Attack tap. pointer-events: none on .tutorial-hint lets the hit pass through. No second consequence writer. PR left as draft. Not merged.

  • SHA: 3b947e73afef30d8bcee5b5911d1a1d9f569aa02
  • Evidence: /opt/cursor/artifacts/PR196_HITTEST_375.md
  • Screenshot: /opt/cursor/artifacts/replay-r1/launch_attack_enabled_375.png
  • elementFromPoint(188, 679) and the button center (187.5, 679) are button.launch-btn / LAUNCH ATTACK. PASS.

Note

Low Risk
Frontend-only UX and launch preconditions; no auth, persistence API, economy, or combat math changes. Demo roster seeding behavior changes only for repeated demo reseeds.

Overview
This PR tightens Block Attack entry and fixes phone layout overlays that were blocking taps and headers (#193).

Launch gating: OPS PLAN Launch Attack stays disabled until a target, a driver, and a different crew member who can shoot (shooter, enforcer, or boss) are assigned; the handler no-ops if disabled. TopDownShooter setup uses the same rule—lookout/dealer passengers no longer satisfy the shooter requirement. Navigation to topdown is unchanged; the car screen still owns seats.

Phone UI: The Nightfall GhostThreatBanner measures its height and sets --slide-banner-inset on the document root (min 88px); .page-container insets below it so headers aren’t covered, and the inset clears on dismiss. The tutorial welcome hint sits 92px above the bottom (safe area), and pointer-events: none so an overlapping Launch Attack button receives taps at 375×812.

Demo seed: applyDemoSeed removes demo crew contact cards before removeMember / addMember, so a second seed doesn’t duplicate demo-dealer-1 (and sibling ids); non-demo contacts are kept.

Regression tests cover planner/car launch, banner inset, hint position/hit-through, and contact dedupe; PROJECT_LOG documents the slice.

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

cursoragent and others added 4 commits September 30, 2026 20:27
OPS PLAN enabled Launch Attack from a target alone, and the car treated any passenger as a shooter. Both gates now stay closed until a driver and a member who can fire are assigned.

Co-authored-by: BrandDead <BrandDead@users.noreply.github.com>
The fixed Nightfall banner covered the header, and the welcome hint sat on the dock. The page now starts below the banner, and the hint clears the dock.

Co-authored-by: BrandDead <BrandDead@users.noreply.github.com>
removeMember left the contact card in place, and addMember appended another with the same id. The demo seed now clears those cards first so each crew id mounts once.

Co-authored-by: BrandDead <BrandDead@users.noreply.github.com>
Contact ids are plain strings. The demo id set has to accept them so the reseed filter typechecks.

Co-authored-by: BrandDead <BrandDead@users.noreply.github.com>
@vercel

vercel Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

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

Project Deployment Actions Updated
slide Ready Ready Preview Sep 30, 2026 8:56pm UTC

Request Review

@BrandDead BrandDead left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Integration review — reproducible mobile blocker on PR head 2e43366, 375×812 local demo. Fresh 18+ -> desktop -> dismiss banner -> OPS PLAN -> choose dummy target -> driver Lil Dre -> enforcer Big Rome: Launch Attack is enabled but a real Chromium click leaves the player in OPS PLANNER. Reproduced twice, no page/console errors. Immediately before click, button center was x188,y679; document.elementFromPoint(188,679) was <div class="tutorial-hint">, not the enabled .launch-btn. The hint sits y674–720 and steals clicks after the scrolling container moves the button behind it. 1440×900 flow entered the car and local combat successfully. Please fix within your reserved TutorialOverlay.css/tsx scope so the non-interactive hint cannot intercept any action and ideally suppress it on planner/topdown; add a phone player-path regression/capture with real hit-testing, not merely CSS style assertions. Keep #192 canonical-route decision separate and do not merge yet. My independent frontend full validate/build: 1024 pass/4 skipped, backend 95 pass; CI also green, but this mobile action is NOT PASS.

Copy link
Copy Markdown
Owner Author

Root-cause isolation: on the same 2e43366 source, I repeated the exact 375×812 flow with a QA-only browser style override document.querySelector(".tutorial-hint").style.pointerEvents = "none" immediately before clicking the enabled planner button. Without changing repository code, the phone run then passed planner -> car, still rejected a lookout-only car, enabled a shooter, and entered local combat. This confirms the fixed hint intercepts the tap; the PR still requires its own in-source repair and real phone retest before merge. Browser override is diagnostic only, not product evidence.

The fixed tutorial hint covered the enabled Launch Attack control at
375×812 and won elementFromPoint(188, 679). pointer-events: none keeps
the hint on screen without stealing that tap.

Co-authored-by: BrandDead <BrandDead@users.noreply.github.com>

Copy link
Copy Markdown
Owner Author

Independent integrator verification on head 3b947e7: focused TutorialOverlay regression 4/4 passed; full frontend 1025 passed / 4 skipped across 91 files, lint 0 errors / 200 baseline warnings, typecheck and production build passed; backend 95 passed. Fresh VITE_DEMO_MODE=1 real Chromium at 375×812 and 1440×900: banner initially insets the page; hint clears dock by 6px; empty/driver-only planner disabled; valid roles enabled; at phone button center (188,679), elementFromPoint now returns button.launch-btn and actual tap opens car; car rejects lookout-only, enables a shooter, enters local legacy combat; no page/console/network errors. Contacts displayed exactly four unique crew cards with no console errors across three phone loads. The hint remains visually over some scrolling content (nonblocking beta-design debt), and dismissal exit briefly animates over the rising page (<~200ms); neither was changed in this scoped repair. #192 canonical route and #175 authenticated save proof remain open; this is NOT a launch/beta-ready claim. PR is eligible for normal protected-branch integration.

@BrandDead
BrandDead marked this pull request as ready for review September 30, 2026 21:03
@BrandDead
BrandDead merged commit 638d11e into main-tL2525 Sep 30, 2026
4 checks passed
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-30T21:06:14.060873Z 3b947e7 Draft marked ready
🔒 Security Review ✅ Completed 2026-09-30T21:06:49.529432Z 3b947e7 Draft marked ready
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@cursor

cursor Bot commented Sep 30, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_3c846887-a09b-4cc9-aaaf-26cbf494c077)

This branch was successfully deployed

1 active deployment
Preview — 3b947e73 Deployed Sep 30, 2026 by vercel[bot]
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.

2 participants