March 15: Infrastructure Day
Massive infrastructure session — 15 PRs merged spanning Vite 8 migration, test infrastructure overhaul, 80+ lint fixes, and the first UX sprint feature landing. The codebase is cleaner than it's been in weeks.
Developer Journal
Vite 7 → 8 migration
The dependabot PR (#813) for Vite 8 had been sitting with CI failures. Turned out to be two issues: the @vitejs/plugin-react major bump needed to come along with it (#830), and the Docker Alpine container was missing the new @rolldown/binding-linux-arm64-musl native binary that Vite 8 introduced (#833). Vite 8 swaps esbuild for rolldown under the hood — faster builds, but the native bindings need to match the container's architecture and libc. Added the musl binaries to package.json optional dependencies and the Docker frontend came back to life.
Also discovered during the compliance check that the docker_frontend_node_modules named volume was stale — it had been populated before #833 merged, so the container kept crash-looping even after the fix was on main. Deleting the volume and rebuilding fixed it. A good reminder that Docker named volumes persist across rebuilds.
UX sprint progress
Three UX fixes landed today:
Navigation wayfinding (#828, closes #671): Added a 2px blue underline to active nav links, page titles and document.title on all main pages, selection count in the floating bar, and a labeled view mode toggle. Found and fixed a pre-existing dead-code bug where the composite button never applied its ready CSS class.
Design token migration (#832): Migrated hardcoded hex colors to design tokens across the codebase. No visual change — the tokens resolve to the same values — but it means the theme system actually works now.
Spectrum button fix (#831): The Spectrum viewer button was gated on isViewable, which meant spectral FITS files that couldn't render as images also couldn't open in the spectral viewer. Decoupled the check.
Archive feedback and toast behavior (#842, closes #679)
The archive button had a barely-visible opacity pulse (0.7→0.4) that users couldn't see on dark backgrounds. Replaced it with the button text changing to "Archiving..." plus a disabled state. More importantly, added success toasts for archive/unarchive — previously these actions were completely silent on success.
Also standardized toast duration across the app: success and info toasts auto-dismiss after 4 seconds, error toasts persist until manually dismissed. Previously all toasts used the same duration, which meant errors would vanish before users could read them.
Test infrastructure overhaul
Three back-to-back test PRs that significantly expanded coverage:
Unit tests (#834): Added tests for MosaicService, SemanticSearchService, and DataScanService. Coverage for the processing pipeline's service layer.
Integration tests (#835): Added tests for MongoDBService (the largest test file at 2200+ lines), MastController security validation, and background workers (JobReaperBackgroundService, StartupScanBackgroundService).
E2E mock server (#837): Replaced the real processing engine with a mock HTTP server in E2E tests. The mock responds instantly with valid but minimal payloads, which means E2E tests no longer depend on the processing engine being healthy or fast. Combined with #827 (doubling Playwright workers to 6), E2E reliability and speed improved dramatically.
E2E repairs (#838): Fixed 8 failing E2E tests — file selection, button state assertions, and viewer tolerance thresholds that had drifted.
80+ StyleCop lint fixes (#839)
The compliance check (/compliance-check full) caught what CI missed: 80+ StyleCop violations across test files from #834 and #835. CI doesn't use --warnaserror, so these shipped as warnings. Fixed all of them — member ordering (SA1202, SA1204), comment whitespace (SA1512, SA1515), parameter formatting (SA1116/SA1117), doc comment text (SA1623/SA1642), and exception specificity (CA2201). All structural fixes, zero suppressions.
This exposed a gap in the self-review process: the code-reviewer agent checks logic and security but doesn't run the linter. Added a new rule: run Tier 1 lint checks (backend --warnaserror, frontend lint/format/types, Python ruff) before the first push. Effectively the compliance check's fast tier as a pre-push gate.
Lint warning cleanup (#841)
Suppressed the last 3 ESLint warnings — console.log/console.table in the window.jwst debug utilities. These are intentional (the functions exist to print to the console), so inline eslint-disable-line with explanations. Created issue #840 to remove the debug helpers entirely before the v1 community release. Frontend lint is now 0 errors, 0 warnings.
What shipped
| PR | Title |
|---|---|
| #827 | perf: increase E2E Playwright workers from 3 to 6 |
| #828 | fix: improve navigation wayfinding with stronger active states and page context |
| #830 | chore: upgrade vite 7→8 and @vitejs/plugin-react 5→6 |
| #831 | fix: enable Spectrum button for spectral files regardless of isViewable |
| #832 | fix: migrate hardcoded colors to design tokens |
| #833 | fix: add musl Linux binaries for Vite 8 Alpine Docker support |
| #834 | test: add unit tests for MosaicService, SemanticSearchService, DataScanService |
| #835 | test: add tests for MongoDBService, MastController, and background workers |
| #837 | test: replace processing engine with mock server in E2E tests |
| #838 | fix: repair 8 failing E2E tests |
| #839 | fix: resolve 80+ StyleCop lint errors across backend tests and services |
| #841 | chore: suppress no-console lint warnings in debug utilities |
| #842 | fix: improve archive feedback and toast duration behavior |
Issues created
| Issue | Title |
|---|---|
| #840 | chore: remove window.jwst debug helpers before community release |
Compliance check
Full compliance check passed clean after all merges:
- 2,969 tests passing (1019 backend + 868 frontend + 953 Python + 129 E2E)
- 0 lint warnings across all three layers
- All coverage thresholds met (Python 67%, backend 42.5%, frontend 42.9%)
- 0 dependency vulnerabilities
- All 6 Docker services healthy