Review: T5: data-driven page.server.ts + merge logic
Verdict: READY
Template Completeness
- [x] Type — Feature
- [x] Lineage — sub-ticket of westside-contracts#34, wave 2
- [x] Repo — forgejo_admin/westside-contracts
- [x] User Story — clear "contract page loads structured config and merges team defaults with player overrides"
- [x] Context — thorough, includes all 7 merge rules
- [x] File Targets — 2 modify targets + explicit exclusion list
- [x] Acceptance Criteria — 8 testable criteria
- [x] Test Expectations — 5 unit tests + run command
- [x] Constraints — pure function extraction, backwards compat, type alignment
- [x] Checklist — present
- [x] Related — parent issue + basketball-api dependencies listed
Traceability
- [x] story:WS-S23 — "As an admin, I want to configure custom contract terms per player (different fee, tournaments, practice schedule) so that custom deals render correctly without code changes"
- [x] story note verified — found in project-westside-basketball user-stories section under Admin (Marcus)
- [x] arch:contracts — contracts architecture component
- [x] arch note verified — arch-contracts-westside-basketball exists in pal-e-docs (has Config Merge Logic, Custom Deals, Data Model, Contract Variants sections)
- [x] Forgejo issue — westside-contracts#36, open
File Targets
- [x]
src/routes/contract/[token]/+page.server.ts— verified: exists (47 lines), currently does simple JOIN query with isLocal/isGirls derivation from team_name. No contract_config or contract_overrides columns yet. Ticket accurately describes current state. - [x]
src/lib/types.ts— verified: exists (27 lines), has Player and SignRequest interfaces. No ContractConfig types yet. Ticket correctly identifies this as target for new interfaces. - [x]
src/lib/contract-config.ts— does not exist yet (new file per Constraints section for pure merge function). Parent directorysrc/lib/exists. Correct create target.
Repo Placement
OK. Issue filed on westside-contracts, all file targets are in westside-contracts. The basketball-api migration dependencies (#319, #321) are correctly filed as separate issues on that repo. No cross-repo work in this ticket.
Dependencies
- [x] basketball-api #319 (contract_config JSONB on teams) — board item #772, currently in qa. Must be merged and migration applied before this ticket's SQL can reference the column. Pending.
- [x] basketball-api #321 (contract_overrides JSONB on players) — board item #773, currently in qa. Same dependency. Pending.
- [x] #774 (T3: seed team configs + audit player overrides) — wave 2 peer, in backlog. Provides test data but not a code dependency.
- [x] #775 (T4: extract Svelte components) — wave 1, in qa. Not a direct dependency (this ticket is server-side only).
Wave 1 dependencies (#772, #773) are in qa — not yet merged. Execution should wait until both migrations land, but the ticket scope itself is correct and reviewable now.
Acceptance Criteria
All 8 criteria are verifiable by an agent:
- SQL column presence — grep-checkable after implementation
- Merge function behavior (5 criteria) — unit-testable via the 5 specified test cases
- NULL fallback — unit-testable
- TypeScript check —
npm run check
Run command specified:
npm test && npm run check. Adequate and executable.Blast Radius
isLocal/isGirlsare consumed by +page.svelte (rendering) and sign/+server.ts (contract_version derivation). This ticket only changes +page.server.ts load function — the page still receives isLocal/isGirls. Additive change (newconfigfield).- The sign endpoint (explicitly excluded) has its own isLocal/isGirls derivation — updating it is ticket #778 (wave 3).
- Component wire-up to consume config instead of hardcoded HTML is ticket #777 (wave 3).
- No blast radius concerns. Change is additive and backwards compatible.
Decomposition Assessment
Apply three-thing limit and five-minute rule:
- File targets: 2 modify + 1 create = 3 files, 1 repo. At the limit but cohesive.
- Acceptance criteria: 8 AC — above the 5 guideline, but 5 of them are unit test variations of the same merge function. Logically 3 discrete changes: (1) update SQL query, (2) write merge function + types, (3) wire merge into load return.
- Estimated agent time: ~4 minutes. Query change is small, merge function is well-specified with clear rules, types follow from the merge rules.
- Independent subtasks: No — the merge function, types, and query update are tightly coupled.
No decomposition needed.
Recommendation
No action needed. Ticket is ready for execution once wave 1 dependencies (#772, #773) clear qa.