<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
## Summary
Mounts Financials ??? CAPEX at /dashboards?tab=financials&sub=capex, composing the typed all-site summary table, clean-grain DDR-vs-booked chart, and AERIE-1113 entity tie-out inside the existing Financials shell (school filter + coherent Refresh).
## Changes
- Add capex to Financials sub-tab type/URL validation, context-panel nav, layout routing/labels, and capability mapping (reuses financials.schoolPl.read; no new capability).
- Add CapexView + pure presentation helpers (capex-summary.ts): sortable/filterable table, quality badges/notes (MIXED, non-isolable, unresolved mapping, NS-TB-without-QB, no-current-close-TB), chart eligibility at ddr >= $500_000 with the exact clean-row predicate, selected-close account-11500 TB wording.
- Live loading via useCapexSummaryLive / useCapexEntityTieoutLive (useLiveSection); Refresh refetches both without a request loop.
- Reuse Aerie Financials tokens and var(--color-chart-*) for the recharts horizontal chart ??? no CAPEX-only palette.
## Tests
- Pure helpers: threshold/eligibility, quality notes, sort/filter, pct bar clamp (capex-summary.test.ts).
- Chart: clean-row-only rendering + empty status (capex-ddr-vs-booked-chart.test.tsx).
- CapexView: loading/error/retry, refresh coherence, school filter, sort, capability deny (capex-view.test.tsx).
- Live hooks + navigation/capability: summary hook, tie-out enabled gate, URL/sub-tab, context panel CAPEX visibility.
- pnpm typecheck (chat) + biome check on changed files ??? pass (pre-commit).
## Verification
Live browser verification passed against Redshift at /dashboards?tab=financials&sub=capex (1680?1050): 38 summary rows, 30 tie-out rows, 26 degraded rows, SELECT privilege true on all three CAPEX marts, and zero load failures.
- Filters, configurable DDR threshold, split Attribution/Mapping/Coverage columns, suppressed degraded comparisons, short chart labels, issue references, simplified tie-out rows, KPI reconciliation insights, sorting, and Refresh were exercised.
- CAPEX tests: 88/88 pass; typecheck and Biome pass.
- [Full CAPEX tab](https://cursor.com/agents/bc-eff21704-f125-4d8a-bda3-71f3274dd26e/artifacts?path=%2Fopt%2Fcursor%2Fartifacts%2Fcapex-tab-full.png)
- [Degraded/quality rows](https://cursor.com/agents/bc-eff21704-f125-4d8a-bda3-71f3274dd26e/artifacts?path=%2Fopt%2Fcursor%2Fartifacts%2Fcapex-quality-row.png)
- [Tie-out and coverage](https://cursor.com/agents/bc-eff21704-f125-4d8a-bda3-71f3274dd26e/artifacts?path=%2Fopt%2Fcursor%2Fartifacts%2Fcapex-tieout-coverage.png)
## Risks / follow-ups
- Parks for human merge.
- No AERIE-1115 transaction drilldown; no new capability.
- Live MIXED-row / coverage-card screenshot evidence blocked until Redshift SELECT grants land for the cloud-agent warehouse user.
## Out of scope
- Transaction drilldown, new Redshift marts/actions, new capability keys, auto-merge.
<sub>To show artifacts inline, <a href="https://cursor.com/dashboard/cloud-agents#team-pull-requests">enable</a> in settings.</sub>
## Verification artifact
Browser verification: pass
Live CAPEX at /dashboards?tab=financials&sub=capex with 12 clean vs 38 all sites; new mode toggle (Clean comparisons / All sites) drives muted-bar all-cohort view — verified with live Redshift rows, 0 console errors, current_user redacted, has_table_privilege true on all three CAPEX marts.
Screenshots:





<!-- CURSOR_AGENT_PR_BODY_END -->
<div><a href="https://cursor.com/agents/bc-05db9391-f1f5-41eb-9746-a0725d6c8a31?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a> <a href="https://cursor.com/background-agent?bcId=bc-05db9391-f1f5-41eb-9746-a0725d6c8a31&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img alt="Open in Cursor" width="131" height="28" src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a> </div>
## Browser verification
### Boot
- From the repo root run pnpm dev-local; wait for http://localhost:3000.
- Chromium and Playwright are already installed by the Aerie cloud setup.
- Preserve the newly injected shell REDSHIFT_* runtime secrets when booting local Convex; do not overwrite them with stale .env.local or aerie/dev values, and never print secret values.
### Auth
- Use the established Aerie storage-state replay or mint a fresh Clerk session if the captured JWT expired.
- Verify the authenticated role has financials.schoolPl.read.
### Flow
1. Before browser assertions, query current_user and has_table_privilege for all three CAPEX marts; report the non-secret username and booleans. Live SELECT access is required.
2. Navigate to http://localhost:3000/dashboards?tab=financials&sub=capex.
3. Confirm CAPEX nav is active and loading settles without visible or console errors.
4. Verify populated summary table columns, a visibly degraded/MIXED row, and selected-close NetSuite TB wording.
5. Verify the horizontal chart includes only clean rows with DDR >= $500,000 and sampled values agree with the table.
6. Verify the entity tie-out table and both coverage cards contain live rows.
7. Exercise table sorting or school filtering and Refresh; both sections must settle without duplicate request loops.
8. Compare the page with adjacent Financials tabs for semantic theme tokens, spacing, typography, chart palette, focus, and responsive consistency.
### Screenshots to capture
- capex-tab-full.png - full mounted table and chart.
- capex-quality-row.png - populated MIXED or degraded row and explanation.
- capex-tieout-coverage.png - populated tie-out and coverage cards.
### Pass criteria
- Fixture-only or permission-denied UI evidence is not a pass. The mounted flow must load live CAPEX rows using the injected Redshift credentials.
- Publish durable screenshot links, route, viewport, interactions, console result, current_user, and privilege booleans in the Verification artifact. Never publish credential values.
### Current-head capture guidance
- If pnpm dev-local requests Convex login, use the proven anonymous local path: create/select the local deployment with CONVEX_AGENT_MODE=anonymous, then push functions and start Next.
- Set REDSHIFT_HOST, REDSHIFT_PORT, REDSHIFT_DATABASE, REDSHIFT_USER, REDSHIFT_PASSWORD, LEGACY_EDUCATION_WAREHOUSE_READS_ENABLED=true, and the Clerk issuer on the local Convex deployment without printing values.
- If stored Clerk state is expired, mint a fresh sign-in ticket for the same test user and grant a seeded role carrying financials.schoolPl.read in the disposable local deployment.
- CAPEX scrolls inside its own content container. Capture the inner CAPEX scroll region in stitched sections or locator screenshots; do not rely on Playwright fullPage, which produces mostly empty space.
- Ensure the final screenshots clearly show: executive/attention summary and table, expanded lineage/quality details, chart labels and filters, tie-out KPIs/largest differences/table.