Closes architecture baseline finding F4. Every component now exposes its Public API through `src/<component>/index.ts`; cross-component imports go through the barrel. `scripts/check-arch-imports.mjs` plus `STC-ARCH-01` in the static profile enforce the rule; tests in `tests/architecture_imports.test.ts` cover AC-4/AC-5 + 2 exemption cases. One F3-pending exemption (`classColors`) is documented in 5 places (barrel, consumer, script, doc, test) to avoid a circular import. Phase B cycle 1 batch 1 of 2 (epic AZ-447). Batch 2 is AZ-486 (endpoint builders) — blocked on this commit landing. Co-authored-by: Cursor <cursoragent@cursor.com>
9.8 KiB
Batch Report
Batch: 09 (Phase B cycle 1, batch 1 of 2)
Tasks: AZ-485 (Public API barrels + STC-ARCH-01)
Date: 2026-05-11
Cycle: Phase B feature cycle, Step 10 — Implement
Total complexity: 5 pts
Epic: AZ-447 (01-testability-refactoring)
Closes: architecture baseline finding F4 (_docs/02_document/architecture_compliance_baseline.md)
Task Results
| Task | Status | Files Modified / Added | Tests | AC Coverage | Issues |
|---|---|---|---|---|---|
| AZ-485_refactor_public_api_barrels | Done | 11 new barrels (src/{api,auth,components,hooks,i18n}/index.ts, src/features/{login,flights,annotations,dataset,admin,settings}/index.ts); 1 new script (scripts/check-arch-imports.mjs); 1 new test (tests/architecture_imports.test.ts); 1 modified runner (scripts/run-tests.sh — STC-ARCH-01 wired in); 17 production import sites migrated to barrel paths (App.tsx + every feature page + every src/components/ consumer); 22 test/colocated test import sites migrated; 1 doc (_docs/02_document/module-layout.md) — Layout Rules #3 rewritten, Verification Needed #3 closed, every component's Public API line points to its barrel |
4 new architecture tests in tests/architecture_imports.test.ts (AC-4 / AC-5 + 2 exemption cases); fast profile re-baselined from 163 → 167 passes (no regressions) |
7 / 7 ACs covered | One F3-pending exemption carried forward: src/features/annotations/classColors is imported directly (not through the 06_annotations barrel) to avoid a circular import; documented in the barrel, the consumers, the static check, the module-layout doc, and the new test |
AC Test Coverage: All 7 ACs covered
| AC | Where | Profile | Status |
|---|---|---|---|
| AC-1 — Every component has a barrel exposing only its Public API | src/<component>/index.ts × 11 vs module-layout.md Per-Component Mapping → Public API |
static (manual cross-check in self-review) | PASS — each barrel's re-export list matches the documented Public API line one-for-one; no internal-only symbol leaks |
| AC-2 — No cross-component deep imports remain in production code | scripts/check-arch-imports.mjs scanning src/ |
static (STC-ARCH-01) |
PASS — 0 deep imports outside the documented F3 exemption |
| AC-3 — No cross-component deep imports remain in tests | same script scanning tests/ + e2e/ |
static (STC-ARCH-01) |
PASS — 0 deep imports outside the documented F3 exemption |
| AC-4 — Static gate fails on a newly-introduced deep import | tests/architecture_imports.test.ts AC-4: FAILS when a deep import... + AC-4: deep imports inside line comments do not trip the gate |
fast | PASS — the synthetic fixture (tests/_arch_fixtures/synthetic_deep_import.ts) flips the script to exit non-zero and emits STC-ARCH-01 — ... on stderr |
| AC-5 — Static gate passes on the migrated codebase | tests/architecture_imports.test.ts AC-5: passes on the migrated codebase + STC-ARCH-01 run in the static profile |
fast + static | PASS — exit code 0, stderr empty |
| AC-6 — Fast profile remains green | bash scripts/run-tests.sh (static + fast) |
static + fast | PASS — 167 / 13 / 0 (baseline was 163 / 13 / 0 + 4 new architecture tests); 0 regressions |
| AC-7 — module-layout.md reflects the new convention | _docs/02_document/module-layout.md Layout Rules #3 + Verification Needed #3 + Conventions table + every component's Public API line |
manual review | PASS — Rule #3 names the barrel as the Public API, names STC-ARCH-01 as the enforcing gate, and the F3-pending exemption is documented inline; Verification Needed #3 marked closed by AZ-485 |
Design Decisions
- Single source of truth for the static check —
scripts/check-arch-imports.mjsmirrors the existingscripts/check-banned-deps.mjspattern (AZ-482). The bash functionstatic_check_no_cross_component_deep_importsinscripts/run-tests.shis a one-line delegate. The new unit test invokes the script directly withspawnSync, so a regex regression in the script trips the test even if the bash glue still reports PASS. - classColors exemption is structural, not stylistic — Re-exporting
classColorssymbols through the06_annotationsbarrel creates a runtime circular import (AnnotationsPage → DetectionClasses → 06_annotations barrel → AnnotationsPage) that materializes asFALLBACK_CLASS_NAMES === undefinedinsideDetectionClasses. The exemption is documented in five places (the barrel file, the consumer file, the static-check script'sEXEMPT_REcomment,module-layout.mdLayout Rule #3, and the architecture test) so it cannot be forgotten when F3 lands. 10_app-shellintentionally has no barrel — The component is a collection of root-level files (App.tsx,main.tsx,index.css,vite-env.d.ts) never imported as a unit. STC-ARCH-01's component allowlist (api|auth|components|features/[a-z-]+|hooks|i18n) intentionally omits app-shell; the doc records this explicitly.- Test-file deep-import string concatenation —
tests/architecture_imports.test.tsbuilds its synthetic offending strings via concatenation ('fr' + 'om','..' + '/..') so the scanner does not flag the test source itself when it walkstests/. The fixtures created at runtime go undertests/_arch_fixtures/and are torn down inafterEach.
Code Review Verdict: PASS
Self-review (implement skill Step 9 / 10), applied to the 13 new + 17 production + 22 test + 1 runner + 1 doc + 1 script changes:
- 0 Critical, 0 High, 0 Medium, 0 Low findings.
- Scope discipline: every modified file is one of (barrel author, deep-import consumer, static-check author, doc author). The 4 originally-untracked-and-edited test files (
annotations_endpoint,destructive_ux,form_hygiene,overlay_membership) are pre-existing committed test files where the only edit is import-path migration. - No silent error suppression:
check-arch-imports.mjswrites the full hit list to stderr before exiting non-zero; the bash delegate propagates the exit code;run-tests.shrecords the failure into the static CSV. - Single-responsibility: each barrel re-exports its component's documented Public API only.
check-arch-imports.mjshas one job (detect cross-component deep imports). The new test exercises only that script. - No new dependencies:
check-arch-imports.mjsuses Node stdlib (fs,path,url) only. The architecture test uses Vitest + Node stdlib. - Architecture compliance (Phase 7): no layer-direction violations introduced; the only cross-feature edge (
07_dataset → 06_annotationsforCanvasEditor, F2) is grandfathered exactly as before —CanvasEditoris intentionally re-exported through the06_annotationsbarrel so the consumer is barrel-compliant. STC-ARCH-01 confirms no new cyclic dependencies.
Auto-Fix Attempts: 1
One auto-fix loop entered during Phase 3 (test import migration):
- Symptom:
tests/detection_classes.test.tsxfailed withTypeError: Cannot read properties of undefined (reading 'map')afterFALLBACK_CLASS_NAMESwas migrated to import through the06_annotationsbarrel. - Diagnosis: barrel-induced circular import —
AnnotationsPage → DetectionClasses → 06_annotations barrel → AnnotationsPage. The barrel module evaluated beforeclassColorsexports were bound, so the symbol resolved toundefined. - Fix: remove
classColorsre-exports from the06_annotationsbarrel, document the F3-pending exemption in five places (see Design Decision #2), point the consumer + the test back at the direct pathsrc/features/annotations/classColors. - Validation: fast profile back to green; STC-ARCH-01 unit test added an exemption case (
AC-4: still PASSES when only the classColors F3-pending exemption is used) so the carve-out is regression-tested.
Stuck Agents: None
No multi-pass investigations beyond the auto-fix above.
Test Run Summary
bun run test:fast(viabash scripts/run-tests.sh) — 27 files / 167 passed / 13 skipped / 21.11 s wall (+4 new tests vs Phase A close at 163; 0 regressions).bash scripts/run-tests.sh --static-only— 30 / 30 static checks PASS (addedSTC-ARCH-01; no regressions in the existing 29).node scripts/check-arch-imports.mjs(direct invocation) — exit 0, stderr empty on the migrated codebase; exit 1 on every synthetic fixture in the architecture test.ReadLints— clean on all 13 new files.git diff --stat— 41 modified + 13 new files; +113 / -99 net lines; mostly mechanical one-line import path edits.
Documented Drifts (cumulative across batch)
| Drift | Where | Spec/AC affected | Resolves when |
|---|---|---|---|
classColors symbols cannot flow through the 06_annotations barrel due to a circular import |
src/features/annotations/index.ts (export omitted by design); 5 cross-doc mentions |
F3 (Medium / Architecture) — architecture_compliance_baseline.md |
F3 moves classColors.ts out of 06_annotations into its own component directory (src/shared/classColors.ts or a dedicated 11_class-colors directory); F3 closes by adding a src/<new-home>/index.ts barrel and removing the STC-ARCH-01 exemption |
(No other drifts surfaced.)
Phase B Cycle 1 Status
This is batch 1 of 2 in Phase B cycle 1 (the cycle covers baseline findings F4 + F7 under epic AZ-447). Batch 2 will implement AZ-486 — endpoint builders in src/api/endpoints.ts + STC-ARCH-02 for hardcoded /api/<service>/… paths — which depends on this batch landing first (endpoints ships through the new src/api barrel; Jira "Blocks" link AZ-485 → AZ-486).
Next Batch
AZ-486 (5 pts) — endpoint builders + STC-ARCH-02. Spec already in _docs/02_tasks/todo/AZ-486_refactor_endpoint_builders.md.