You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Check CI status (could not run tests/lint locally — see note below)
Post final review
This is a clean, well-scoped slice of #30. It sticks to the stated boundaries (no route migration, no analytics/chart changes, Player nav left out until there's a real destination), and the architecture fits AGENTS.md: navigation.py stays a plain typed builder, presentation logic stays in app/web/templates, and no generic "framework" was introduced for a two-group taxonomy.
Strengths
app/web/navigation.py:41 adds group: Literal["Offense", "Pitching", "Results"] to NavLink instead of a bare str — keeps the domain typed per the type-safety rules, and a typo in a group name would be a type error, not a silent no-op in the template.
team_base.html cleanly separates the entity-neutral shell (base.html) from the Team-specific scaffold, which sets up a Player shell later without copying Team assumptions — matches the "small focused modules" guidance.
build_nav_links (app/web/navigation.py:44) always returns all 8 links regardless of team_id/season, so team_base.html's nav_links[0].href (used for the "Teams" primary-nav link) can never index into an empty list — checked both the "empty"/"not_found" and schema-missing paths in routes.py:1040-1168, and only error.html (which uses default base.html, no Team context) skips the Team nav entirely.
Test coverage is a real strength here: tests/test_web_page_scaffolding.py's new NavigationParser (an HTMLParser subclass) replaces a regex-based nav scraper and asserts on landmark labels, aria-current semantics, group headings, skip-link target, and main id — a meaningfully stronger contract than counting substring matches. The new test_reimport_states_keep_team_navigation case also protects the 409 conflict path, which is easy to regress silently.
Relabeling ("Runs" → "Runs Scored", "Comparison" → "Hits vs Batting Strikeouts") is consistently propagated through navigation.py, all dependent templates, and every test that asserted on the old label text — nothing was left referencing the stale strings (confirmed via grep).
docs/ui-information-architecture.md documents the actual design decision (why Comparison is grouped under Offense, why Players stays hidden, the shell/team_base split) rather than restating the visible markup — in the spirit of the "why over what" documentation guidance.
Minor observations (non-blocking)
_team_navigation.html:3 hardcodes the group order/list ("Offense", "Pitching", "Results") separately from the Literal in navigation.py:41. Small duplication, but if a fourth group is ever added, both places need updating in lockstep — worth a one-line comment noting the coupling, or leave as-is since three static groups is unlikely to churn (AGENTS.md's "small amount of obvious duplication over premature abstraction" guidance applies fine here).
The aria-current="location" value on the "Teams" primary-nav link (team_base.html:5) is a valid ARIA 1.1 token but less common than page/true; worth a quick screen-reader spot check since it's new to this codebase, but the semantics (a link to the current section, not the current document) are correctly chosen over aria-current="page".
_team_navigation.html and team_base.html are new small template files rather than one file — consistent with "module ownership" guidance (nav markup owns navigation, the scaffold owns layout), not a concern.
Not verified
I was not able to run poetry run pytest, ruff check, or ruff format --check in this sandbox (the tool approval for poetry run … was declined). CI's Test workflow run (36147456910) reports success for this branch, which covers the test-suite requirement; formatting/linting should still be double-checked with poetry run ruff check . and poetry run ruff format --check . before merge if those aren't part of that same CI job.
No functional or architectural issues found. Nice, disciplined slice.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements the first focused UI-architecture slice of #30.
team_id,season, andwindowacross navigationNavigation
Offense
Pitching
Results
Compatibility
No route migration is included.
Existing URLs remain:
Existing selector behavior, error states, completeness semantics, and DB-only browser rendering are preserved.
Scope intentionally excluded
/teams/*URL migrationCloses part of #30.