en una conversacion ayer arreglabamos errores de main. como quedo eso?


# Ballbox Host App Plan

## Goal
- Convert `ballbox` into the host app for Ballbox platform.
- Preserve the current marketing home at `/`.
- Add a shared admin shell at `/admin`.
- Keep product boundaries explicit with dedicated subroutes.
- Converge on a shared `network` core model that all product domains reference.

## Current State
- Ballbox overall is still in validation stage for padel centers; there are no customers yet and near-term proof still depends on pilots with the first machines.
- `/` remains the marketing home.
- `/admin` is live as the shared Ballbox admin shell.
- Product-separated admin areas exist for `tvs`, `payments`, `network`, `sports`, and `players`.
- `/admin/screens` exists as the runtime entry area for TVs.
- `/player/[screenId]` is the lightweight TV runtime route served as plain HTML + JavaScript inside Ballbox.
- `/player/[screenId]` now exists as the lightweight TV runtime route served as plain HTML + JavaScript inside Ballbox.
- TVs are internal to Ballbox as a module, not a separate app.
- TVs admin and `/api/tvs/*` use an internal Ballbox ownership model for clubs, venues, screens, and campaigns.
- TVs runtime/admin already read Ballbox Postgres directly through Prisma.
- TVs runtime heartbeats and impressions already write to Ballbox DB-backed flows.
- TVs manifest/admin scheduling now respects campaign and assignment time windows.
- TVs now expose a strict Zod-backed API contract plus contract tests.
- TVs runtime now exposes on-screen diagnostics for cache/object-URL/manual parity verification on real devices.
- TVs runtime diagnostics now also support a one-click parity snapshot JSON export (playback/cache/network/reporting state + user agent + capture timestamp) to standardize real-device evidence capture.
- TVs player runtime cache/media/impression/heartbeat/manifest-refresh logic now lives in one shared core used by both the React player and the lightweight plain-JS player shell.
- Maintainability review for the next refactor cycle is documented in `docs/maintainability-priorities-2026-03.md`.
- Payments are now being consolidated into Ballbox host app: native MercadoPago webhook intake exists under `/notification/mercadopago` with signature validation and order fetch.
- Payments host app now also exposes native QR order creation under `/api/integrations/payments/orders`, generating canonical `externalReference` values required for approved-session persistence correlation.
- Legacy bridge callback compatibility still exists at `/api/integrations/payments/approved` during transition.
- `/admin/payments` now exposes Ballbox-local CRUD/reconciliation for approved payment sessions plus correlation checks against canonical `payment:{vendingMachineId}:{machineTxnId}` references.
- Payments admin session routes now read Prisma error helpers from `lib/prisma-errors.ts` instead of importing them via `lib/ballbox-store.ts`.
- Network core now has DB-backed admin CRUD for ATC-linked clubs, venues, and vending machines inside Ballbox.
- Prisma `Club.atcSportclubId` now matches live nullable data to prevent admin loader `P2032` crashes on legacy clubs without ATC linkage (`/admin/network`, `/admin/players`, `/admin/sports`, `/admin/tvs`).
- Clubs keep nullable `atcSportclubId` support for legacy/local rows, and repo now ships `db:backfill-atc-clubs` to reconcile local club names with ATC summary data when ids exist.
- Network club list/detail/admin query shaping has started moving out of `lib/ballbox-store.ts` into a dedicated backend module.
- Network club create/update/delete helpers have now also started moving out of `lib/ballbox-store.ts` into a dedicated backend module.
- Network venue mutation/delete helpers have also started moving out of `lib/ballbox-store.ts` into dedicated backend modules.
- Network vending-machine route callers now import `lib/network-backend-vending-machines.ts` directly and read unique-constraint classification from `lib/prisma-errors.ts`.
- Network club/venue route callers and `/admin/network` page now import direct network backend modules (`lib/network-backend-clubs.ts`, `lib/network-backend-club-mutations.ts`, `lib/network-backend-venues.ts`) plus `lib/prisma-errors.ts`.
- Network route handlers now share `lib/http/network-route-helpers.ts` for JSON parsing plus success/error envelopes across club, venue, and vending-machine contract routes.
- Players, sports, and payments route handlers now also share `lib/http/*-route-helpers.ts` so public/admin contract surfaces no longer depend on deep route-local helper imports.
- Network admin frontend view extraction has started moving venue-level and club-level rendering blocks out of `components/network-admin-client.tsx` into smaller components.
- Network admin frontend section composition has now also started moving club-list rendering, create-club section wiring, and derived venue-form wiring out of `components/network-admin-client.tsx` so it trends further toward a shell.
- Network admin frontend client-state, mutation orchestration, and local form-state wiring have started moving out of `components/network-admin-client.tsx` into dedicated hooks so the client trends toward a shell.
- Network admin frontend form defaults and status-option constants now live in a shared client config so shell and child components consume one source of truth.
- Network admin frontend layout/class wiring now also lives in a dedicated shell component so `components/network-admin-client.tsx` is closer to trivial hook composition.
- Network admin frontend shell chrome styles now also live in a tiny shared helper so the shell stays closer to pure composition/wiring.
- Players admin frontend client-state, form defaults, shell composition, and presentational stats/create/list-card seams now live in dedicated frontend modules so the client follows the same maintainable pattern already used by network.
- Sports admin frontend client-state, form defaults, shell composition, and coach/event section rendering now live in dedicated frontend seams so `components/sports-admin-client.tsx` is closer to pure wiring.
- Final naming direction is `network` core with `Club`, `Venue`, `VendingMachine`, `Screen`, and `TvDevice`.
- Post-`pnpm db:push` plus `pnpm db:seed` verification confirms physical DB columns stay canonical as `vendingMachineId` and `tvDeviceId`, with no `machineId`, `deviceId`, `/devices`, or `PaymentSessionRef` persistence aliases reintroduced.
- TVs admin now has DB-backed CRUD for screens and tv devices inside Ballbox.
- TV device admin mutations have started moving out of `lib/ballbox-store.ts` into a dedicated backend module.
- TV screen admin mutations have now also started moving out of `lib/ballbox-store.ts` into a dedicated backend module.
- TV campaign admin mutations have now also started moving out of `lib/ballbox-store.ts` into a dedicated backend module.
- TV creative admin mutations have now also started moving out of `lib/ballbox-store.ts` into a dedicated backend module.
- TV assignment admin mutations have now also started moving out of `lib/ballbox-store.ts` into a dedicated backend module.
- TV admin venue-option query shaping has now also started moving out of `lib/ballbox-store.ts` into a dedicated backend module.
- TV admin device/screen/campaign operations query shaping has now also started moving out of `lib/ballbox-store.ts` into a dedicated backend module.
- TV runtime source/manifest/heartbeat/impression helpers now also delegate from `lib/ballbox-store.ts` into a dedicated TV runtime backend module.
- TVs admin now has DB-backed CRUD for campaigns, creatives, and screen assignments inside Ballbox.
- Admin now supports a simple shared-password access layer when `BALLBOX_ADMIN_PASSWORD` is configured.
- TVs impressions now reject creatives that are not active for the target screen.
- Players API now reads Ballbox Postgres for `Player` and `Membership` rollups.
- Player backend read/admin query+mutation helpers have now started moving out of `lib/ballbox-store.ts` into a dedicated backend module.
- Sports coach backend helpers have now started moving out of `lib/ballbox-store.ts` into a dedicated backend module.
- Sports events plus classes offer/request backend helpers have now also started moving out of `lib/ballbox-store.ts` into dedicated backend modules.
- Sports now has DB-backed entities and admin/read APIs for coaches, open matches, and classes.
- `/classes` now exists as the first non-admin public Ballbox surface.
- `/classes` now lists Ballbox-local `ClassOffer` records, shows offer detail, surfaces visible ATC public-read slots, and accepts local `ClassRequest` submissions with either a concrete selected slot or a flexible any-schedule/any-location fallback.
- `/classes-by-date` now ships as a zone-first reservation calendar driven by coach availability plus ATC club availability, including explicit “coach disponible, pero sin canchas” slots and a required first zone selection based on the club's public location label when available.
- `/classes/me` now ships as a lightweight read-only student follow-up view (email-filtered request history) so demos can show the request loop without claiming full reservation confirmation.
- `/classes` initial HTML now renders from Ballbox-local offer data first and resolves ATC public-read context asynchronously after paint, with a short shared server cache to avoid repeating the same ATC lookup per visitor.
- Rapid demo execution now follows `docs/demo-iteration-mode.md` (`L1 story` / `L2 contracted demo` / `L3 production candidate`) so pivots stay fast without leaking demo shortcuts into core modules.
- `/coaches` now acts as the Ballbox account hub where the first differentiation is `Coach` vs `Club`.
- `/coaches` now defaults to `Sign in`, and `Sign up` is the fallback path for new accounts.
- `/coaches/settings` now lands on a coach dashboard first with `Calendar` and `Analytics` sub-sections: calendar shows the current week's coach availability plus taken student reservations, while analytics shows weekly earnings and student consistency/review rows; setup stays in `Mi Perfil` and student follow-up stays in `Alumnos`.
- `/clubs` now exists as the club-only service home that opens right after club sign-in/sign-up and groups the operational surfaces into service cards, with `Entrenadores` as the active entry point into the existing coaches workspace and the remaining services marked as `Proximamente`.
- `/clubs/coaches` now lands on a club workspace with top-level `Calendar`, `Analytics`, `Sedes`, and `Profesores` sections: calendar shows the current week's coach availability and reservations with sede/coach/court filters plus in-place manual class loading, analytics shows professor/reservation money splits and review placeholders, `Sedes` groups venue creation plus venue quick settings, and `Profesores` groups invite links plus the club coach table.
- `/clubs/coaches` now also enforces the club session at the page boundary before rendering the workspace, preventing the `Entrenadores` service-card hop from dropping users back into the shared `/coaches` access hub after a valid club login.
- Club workspace clickable actions are now visually distinguished with stronger accent borders, CTA chips, and hover/focus states, while existing-setting edits in club quick settings and venue detail auto-save in place instead of requiring explicit `Guardar` buttons or reloading the user back to the top.
- `/api/coaches/students` now lets a coach load existing Ballbox players into concrete occupied time slots, validating availability, venue fit, and overlap rules, and the coach workspace now surfaces those students in a dedicated `Alumnos` section with WhatsApp / Telegram contact fields.
- `/clubs/venues/[venueId]` now exists as the dedicated venue detail view for configuring venue opening/closing time, coach hours, external-coach availability, reservation settings, courts, and the coaches assigned to that venue.
- `CoachAvailability` weekly ranges and `CoachClub` selections now model coach intent separately from ATC court availability, while coach-side editing is clamped to the hours enabled by the assigned venue or the selected external clubs.
- Clubs now carry optional ATC sportclub ids to query availability at the club level.
- Clubs now also carry an optional contact email used for demo-grade club access and roster management.
- Venues now also store one opening time, one closing time, weekly coach-availability ranges, an external-coach availability flag, coach-enabled courts per venue, a special reservation price for coach classes, a club-coach-only discount on that fee, and a configurable late-cancellation window in hours.
- Coaches now can also be assigned to one venue inside their club.
- Coaches now also persist a Mercado Pago placeholder handle plus reusable sales-package rows for pricing, duration, class format, and max-student setup.
- Coaches and clubs now also store per-account password hashes for sign-in.
- Clubs now also persist coach invite tokens for generic join links, while still tolerating older email-bound invites.
- Local development now has a first-class Docker Postgres path via `docker-compose.yml` plus `.env.local`, and the seed now provisions demo coach/club passwords for local sign-in.
- Auth/session routes now return explicit database-unavailable errors when Prisma cannot reach or borrow a DB connection, instead of surfacing those failures as generic bad-login states.
- `/admin` overview now reads lightweight aggregate counts instead of hydrating full product datasets during SSR.
- Coach experience discovery is still early: current research input is an online form, so Ballbox does not yet have enough real-world coach workflow evidence to lock the sports product thesis.
- ATC admin/write is still not integrated; only a small public-read availability boundary now exists for `/classes` offer context and must degrade cleanly when unavailable.
- Local quality gate now includes `pnpm lint`, `pnpm typecheck`, `pnpm test:contracts`, `pnpm test:e2e`, and `pnpm build`.
- Vitest taxonomy now includes layered includes for `tests/contracts`, `tests/unit`, and `tests/integration`, with dedicated scripts for each layer.

## Route Map
- `/`: marketing home
- `/admin`: admin overview
- `/admin/tvs`: TV and screen operations
- `/admin/payments`: payment operations and reconciliation
- `/admin/network`: clubs, venues, vending machines
- `/admin/sports`: open matches, coaches, academy
- `/admin/players`: players y memberships
- `/admin/screens`: screen runtime admin surface hosted inside Ballbox
- `/classes`: public class discovery + request surface
- `/classes/[offerId]`: public offer detail + request form
- `/classes-by-date`: zone-first reservation discovery calendar
- `/coaches`: account hub for coach vs club
- `/classes/me`: read-only student request follow-up
- `/coaches/settings`: coach dashboard with `Calendar` / `Analytics`, plus `Mi Perfil` and `Alumnos`
- `/clubs`: club service home
- `/clubs/coaches`: club workspace with `Calendar` / `Analytics` / `Sedes` / `Profesores`
- authenticated coach/club workspace routes now use a shared top navbar with section tabs and an avatar-triggered sign-out menu instead of top-corner text links or standalone explainer hero panels
- coach workspace now also includes student follow-up and manually occupied-hour management using existing `Player` records, including coach-editable WhatsApp and Telegram contact data
- `/clubs/venues/[venueId]`: dedicated venue setup and venue roster

## Backend Split
- Ballbox Next.js host:
  - app shell
  - admin UI
  - shared auth/RBAC foundation
  - low-complexity CRUD
  - BFF aggregation and integration routes
  - shared `network` core entities
  - internal TVs module and runtime
- External specialized services:
  - none required for current payments callback/webhook flow (legacy bridge compatibility remains temporarily accepted)

## Implemented
- Shared admin shell and product-separated routes are in place.
- Admin shell copy now adapts per route instead of repeating one generic hero across every module.
- TVs now resolve admin/runtime state from a canonical internal Ballbox model with explicit club, venue, screen, and campaign ownership.
- TVs runtime now has a per-screen route and manifest-driven player UI.
- TVs now also expose a lightweight non-React runtime at `/player/[screenId]` for constrained devices.
- Prisma/Postgres foundation now exists in Ballbox for the durable replacement.
- Ballbox Postgres has the TVs schema pushed and seeded with current local fixture data.
- Network APIs now read/write Ballbox Postgres through Prisma.
- TVs source/manifest/impression/heartbeat paths already read/write against Ballbox Postgres.
- TVs admin now exposes direct runtime and manifest links per screen for operations.
- TVs errors now use a shared strict shape and the contract is validated by `pnpm test:contracts`.
- Payments integration health and sessions routes now report Ballbox-internal status plus MercadoPago configuration/webhook metadata.
- Payments approved-session callbacks now land in Ballbox, validate canonical payment correlation, and persist as `PaymentSession` records.
- Payments now have an admin CRUD/reconciliation surface over local `PaymentSession` rows via `/api/admin/payments/*`.
- Final target model is documented in `docs/domain-model-target.md`; end state does not keep retro-compatibility shims.
- ESLint is now wired and the repo exposes an explicit `typecheck` script.
- `/admin` and current admin-only APIs can now be gated by a shared password cookie session.
- `/admin/tvs` now performs admin CRUD for screens and tv devices through admin-only APIs under `/api/admin/tvs/*`.
- `/admin/tvs` now performs admin CRUD for campaigns, creatives, and assignments through admin-only APIs under `/api/admin/tvs/*`.
- TVs impression writes now validate creative-to-screen activity windows before persisting telemetry.
- Players now have DB-backed read/admin APIs for `Player` and `Membership`.
- Players route + page callers now import `lib/players-backend.ts` (and `lib/network-backend-clubs.ts` for club lists) directly instead of relying on `lib/ballbox-store.ts` for runtime access.
- Sports now have DB-backed read/admin APIs for `Coach`, `OpenMatch`, and `Class`.
- Classes MVP now also has DB-backed public APIs for `ClassOffer` and `ClassRequest`.
- `/classes/me` now provides a lightweight student request-history surface over Ballbox-local `ClassRequest` records (read-only, demo-grade email lookup).
- `ClassRequest` now snapshots the student's selected visible slot when they choose one, and otherwise persists an explicit flexible-selection fallback mode.
- Coach availability now ships as weekly ranges with 90-minute slots, filtered by coach club selection and ATC club availability.
- Coach and club account entry now starts at `/coaches`, with `Sign in` first and `Sign up` only for users without an account.
- Coaches and clubs now sign in with per-account email + password credentials, and `/api/account/session` routes each session to the correct dashboard.
- Coach sign-up now asks only for name, email, and password; if a club invited that coach, the invite link auto-links the account to that club.
- `/coaches/settings` now opens on a dashboard split into `Calendar` and `Analytics`, then lets coaches move into configuration from the shared navbar to choose external clubs, edit weekly availability only inside allowed venue/club windows, configure reusable class packages, and save a Mercado Pago placeholder handle.
- `/coaches/settings` now also lets coaches attach existing Ballbox players to concrete booked slots in their active venues, so taken hours, weekly earnings, consistency tracking, and lightweight student follow-up live inside the coach workspace.
- Club sign-in/sign-up now lands on `/clubs`, a service home that separates the club's operational modules before entering the detailed coaches workspace.
- Club accounts now have a dedicated workspace at `/clubs/coaches` split into `Calendar`, `Analytics`, `Sedes`, and `Profesores`, while venue-by-venue deep setup still lives at `/clubs/venues/[venueId]`, all under the same shared navbar/profile chrome.
- Venue setup now uses two simple fields for opening and closing time plus a collapsible weekly half-hour grid for coach hours, shows closed periods in red while editing coach availability, lets clubs mark whether external coaches are allowed, keeps coach-enabled courts in a dedicated selection panel, and includes reservation pricing/cancellation settings both in the venue detail and as quick settings on `/clubs/coaches`, including a discount that applies only to coaches assigned to that club.
- ATC lookups for class surfaces now resolve by club (no court coupling), and class request validation rechecks the selected slot date/time against ATC public-read.
- `/classes` SSR now avoids blocking first paint on ATC public-read fetches; the page paints local offer data first, then hydrates ATC availability from cached API responses.
- `/admin` overview SSR now uses direct aggregate counts instead of loading full admin datasets only to derive metrics.
- Sports/classes facade exports in `lib/ballbox-store.ts` now delegate to dedicated sports-events and classes backend modules instead of keeping that slice inline.
- Sports route + page callers now import `lib/sports-backend-events.ts` and `lib/sports-backend-coaches.ts` directly, so `lib/ballbox-store.ts` is no longer the primary sports entrypoint.
- TV runtime/backend facade exports in `lib/ballbox-store.ts` now delegate to `lib/tvs-backend-runtime.ts` instead of keeping source/manifest/heartbeat/impression logic inline.
- UI color/system tokens are split between landing (`app/styles/landing-tokens.css`) and admin (`app/styles/admin-tokens.css`).

## Streetcast Migration Check
- Source of truth for parity review: `/Users/sebas/Code/street-cast-pwa`.
- Covered in Ballbox today:
  - manifest polling exists in `components/screen-player.tsx`
  - sequential creative playback exists in `components/screen-player.tsx`
  - impression writes exist in `components/screen-player.tsx`
  - runtime health signaling exists via heartbeats in `components/screen-player.tsx`
- Missing or not yet verified against Streetcast behavior:
  - no manual real-device verification yet proves CacheStorage/object-URL playback outside local browser automation

## Next Steps (Priority + Dependency Queue)
- Source of truth for task backlog and dependencies: `docs/next-steps-queue.md`.
- Selection rule for the next agent: pick the highest-priority task marked `ready` in that doc.
- Current pick (`P0`, `ready`): `OPS-1` payments real-world validation closure.
- Immediately after `OPS-1`: `OPS-2` TVs runtime parity closure.
- Then continue with `P1` in dependency order: `ARCH-2` and `ARCH-3` -> `PERF-1` -> `PAY-2` -> `PAY-3`.
- Keep detailed backlog/status only in `docs/next-steps-queue.md` to avoid drift.

### Product Continuation Constraints
- Keep `sports` discovery honest: no claims beyond evidence in `docs/coaches-discovery-stage.md`.
- Next sports expansion after `/classes/me`: lightweight operator review for incoming requests.
- Expand ATC scope beyond public-read only after the request loop proves it is needed.

[82 more lines in file. Use offset=201 to continue.]


bash

git status --short --branch && echo '---' && git log --oneline --decorate -n 12

ls -1 docs | sed -n '1,120p' && echo '---' && if [ -f docs/next-steps-queue.md ]; then sed -n '1,220p' docs/next-steps-queue.md; fi


## main...origin/main
---
95f8b5c (HEAD -> main, origin/main, origin/HEAD) docs: require plan/progress docs and frequent pushes
ce929a8 fix club coaches schema drift fallback
a51790c fix club coaches fallback messaging
75e2812 fix auth redirect and align contracts
c713f97 fix club coaches auth redirect
1ba63f7 force redeploy
39bdcce Merge pull request #25 from sebasfavaron/FelipeVersion
129e317 fix CI errors
edd7b44 Merge branch 'main' into FelipeVersion
e7ff23e Dashboard principal mostrando todos los servicios para clubes, calendario como view principal para coahces y profesores
f3d16c1 (origin/FelipeVersion) Sign in, sign up, dashboard for clubs and coaches, reservations, configurations for coaches and clubs, more UI than stable backend
d2d679b (FelipeVersion) fix: avoid useSearchParams in route feedback during prerender


atc-access-request-checklist.md
atc-integration-discovery.md
atc-integration-spec-skeleton.md
atc-mock-integration-plan.md
ballbox-db-plan.md
classes-implementation-notes.md
classes-mvp-rfc.md
classes-subroute-plan.md
coach-availability-rfc.md
coaches-coordination-gap-analysis.md
coaches-design-partner-outreach.md
coaches-discovery-execution-plan.md
coaches-discovery-stage.md
coaches-form-current.md
coaches-icp-segmentation.md
coaches-interview-script.md
coaches-jtbd-workflow-map.md
coaches-opportunity-brief.md
coaches-research-repository.md
coaches-solution-thesis.md
coaches-validation-checklist-2-weeks.md
coaches-wedges-matrix.md
demo-iteration-mode.md
domain-model-target.md
implemented-host-app.md
implemented-network.md
implemented-payments.md
implemented-players.md
implemented-sports.md
implemented-tvs.md
index.md
maintainability-priorities-2026-03.md
next-steps-queue.md
repo-map.md
screen-runtime-delivery-investigation.md
streetcast-parity.md
---
# Next Steps Queue

## Purpose
- Keep `PLAN.md` actionable without turning it into a long unordered backlog.
- Let any agent pick the next best task quickly using priority + dependency.

## Picking Rule
- Pick the highest-priority task with `Status: ready`.
- If a task is `blocked`, unblock its dependency first.
- After shipping, update this file, `PLAN.md`, and relevant `docs/implemented-*.md` in the same work.

## Recently Completed (2026-04-14)

### DOC-1 Docs normalization baseline
- Priority: P0
- Status: completed
- Depends on: none
- Scope shipped:
  - docs navigation/categories normalized in `docs/index.md`
  - `docs/repo-map.md` maintained as a fast entrypoint map
  - stale/missing references removed from active docs surfaces (`README.md`, `PLAN.md`, `docs/index.md`)
- Evidence: `node scripts/check-doc-references.mjs` passes

### DOC-2 PLAN execution hygiene
- Priority: P0
- Status: completed
- Depends on: none
- Scope shipped:
  - `PLAN.md` next-steps section reduced to queue pointer + explicit pick order
  - active queue wording avoids mixing done narrative
  - handoff wording keeps one clear "pick this next" target
- Expected payoff: next-agent selection is immediate

### DOC-3 Docs drift CI guard
- Priority: P0
- Status: completed
- Depends on: none
- Scope shipped:
  - CI check validates docs references in `README.md`, `PLAN.md`, and `docs/index.md`
  - CI fails on broken/missing local doc references
- Evidence: `.github/workflows/docs-drift-guard.yml`, `scripts/check-doc-references.mjs`

### ARCH-1 Route helper boundary cleanup
- Priority: P1
- Status: completed
- Depends on: DOC-1 (done)
- Scope shipped:
  - route helper/envelope parsing moved to shared `lib/http/*`
  - deep relative helper imports removed from network, players, sports, and payments route handlers
- Evidence: route handlers now import `@/lib/http/*-route-helpers`

### OPS-0 Admin surface 500 fix (`/admin/tvs`, `/admin/network`, `/admin/sports`, `/admin/players`)
- Priority: P0
- Status: completed
- Depends on: none
- Scope shipped:
  - aligned Prisma `Club.atcSportclubId` with live nullable data to prevent runtime `P2032` decode failures
  - regenerated Prisma client after schema alignment
  - added `db:backfill-atc-clubs` to sync local club names with ATC summary by `atcSportclubId` while keeping null-ATC clubs supported
- Evidence: Prisma `club.findMany` now handles rows with `atcSportclubId = null`

## P0 Ready

### OPS-1 Payments real-world validation closure
- Priority: P0
- Status: ready
- Depends on: none
- Scope:
  - run one public webhook smoke with real callback path
  - run one real payment and verify persisted approved callback in `/admin/payments`
  - document observed payload + public URL evidence
- Progress (2026-04-14): payments migration to host app started in one feature branch; health/sessions now expose internal MercadoPago mode, Ballbox ships `/notification/mercadopago` intake with signature validation + order fetch, and native order creation now exists at `/api/integrations/payments/orders`.
- Expected payoff: closes highest-risk integration uncertainty

### OPS-2 TVs runtime parity closure
- Priority: P0
- Status: ready
- Depends on: none
- Scope:
  - manually verify real-device CacheStorage/object-URL behavior on `/player/[screenId]`
  - update `docs/streetcast-parity.md` with concrete evidence
- Progress (2026-04-14): runtime now exports a JSON parity snapshot from `/player/[screenId]` to standardize evidence capture; remaining work is one real-device run and doc evidence entry.
- Expected payoff: de-risks constrained-device production behavior

## P1 After P0

### ARCH-2 Continue `ballbox-store` caller migration
- Priority: P1
- Status: ready
- Depends on: ARCH-1 (done)
- Scope:
  - migrate callers to direct domain modules where clearer
  - keep `lib/ballbox-store.ts` as minimal compatibility facade only
- Progress (2026-04-14): sports route/page callers and sports UI/test types now import direct sports backend modules; players route/page callers now import `lib/players-backend.ts` directly (plus `lib/network-backend-clubs.ts` for admin club list hydration); payments admin session routes now consume Prisma error helpers from `lib/prisma-errors.ts`; and network route/page callers now import direct network backend modules (`clubs`, `club-mutations`, `venues`, `vending-machines`) plus `lib/prisma-errors.ts`. Remaining scope continues with the same migration pattern for TVs and classes surfaces still reading via `lib/ballbox-store.ts`.
- Expected payoff: less coupling and better module discoverability

### ARCH-3 Test taxonomy split
- Priority: P1
- Status: ready
- Depends on: DOC-1 (done)
- Scope:
  - separate tests by intent: `contracts`, `unit`, `integration`
  - align `vitest.config.ts` includes with those layers
- Progress (2026-04-14): `vitest` include patterns now cover `tests/contracts`, `tests/unit`, and `tests/integration`; dedicated scripts now exist for each layer, and first unit moves landed (`network/route-helpers`, sports client config/state tests).
- Expected payoff: faster debugging and more intentional coverage growth

### PERF-1 TTFB focused pass
- Priority: P1
- Status: ready
- Depends on: OPS-1
- Scope:
  - measure `/classes` and `/admin` server timings
  - add only the cache/instrumentation changes justified by measurement
- Expected payoff: better responsiveness without blind cache complexity

### PAY-2 Full payments migration into Ballbox host app
- Priority: P1
- Status: ready
- Depends on: OPS-1
- Scope:
  - migrate remaining bridge-owned MercadoPago flow (webhook + order lifecycle) into Ballbox routes/lib
  - remove reliance on `BALLBOX_PAYMENTS_URL` bridge dependency for operational status
  - keep callback compatibility during transition, then retire bridge dependency cleanly
- Progress (2026-04-14): host app now includes MercadoPago webhook route (`/notification/mercadopago`) plus signature verification and order fetch primitives.
- Progress (2026-04-14): host app now also includes QR order creation (`/api/integrations/payments/orders`) with canonical `externalReference` generation (`payment:{vendingMachineId}:{machineTxnId}`).
- Expected payoff: one-repo payments ownership, simpler operations, faster debugging

### PAY-3 Split payments (MercadoPago Partners) per club
- Priority: P1
- Status: blocked
- Depends on: OPS-1, PAY-2
- Scope:
  - define a fixed Ballbox split-payments setup equivalent to v1 so every approved payment can route a configurable percentage to the club owning the vending machine
  - add an admin CTA in club configuration to start/link MercadoPago partner onboarding for that club
  - persist the minimum per-club MercadoPago partner metadata/credentials required for payout routing and operational support
  - document security and rotation rules for stored credentials before go-live
- Notes:
  - implementation details are intentionally pending discovery when this task is started
  - keep this behind real-world payments validation first (`OPS-1`)
- Expected payoff: platform-controlled split payments with club-aligned revenue distribution

## P2 Sequenced Refactors

### ARCH-4 Domain folder architecture
- Priority: P2
- Status: blocked
- Depends on: ARCH-2, ARCH-3
- Scope:
  - move flat prefix-based modules into domain folders in `lib/` and `components/`
  - preserve behavior; focus on discoverability and ownership boundaries
- Expected payoff: major readability improvement for future work

### ARCH-5 Route IA normalization (`/classes*` + `/coaches*`)
- Priority: P2
- Status: blocked
- Depends on: DOC-1
- Scope:
  - align route grouping and naming with real auth/surface behavior
  - keep redirects/aliases explicit during transition
- Expected payoff: lower confusion in feature placement and routing maintenance

### ARCH-6 Naming conventions and metadata cleanup
- Priority: P2
- Status: blocked
- Depends on: ARCH-4
- Scope:
  - codify canonical naming terms and singular/plural rules
  - align package metadata with repo identity
- Expected payoff: fewer naming mismatches and clearer ownership vocabulary


Quedó estable en `main`.

Resumen:
- `main` está limpio y sincronizado con `origin/main`.
- HEAD actual: `95f8b5c` — `docs: require plan/progress docs and frequent pushes`
- No hay cambios locales pendientes.

Lo último que se arregló en esa línea:
- `ce929a8` `fix club coaches schema drift fallback`
- `a51790c` `fix club coaches fallback messaging`
- `75e2812` `fix auth redirect and align contracts`
- `c713f97` `fix club coaches auth redirect`
- antes de eso también `129e317` `fix CI errors`

Estado práctico:
- no quedó una rama colgando de ese arreglo
- esos fixes ya están en `main`
- el backlog actual ya no apunta a “errores de main”, sino a:
  - `OPS-1` validación real de payments
  - `OPS-2` parity real de TVs

Si querés, hago una de estas dos:
1. te digo exactamente qué rompía `main` y cómo se corrigió commit por commit
2. levanto/verifico localmente que esas rutas críticas sigan bien ahora mismo (`/clubs/coaches`, auth, contracts, CI gates)


ops2 que es


`OPS-2` = cierre de paridad del runtime de TVs.

En concreto:
- verificar en dispositivo real que `/player/[screenId]` funcione bien con:
  - `CacheStorage`
  - reproducción vía `object URL`
  - refresh/manifest
  - telemetría básica
- capturar evidencia real
- actualizar `docs/streetcast-parity.md`

Objetivo de negocio:
- bajar el riesgo de que el player ande en desktop/dev pero falle en TVs o navegadores limitados.

Estado actual:
- ya existe export JSON de “parity snapshot” desde `/player/[screenId]`
- falta la prueba real en dispositivo y dejar evidencia en docs

Entregable esperado:
- 1 corrida real en TV/dispositivo
- evidencia guardada
- doc actualizada
- task marcada como cerrada

Si querés, te abro ahora el detalle exacto leyendo `docs/streetcast-parity.md` y te digo qué falta punto por punto.


la podes hacer de manera autonoma? necesitas playwright?


Sí, casi toda la puedo hacer autónomo.

No necesito Playwright para el núcleo.
`OPS-2` pide dispositivo real. Playwright sirve para apoyo, no para cerrar la incertidumbre principal.

Qué sí puedo hacer solo:
- revisar el player actual `/player/[screenId]`
- levantar entorno local
- validar flujo técnico en navegador local/headless
- comprobar snapshot JSON, manifest refresh, heartbeats, impressions, cache path
- detectar huecos antes de la prueba real
- dejar doc preparada y checklist exacto
- si hay bug reproducible local, corregirlo

Qué no puedo cerrar 100% sin hardware/ejecución real:
- comportamiento final en TV o navegador embebido/constrained
- evidencia real de `CacheStorage` + `object URL` en ese entorno

Cuándo usaría Playwright:
- para automatizar una pasada del runtime en Chromium
- para capturar consola/red/estado
- para validar que no rompimos el flujo base
Pero eso no reemplaza la prueba real.

Mi recomendación:
- yo hago ya la parte autónoma completa
- te dejo solo el último paso mínimo de evidencia real, idealmente 5–10 min en el dispositivo
- si todo da bien, cierro docs y estado

Si querés, arranco ahora con una auditoría de `OPS-2` y te digo:
1. qué ya está cubierto
2. qué falta
3. si hay algo para arreglar antes de probar en dispositivo real.


prefiero que primero dejes en la maquina bien configurado el uso de playwright en gral (fuera del repo) usando cli/skills lo que necesites. con su propia test suite. no reinventes la rueda igual si pido demas. recien ahi encara ops2 completamente. usa subagents


pwd && echo '---' && ls -la /home/sebas/.agents/skills && echo '---' && command -v playwright-mcp || true && command -v npx || true && node -v && pnpm -v


---
name: temporary-file-share
description: Expose a local directory or file briefly over HTTP for same-network or Tailscale download
---

# temporary-file-share

## Use When

- you need to fetch a file from a phone or another device quickly
- the file already exists locally and should stay in place
- a short-lived HTTP server is enough

## Workflow

1. Prefer serving the smallest useful directory, not `/`.
2. Verify the parent directory exists and the target file is present.
3. Start a detached HTTP server:
   - `sh -c 'nohup python3 -m http.server 8000 --bind 0.0.0.0 --directory "<directory>" >/tmp/file_share_http.log 2>&1 </dev/null &'`
4. Verify it is listening:
   - `ss -ltnp | rg ":8000"`
5. Give the user one or two direct URLs:
   - `http://100.116.176.16:8000/`
   - `http://100.116.176.16:8000/<filename>`
   - if relevant, also provide `http://ballbox-first.emperor-ratio.ts.net:8000/`
6. When the user confirms the download is done, stop the server:
   - identify the pid from `ss -ltnp | rg ":8000"`
   - `kill <pid>`
7. Verify the port is no longer listening.

## Rules

- default to port `8000` unless it is already in use
- do not move or rename the user's file just to share it
- prefer Tailscale IP or hostname over opening public exposure
- keep the server temporary; close it when the transfer is complete
- if the directory contains unrelated sensitive files, serve a narrower directory instead


# Personal Agent

## Communication

- Follow the system communication defaults.
- Preserve user intent and technical accuracy.
- Keep responses brief, clear, and action-oriented unless the user asks for more detail.
- **Pending validation:** confirm this communication mode auto-loads in every new Pi session.

## Intent

- Prioritize business impact.
- Reframe technical work toward the real objective.
- Ask only questions that change scope, risk, or success criteria.
- Execute fully once clarified.
- Keep the main thread focused.
- Use subagents for recon, parallel work, or context isolation when useful.
- Use Agents Database as durable shared memory, not just search.
- Save high-signal preferences, decisions, project facts, reusable artifacts, and concise handoff context when likely useful beyond the current chat.
- Prefer a few strong memories over many noisy ones.
- This Pi config repo is the main place to evolve these rules going forward.

## Rules

- Irreversible actions require explicit confirmation.
- Never merge or push to main without user confirmation.
- Keep responses direct and low-noise.
- Keep code blocks, commands, commits, and PR text in normal technical form unless the user asks otherwise.
- Point out contradictions when they matter.

## Machine Context

- **This machine is `ballbox-first`.**
- Do **not** SSH into `ballbox-first` for normal local work. You are already on it.
- This Raspberry Pi is effectively both workstation and server for Sebas's day-to-day work.
- "el servidor" usually refers to this same machine unless the user clearly means another host.

## Server Details

- Hostname: `ballbox-first.emperor-ratio.ts.net`
- Tailscale IP: `100.116.176.16`
- 24/7 machine
- Nginx on `:80` routes to other local services
- `personal-agent` API: `http://100.116.176.16:8082/api/status`
- `agents-database` API: `http://100.116.176.16:8091/api/status`

## Playwright

- `playwright-mcp` CLI available.
- Prefer headless Chromium.
- Avoid Firefox/WebKit unless needed.

## Telegram

Required vars:
- `TELEGRAM_BOT_TOKEN`
- `TELEGRAM_CHAT_ID`

Notify command:
```bash
~/.agents/skills/telegram-notify/telegram-notify "Message"
```


/mnt/rpi/repos/ballbox
---
lrwxrwxrwx 1 sebas sebas 46 Apr 11 16:22 /home/sebas/.agents/skills -> /mnt/rpi/repos/opencode-harness/.agents/skills
---
/usr/bin/npx
v22.22.0
10.33.0


subagent

Playwright machine setup recon

You are a specialized infra/setup agent. Be concise. Inspect this machine for existing Playwright or playwright-mcp related tooling, browser binaries, configs, and reusable test harnesses outside the repo. Recommend the smallest durable setup path with its own test suite, minimizing reinvention. Do not modify files. Return findings, risks, and a concrete setup plan.

Audit machine-wide Playwright/playwright-mcp setup outside /mnt/rpi/repos/ballbox. Check common dirs under /home/sebas, ~/.config, ~/.cache, ~/.local, and available CLIs. Find any existing reusable harness/test suite or global patterns. Recommend minimal durable setup with own tests and where it should live.

OPS-2 repo/task recon

You are a specialized product-engineering recon agent. Be concise. Inspect the repo docs/code for OPS-2 TV runtime parity closure, current evidence hooks, and what local automation can validate before a real-device run. Do not modify files. Return exact file pointers and a closure checklist.

Inspect /mnt/rpi/repos/ballbox for OPS-2 context. Read docs/streetcast-parity.md, docs/next-steps-queue.md, PLAN.md, and locate /player runtime code plus any snapshot/export tooling. Summarize what is already implemented, what can be automated locally, and what still requires a real device.