# LaunchSeat community pilot · v0.16.0

The community reporter is implemented for all 30 current ballparks. It uses the same section footprints and row references as the 3D viewer, displayed one seating level at a time. A fan can mark a horizontal dot, identify only a section/row, or record an unseen destination. Home runs and foul pitches use real archived event identities. The 2026 data is a snapshot, not a live score feed.

## Map-first reporting and account drafts

Choose the recorded ball, tap its location, and answer source/catch/bounce questions in a short dialog. Row and evidence are optional unless a video review requires them. A bounce asks for a separate final spot. Account drafts resume after reload without earning points or entering consensus. Home park preferences and all-device sign-out are stored on the server.

## Run and storage

```powershell
python scripts/community_server.py
```

Open http://127.0.0.1:4198/community.html. This serves both the main site and the API. The database is `data/private/community.sqlite`, excluded from Git and unavailable through HTTP. Python's standard library is sufficient; there is no paid service or new runtime package. A static file server can display the viewer but cannot save community reports.

Accounts support username/password and configured social providers. Google, Apple, Facebook and X appear first; Microsoft, Discord and GitHub are additional options. Social sign-in automatically creates an account and returns repeat users to their original account. Signed-in fans can explicitly connect other providers. Missing credentials leave provider buttons disabled rather than simulating login. See [provider setup and verification limits](SOCIAL_AUTH.md).

Password accounts use unique usernames and scrypt hashes. Sessions use random hashed tokens, HttpOnly / SameSite=Lax cookies (Secure on HTTPS), CSRF checks, same-origin mutation checks and rate limits. The server binds only to loopback and validates the configured canonical host. No provider email or real name is collected for the public profile, and social sign-in does not establish one unique person per account. Recovery and public abuse controls remain launch work. Use a unique test password for password accounts.

Keep the SQLite database private. Use SQLite's backup API for a consistent backup while the server runs; copying only the `.sqlite` file while its WAL is active can miss writes. Never publish `data/private`, `data/cache` or the project directory as a general file listing.

## A ball, a report and an accepted landing

The server validates kind, venue, season and event ID against its archive; client-supplied batter or game details cannot create a ball. Each account has one current report per event. Corrections append an immutable payload revision and recalculate consensus and point credit; they do not add a vote.

Each schema-version-2 report has two independent `locations`: `firstImpact` and `finalSpot`. Each stores destination, section, optional row and optional horizontal dot. Either can remain unknown. The ending is separately recorded as a direct catch, catch after a bounce, resting ball, bounce with the ending unseen, or unknown. Supported areas include seating, net, bullpen, water/pool, field, concourse, roof, exterior and unknown. A net contact followed by a bullpen destination, or a seat impact followed by a catch in another section, stays as two observations of one ball. Dashed map connectors join observed endpoints; they are not bounce trajectories. Physical rebounds and intermediate bounces are not predicted.

Older reports retain an unspecified stage. They cannot vote toward either of the new stages or become a reported final catch. When correcting an old report, the fan explicitly identifies its stage before saving. Original revisions remain available. A direct catch with contradictory observed endpoints, or an unseen ending with a claimed final point, is rejected.

Pending reports stay blind: contributors see count and status, then their own saved report and the aggregate result after submitting. Raw reports from other accounts are never returned. Accepted aggregate landings are public on the main map, so previously published locations cannot remain blind forever. Ten accounts are not proof of ten independent people; public identity and abuse controls are still required before launch.

The initial consensus rule is:

- At least ten usable accounts **per stage**. Five impact reports and five final-spot reports cannot establish consensus. Unknown stages remain in the record without placement credit.
- At least 80% agree on destination, section/area and map edition within that stage. An unseen first contact does not block agreement on the final spot. Legacy, unspecified-stage groups also retain their original first-contact-category rule. Conflicting tiers or areas are never averaged.
- A row requires 80% of all usable reports to name it. If none qualifies, the row remains unknown.
- A point requires at least 80% of all usable reports inside a 35-model-foot radius of an actual submitted point. The centre is chosen from supported submitted points by support and total distance. This is a pilot clustering parameter, not a physical error bound.
- An area can be accepted without a dot. Point disagreements can leave an accepted section with no exact location. Area disagreements remain disputed.

The main map selects first impacts or catch/final spots. First impacts can include flight estimates and explicitly labeled legacy observations; final spots require an accepted report for that stage. Missing final spots never receive modeled flight endpoints. Each accepted foul contributes once within the selected view. A home-run observation updates its original event for the selected stage, without creating another home run. Accepted stages never receive a combined heat dot. Club-confirmed splash destinations cannot be silently changed by a crowd vote. Water, bullpens and other non-seating destinations never enter seat recommendations.

The outcome label also needs ten known endings with 80% agreement; otherwise it remains unknown. Acceptance rewards are capped at 10 points per ball, even when both stages agree. Independent geometry review can add 20 points once. Accuracy compares every assessable, observed stage with that stage's independent truth; a wrong final spot cannot earn full accuracy just because its first impact was right. Outcome labels do not currently earn separate accuracy credit.

Rows remain unknown when the observation lacks them. A section-only observation can rank its section, frame that section in 3D and open its ticket reminder; it cannot select a fabricated row, chair or row heat contribution. Area-only markers use a modeled centre, distinguished from a fan-marked dot. Unmapped destinations with no point remain in the database without a fabricated marker. Horizontal dots on net, roof or concourse reports do not establish height; their placement and ground-level rendering still need vertical verification.

## Points and badges

| Recognition | Qualification |
| --- | --- |
| Catch Points | 10 for an accepted contribution; 20 additional for a correct, independently assessable video review |
| First Catch | First accepted landing |
| Founder | First 25 qualifying contributors with an accepted home-run report; signup alone does not qualify |
| Foul Scout | 100 distinct accepted foul reports |
| Foul Specialist | 500 distinct accepted foul reports |
| Foul Legend | 1,000 distinct accepted foul reports |
| Sharp Eye | At least 20 independently graded reports and at least 90% accuracy |

Crowd agreement earns acceptance credit, not measured accuracy. Accuracy is correct / graded against owner-curated, independently reviewed video evidence. A matching section with missing finer detail does not claim point or row accuracy. Incorrect destination or an explicitly incorrect row is assessable. Reviewers cannot grade their own report under their account name. The accuracy leaderboard requires 20 graded reports; the contribution leaderboard uses recalculated points.

Founder slots are assigned transactionally, with earlier account creation breaking ties when several reports first qualify together. Founder recognition is retained as an early contribution achievement; point totals and other qualification-based badges can change after corrections. Fraud revocation and verified-person eligibility need a moderation policy before public awards. The live pilot starts with no users or reports; QA fixtures use a separate database and cannot consume its slots.

Points currently have no monetary value or redemption. Tickets, baseball cards, merch and memorabilia remain product ideas. No inventory, sponsor relationship, MLB endorsement or payment commitment is implied.

## Independent review

Only the local owner CLI can establish the review truth. There is no public verification endpoint. Two different named reviewers must inspect the visible landing and timestamp before the owner applies it. Supplying two names or a syntactically valid URL is not itself proof that a review happened.

Create a JSON document with `schemaVersion: 2`, the event identity (`eventId`, `kind`, `venueId`, `year`, `edition`), `locations: {firstImpact: {...}, finalSpot: {...}}`, `outcome`, `firstContact`, `source: "clip"`, `videoUrl`, `timestamp`, `notes`, `reviewer`, `secondReviewer`, and optional `toleranceFeet`. Each location uses `destination`, `section`, `row`, `areaId`, and optional `point: [x,z]`. An unseen location uses `destination: "unknown"`, empty section and row, and no point. Use identifiers from that park's report-map file. Legacy single-location reviews still work with an unspecified stage. Then run:

```powershell
python scripts/community_server.py --review data/private/review.json
```

No sample video or fabricated location is preloaded into the live database. The reviewer-defined tolerance is a comparison tolerance on approximate geometry, not surveyed seat accuracy. Keep disagreement and evidence limitations visible. A later review can replace the truth; previous independent-review payloads and the resulting point-credit changes remain recorded in private revision tables.

## Verification and public launch

```powershell
npm run check
npm test
python -m unittest discover -s tests -p '*_test.py'
npm run build
```

Browser QA uses `data/cache/community-qa.sqlite` and explicitly synthetic placements. `scripts/seed_community_qa.py` is restricted to that cache path. Never move this fixture database into `data/private` or publish its synthetic consensus as real evidence. Park queue/map checks are recorded in `data/community-browser-checks.json`.

This is a working local pilot, not an Internet deployment. Before inviting fans, provide HTTPS hosting, production session settings, account verification/recovery, moderation and abuse controls, a clear contribution policy, durable backups, deployment monitoring and an independently reviewed accuracy set. Calibrate consensus thresholds on known landings before using them for customer claims. Reward redemption will additionally need owner-approved funding, fulfillment and eligibility rules. The existing ticket routing still uses official club pages until the owner supplies approved affiliate links.

See [geometry and free mapping sources](MAPPING.md), [verification record](VERIFICATION.md) and [methodology](methodology.html).

## Park and season missions

`GET /api/progress?kind=foul&venue=3&year=2026` derives its denominator from the actual archived event IDs. Every available year is offered, including sparse early archives and explicit zero-event seasons. First impact and final spot have independent accepted, remaining, collecting, disputed, video-reviewed and unreported counts. Legacy locations do not enter either stage. Corrections recalculate coverage; contributions never multiply the ball denominator. Pending positions, sections, rows, notes and usernames are excluded from public progress.

The queue offers all balls, missing first impacts, missing final spots and disputed observations. Find a ball that needs help prioritizes events approaching consensus within the current player/date filters. Individual balls show usable reports toward the ten-report threshold without revealing the other locations. Service failures show unavailable progress instead of zero.

The shared venue policy excludes non-current actual venues and spring/exhibition/All-Star phases. Sacramento offers only 2025 onward; no Oakland records are reassigned. The static preview reads a saved aggregate snapshot and blocks all account/report mutations. See [RELEASE_PLAN.md](RELEASE_PLAN.md).
