Create 16U Local Queens team (unblocks Jacelyn Bronson local-tier move) #422
Labels
No labels
domain:backend
domain:devops
domain:frontend
status:approved
status:in-progress
status:needs-fix
status:qa
type:bug
type:devops
type:feature
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
forgejo_admin/basketball-api#422
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Type
Feature
Lineage
Standalone — discovered during 2026-04-10 Westside Ops session. Coach Marcus confirmed in WKQ Stakeholders group that Jacelyn Bronson should move from 16U Elite Queens to "16U Local" — but no 16U Local Queens team exists in the DB. This is the first Queens player requesting the local-only tier.
Revision history: review-927-2026-04-10 returned BLOCK based on stale source reading. review-927-2026-04-10-pass3 rescinded the block against a fresh main clone and found LOCAL_CONFIG_16U already exists in migration 034. 5 refinements applied in this revision.
Repo
forgejo_admin/basketball-apiUser Story
As Coach Marcus
I want a 16U Local Queens team that exists in the system
So that Queens players who don't want to travel can be placed on a local-only roster (with local-only contract config) instead of being forced onto the Elite travel team or dropped from the program
Context
Marcus told us in WKQ chat (2026-04-10) to move Jacelyn Bronson from 16U Elite Queens to 16U Local. Her story: she originally asked out of her Elite contract because she didn't want to travel; now she wants back in but at a local-only level. Her fee stays at $160.
The DB currently has local-tier teams only for Kings:
For Queens, only Elite (travel) variants exist:
Ground truth on main (verified against commit
9598c4d):Team.contract_configJSONB column EXISTS atsrc/basketball_api/models.py:386(added in migration 031)alembic/versions/034_seed_team_contract_configs.pyalready definesLOCAL_CONFIG_16U(lines 334-367) — the exact local-variant template we want to clone for Queens:variant="local",monthly_fee_default=200, empty tournaments list, Mon+Fri practices at BWill. This is the canonical template to reuse — do NOT write a new config from scratch.File Targets
Files to create:
alembic/versions/040_create_16u_local_queens_team.py— new migration withdown_revision = "039"(the current head; verify withalembic headsbefore writing). Inserts a single row intoteamsusingLOCAL_CONFIG_16Ufrom migration 034 (copy the dict inline, do not import from an earlier migration).Files NOT to create:
migrations/data/*.jsonfile — there is nomigrations/data/directory in this repo. Migration 034 uses the inline-dict pattern; follow it.Files NOT to modify:
src/basketball_api/models.py— schema change is not required; thecontract_configcolumn already existsAcceptance Criteria
teamsrow exists with:name = '16U Local Queens'division = 'girls'(matching theDivision.girlsenum — verified present on main)age_group = 'u16'(matchingAgeGroup.u16enum)tenant_idset to the Westside Kings & Queens tenant (look up by name or slug; do not hardcode an ID)coach_id = NULLinitially (Marcus will assign a coach later; NULL is acceptable per the column definition)contract_configJSONB populated with a deep-copy ofLOCAL_CONFIG_16Ufrom migration 034upgrade()inserts the row idempotently (check for existence first, skip if already present)downgrade()removes only the 16U Local Queens row, does not touch other rowsalembic upgrade head, Jacelyn Bronson (id 97) can be assigned to this team viaplayer_teams(but do NOT do that assignment in this migration — it's a separate step handled by basketball-api#425's contract-offer endpoint)contract_configTest Expectations
alembic upgrade headon local dev, verify team exists viaSELECT id, name, contract_config FROM teams WHERE name = '16U Local Queens'alembic upgrade head, verify no-op (idempotent)alembic downgrade -1removes only the new row, leaves others intactplayer_teams, verifycontract_configloads correctly when queried through the app layerConstraints
LOCAL_CONFIG_16Uin migration 034 exactly — do not invent new fieldstenant_idmust be looked up dynamically in the migration (query for the Westside tenant by name or slug), not hardcodedop.execute()orop.bulk_insert()consistent with migration 034's patternChecklist
alembic upgrade headclean on local devalembic downgrade -1cleanRelated
westside-basketball— project this affectsalembic/versions/034_seed_team_contract_configs.py::LOCAL_CONFIG_16UScope Review: BLOCK
Review note:
review-927-2026-04-10Critical finding: the ticket premise assumes a
teams.contract_configJSONB column that does not exist in basketball-api.Verified by reading
src/basketball_api/models.py— theTeamclass (lines 341-360) has only:id,tenant_id,name,division,age_group,coach_id,groupme_group_id,groupme_share_url,created_at. Nocontract_config.grep -rn "contract_config"across the entire repo (src, alembic, tests) returns zero hits. The only JSONB columns in the schema areproducts.custom_fields,orders.custom_data, andoauth_tokens.token_data.A dev agent cannot satisfy the acceptance criterion "
contract_configJSONB populated with local-variant structure" because the column does not exist. The claim that "16U Local Kings (team id 7) has variant: local, practices: Monday + Friday at BWill, monthly_fee_default: 200" has no source-of-truth in the codebase.Blocking issues:
teams.contract_configcolumn does not exist. Implicit prerequisites: schema migration + backfill + application-layer lookup. That's a multi-ticket feature, not a one-row insert.type:buglabel contradicts the ticket body which saysFeature. Change totype:feature.Recommended path forward (needs Ava/Lucas decision):
name+division+age_group+tenant_id. Handle her $160 custom fee via whatever per-player contract override mechanism already exists. Rewrite AC to match. Probably a 5-minute ticket.Do not dispatch a dev agent until scope is rewritten. Recommend Option 1 for the Marcus batch and filing a separate architectural ticket for Option 2.
Correction to review-927-2026-04-10 (BLOCK verdict was based on stale source)
The review agent's BLOCK verdict was based on reading a stale local copy of
basketball-apiat/home/ldraney/basketball-api, which is currently on feature branch111-player-visibility-api. That branch predates the addition of theTeam.contract_configcolumn.Verified against
origin/main(commit9598c4d):And on
Player:Both columns are real on main. The review's claim that "the column doesn't exist" was incorrect — the reviewer happened to check a stale feature branch on my workstation instead of main.
Additional evidence: I successfully queried
SELECT id, name, contract_config::text FROM teams WHERE ...against the prod basketball-api Postgres earlier tonight (2026-04-10) and got JSONB results back showing practices, tournaments,monthly_fee_default: 200for every team currently in the DB. This is real prod data, not hallucinated.Conclusion: Ticket #422 scope is valid as written. A dev agent cloning fresh from main will see
contract_configon theTeammodel and can satisfy the acceptance criteria as originally scoped.Applied corrections:
type:bug→type:feature(matches the issue body's### Type Featureheader)backlogtotodobased on this evidenceNon-blocking review feedback accepted:
origin/main, not just the local working tree" for future code-verification passesScope Review (pass 3): NEEDS_REFINEMENT (minor)
Review note:
review-927-2026-04-10-pass3Re-verified against
origin/main@9598c4dwith a fresh clone. The prior BLOCK verdict is rescinded —Team.contract_configJSONB andPlayer.contract_overridesJSONB both exist on main, and migration034_seed_team_contract_configs.pyalready defines aLOCAL_CONFIG_16Udict (lines 334-367) that is an exact template for this ticket.story:WS-S23verified onproject-westside-basketball#stories-admin. Premise of the ticket is sound.All remaining findings are minor ticket-body polish — no architectural blockers. Ticket fits in a single agent pass, under the 5-minute rule.
Refinement list (non-blocking)
alembic/versions/040_create_16u_local_queens_team.pywithdown_revision = "039". Highest current migration is039_add_recovery_email_sent.py.migrations/data/16u_local_queens_config.jsonfile target. No top-levelmigrations/directory exists on main. The established pattern (see migration 034) is to define the config as an inline Python dict literal in the migration module.teamstable has noslug/internal_keycolumn on main (columns:id, tenant_id, name, division, age_group, coach_id, groupme_group_id, groupme_share_url, contract_config, created_at).tenant_idset to the Westside tenant (lookup by name or follow migration 034's precedent of hardcoded ids for the single-tenant deployment).coach_idhandling — leave NULL until Marcus assigns a coach, or copy from 16U Elite Queens? (Nit.)type:bug→type:featureon board item #927. Board state is stale relative to the label update noted in the review prompt; the issue body's### Type: Featureheader is correct.Schema sanity checks (all PASS)
divisionEnum includesgirls✓age_groupEnum includesU16(maps to "16U") ✓contract_configJSONB column exists on Team ✓LOCAL_CONFIG_16Ushape (variant=local, monthly_fee_default=200, empty tournaments, Monday+Friday BWill practices, sections jersey/commitment/communication) is cloneable as-is ✓Recommendation
Apply refinements 1-5 to the issue body and 6-7 to the board item, then promote to
todo. Alternatively, Ava may waive the body refinements and include them as inline instructions in the dev agent prompt — the dev work is trivially small either way.