mirror of
https://github.com/azaion/ui.git
synced 2026-06-22 04:41:10 +00:00
[AZ-511] classColors carve-out to src/class-colors/ (closes F3)
Move src/features/annotations/classColors.ts to its own component directory src/class-colors/ with a proper barrel; update the 4 consumer imports to go through the barrel; remove the F3-pending exemption from STC-ARCH-01 and from the architecture test fixture; clean up the 5 coupled doc/script touchpoints. Closes baseline finding F3 and retires the 5-coupled-places carry-over surface logged in LESSONS.md 2026-05-12. - Add `class-colors` to scripts/check-arch-imports.mjs COMPONENT_DIRS so deep imports past the new barrel are caught symmetric to every other component. - Replace the architecture test "exemption WORKS" fixture with the stronger "deep import into class-colors NOW FAILS" assertion (Risk 4 mitigation). - module-layout.md: Layout Rules + Per-Component Mapping (11_class-colors, 06_annotations, 03_shared-ui) + Verification Needed #1 + shared/class-colors block all updated to reflect the new home. - 11_class-colors/description.md: Caveats §7 + Module Inventory updated. - architecture_compliance_baseline.md: F3 marked CLOSED with full pre-resolution context preserved (mirrors AZ-485/F4 + AZ-486/F7 pattern); F4 carry-forward exemption note retired. - 04_verification_log.md: open questions #1 + #8 marked RESOLVED. - Build passes with no circular-import warnings (AC-4); fast suite 231/13 skipped green (AC-5); static profile green (AC-3 — zero exemptions remain). Batch report: _docs/03_implementation/batch_14_cycle3_report.md Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,167 +0,0 @@
|
||||
# Carve classColors.ts out of 06_annotations into its own component dir
|
||||
|
||||
**Task**: AZ-511_classcolors_carve_out
|
||||
**Name**: classColors carve-out to dedicated component (closes F3)
|
||||
**Description**: Move `src/features/annotations/classColors.ts` to its own component directory `src/class-colors/` with a barrel; update the four consumer import paths to go through the barrel; remove the STC-ARCH-01 F3-pending exemption; clean up the five coupled documentation/script callouts. Closes the High Architecture baseline finding F3 and eliminates the carry-forward exemption surface logged in `LESSONS.md` ("5 coupled places").
|
||||
**Complexity**: 3 points
|
||||
**Dependencies**: AZ-485 (Public API barrels + STC-ARCH-01) — the F3 exemption only exists because AZ-485 landed; this task lives on top of that boundary.
|
||||
**Component**: 11_class-colors (gains a physical home); 06_annotations (loses the misplaced file from its owns-glob); 03_shared-ui (consumer); plus three doc/script artifacts.
|
||||
**Tracker**: AZ-511
|
||||
**Epic**: AZ-509
|
||||
|
||||
## Problem
|
||||
|
||||
Baseline finding **F3** (`_docs/02_document/architecture_compliance_baseline.md`): `src/features/annotations/classColors.ts` is a Layer 0 / 1 shared kernel logically owned by component `11_class-colors`, but it physically sits inside `06_annotations`'s owns-glob. Re-exporting it through the `06_annotations` barrel would create a runtime circular import:
|
||||
|
||||
```
|
||||
AnnotationsPage → DetectionClasses (03_shared-ui) → 06_annotations barrel → AnnotationsPage
|
||||
```
|
||||
|
||||
So after AZ-485 landed the per-component barrel architecture, F3 became visible. The workaround documented in `_docs/02_document/module-layout.md` Layout Rule #3 leaves the file in place and adds an exemption regex to `scripts/check-arch-imports.mjs` so consumers can deep-import `'../features/annotations/classColors'` without tripping STC-ARCH-01.
|
||||
|
||||
The exemption is correct but expensive — it lives in **five coupled places**, captured as a lesson on 2026-05-12:
|
||||
|
||||
1. `scripts/check-arch-imports.mjs` — `EXEMPT_RE` allowing the deep import.
|
||||
2. `tests/architecture_imports.test.ts` — fixture asserting the exemption holds.
|
||||
3. `src/features/annotations/index.ts` — 7-line carry-over comment block explaining why classColors is NOT re-exported here.
|
||||
4. `_docs/02_document/components/11_class-colors/description.md` — Caveats §7 "Physical location is misplaced today" + Module Inventory's "physical location pending refactor" suffix.
|
||||
5. `_docs/02_document/module-layout.md` — Layout Rule #3 exemption clause + Per-Component Mapping for `11_class-colors` ("Directories: none today...") + Verification Needed #1 + `shared/class-colors` proposed section + `06_annotations` Owns clause ("EXCEPT `classColors.ts`").
|
||||
|
||||
Every contributor reading any one of those touches the exemption — and the lesson explicitly warns that the carry-over **never silently drifts** because each touchpoint is enforced (static check, unit test, doc, layout rule). The cost is real ongoing tax; closing F3 removes all of it at once.
|
||||
|
||||
## Outcome
|
||||
|
||||
- `classColors.ts` lives at its logical layer (`src/class-colors/classColors.ts`) with a proper barrel (`src/class-colors/index.ts`); consumers import from the barrel (`'../class-colors'` or `'../../class-colors'`) like every other component.
|
||||
- The STC-ARCH-01 exemption regex disappears from `scripts/check-arch-imports.mjs` and from the architecture test fixture; running `bun run --bun scripts/check-arch-imports.mjs --mode=arch-imports` finds zero deep imports anywhere in `src/`.
|
||||
- The five coupled doc/script callouts above are simplified: each reflects the new physical home; none reference an exemption.
|
||||
- `bun run build` succeeds with no runtime circular-import warnings (the original concern is gone because `class-colors` is no longer a subtree of `06_annotations`).
|
||||
- `architecture_compliance_baseline.md` F3 row reads **CLOSED** with the task and commit reference, mirroring the AZ-485 → F4 and AZ-486 → F7 patterns.
|
||||
|
||||
## Scope
|
||||
|
||||
### Included
|
||||
|
||||
**Source changes**
|
||||
|
||||
- Create directory `src/class-colors/` containing:
|
||||
- `classColors.ts` — exact byte-for-byte copy of `src/features/annotations/classColors.ts` (12-color palette, 12 fallback names, `getClassColor`, `getPhotoModeSuffix`, `getClassNameFallback`, `FALLBACK_CLASS_NAMES` — no behaviour change).
|
||||
- `index.ts` — re-exports the four public symbols: `getClassColor`, `getClassNameFallback`, `getPhotoModeSuffix`, `FALLBACK_CLASS_NAMES`.
|
||||
- Delete `src/features/annotations/classColors.ts`.
|
||||
- Update 4 consumer imports (currently shown by `rg classColors src/`):
|
||||
- `src/components/DetectionClasses.tsx` — `from '../features/annotations/classColors'` → `from '../class-colors'`.
|
||||
- `src/features/annotations/CanvasEditor.tsx` — `from './classColors'` → `from '../../class-colors'`.
|
||||
- `src/features/annotations/AnnotationsSidebar.tsx` — `from './classColors'` → `from '../../class-colors'`.
|
||||
- `src/features/annotations/AnnotationsPage.tsx` — `from './classColors'` → `from '../../class-colors'`.
|
||||
- Drop the "classColors symbols are NOT re-exported here" comment block from `src/features/annotations/index.ts` (lines 5-12 of the current file).
|
||||
|
||||
**Script + test changes**
|
||||
|
||||
- Remove the F3-pending exemption from `scripts/check-arch-imports.mjs` (the `EXEMPT_RE` entry covering `features/annotations/classColors`).
|
||||
- Update `tests/architecture_imports.test.ts` so the fixture asserting the exemption is either deleted (preferred) or rewritten to assert "no exemptions remain". Whichever shape, the test must still pass and continue to catch regressions.
|
||||
|
||||
**Documentation changes**
|
||||
|
||||
- `_docs/02_document/module-layout.md`:
|
||||
- Layout Rule #3 — drop the "One F3-pending exemption" clause.
|
||||
- Per-Component Mapping for `11_class-colors` — `Directories: src/class-colors/**` (not "none today"); `Public API exported from src/class-colors/index.ts` (not "no barrel today").
|
||||
- Verification Needed #1 — mark as RESOLVED with task reference.
|
||||
- `## Shared / Cross-Cutting` → `### shared/class-colors` block — remove the workaround note about READ-ONLY for `06_annotations` tasks.
|
||||
- Per-Component Mapping for `06_annotations` — drop the "EXCEPT `classColors.ts`" clause from Owns.
|
||||
- `_docs/02_document/components/11_class-colors/description.md` — Caveats §7 "Physical location is misplaced today" → rewrite as "Physical location: `src/class-colors/`" with the historical note moved to a single line citing the closing task; Module Inventory path updated.
|
||||
- `_docs/02_document/architecture_compliance_baseline.md` — F3 row gets the CLOSED marker (same shape as F4, F7), with task + commit hash placeholder for the implementer to fill at merge time.
|
||||
|
||||
### Excluded
|
||||
|
||||
- Moving `CanvasEditor.tsx` (Finding F2 — different cross-feature edge; separate task).
|
||||
- Creating `src/shared/` (Finding F6 — distinct decision; deliberately NOT used as the target so this task doesn't pre-empt F6 design).
|
||||
- Changing the `classColors.ts` API surface — pure file move + import-path updates. The dead `??` guard noted in `11_class-colors/description.md` §5 stays dead; the redundancy with `DetectionClass.photoMode` stays unaddressed; both are Step 4/5 review items, not this task.
|
||||
- Renaming any of the four exported symbols.
|
||||
- Adding `localization` for the suffix strings (Step 4 i18n item; separate concern).
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
**AC-1: File physically lives at new location**
|
||||
Given the repository after the task lands
|
||||
When `ls src/class-colors/`
|
||||
Then it contains `classColors.ts` and `index.ts`; running `find src/features/annotations -name classColors.ts` returns no results.
|
||||
|
||||
**AC-2: Consumers import via barrel**
|
||||
Given the four consumer files (`DetectionClasses.tsx`, `CanvasEditor.tsx`, `AnnotationsSidebar.tsx`, `AnnotationsPage.tsx`)
|
||||
When their imports are inspected
|
||||
Then each imports from `'../class-colors'` or `'../../class-colors'` (the barrel), not from `'.../classColors'` (the file).
|
||||
|
||||
**AC-3: Architecture static check has zero exemptions**
|
||||
Given the codebase after the task lands
|
||||
When `bun run --bun scripts/check-arch-imports.mjs --mode=arch-imports` runs
|
||||
Then the exit code is 0; the `EXEMPT_RE` block in the script contains no entry for `classColors`; `tests/architecture_imports.test.ts` passes without referencing a classColors exemption.
|
||||
|
||||
**AC-4: Build succeeds with no circular-import warnings**
|
||||
Given the codebase after the task lands
|
||||
When `bun run build` runs
|
||||
Then it succeeds; Vite output contains no "Circular dependency" warnings involving `class-colors`, `annotations`, or `DetectionClasses`.
|
||||
|
||||
**AC-5: Full test suite green**
|
||||
Given the codebase after the task lands
|
||||
When `bun run test` runs
|
||||
Then all previously-passing tests still pass — including `tests/detection_classes.test.tsx` (AZ-472), `tests/architecture_imports.test.ts`, and any test that imports a consumer file.
|
||||
|
||||
**AC-6: Documentation is consistent**
|
||||
Given the codebase after the task lands
|
||||
When the 5 coupled doc/script touchpoints are inspected
|
||||
Then `module-layout.md`, `11_class-colors/description.md`, `architecture_compliance_baseline.md`, `src/features/annotations/index.ts`, and `scripts/check-arch-imports.mjs` all reflect the new physical home; no surviving reference describes classColors as "physically misplaced", "F3-pending", or "exempt".
|
||||
|
||||
## Non-Functional Requirements
|
||||
|
||||
**Compatibility**: zero runtime behaviour change. Bundle size is identical (same exported symbols, same implementation). Bundle composition shifts by one chunk boundary but tree-shaking preserves dead-code-elimination semantics.
|
||||
|
||||
**Reliability**: the structural fix removes a long-standing risk that a new contributor accidentally re-introduces the circular import by re-exporting classColors from the 06_annotations barrel. After this task lands, that re-export becomes legal but no longer creates a cycle (because class-colors is its own component).
|
||||
|
||||
## Unit Tests
|
||||
|
||||
| AC Ref | What to Test | Required Outcome |
|
||||
|--------|--------------|------------------|
|
||||
| AC-1 | `import { getClassColor } from '../class-colors'` | resolves to the new file; `getClassColor(0)` returns the same hex as today |
|
||||
| AC-2 | Static scan of import declarations in the 4 consumers | every import is via barrel; no file-path import remains |
|
||||
| AC-3 | Architecture test fixture (`tests/architecture_imports.test.ts`) | passes after the F3 exemption fixture is removed |
|
||||
| AC-5 | All existing classColors-touching tests | unchanged assertions, all green |
|
||||
|
||||
## Blackbox Tests
|
||||
|
||||
| AC Ref | Initial Data/Conditions | What to Test | Expected Behavior | NFR References |
|
||||
|--------|------------------------|--------------|-------------------|----------------|
|
||||
| AC-4 | Clean clone, `bun install` complete | `bun run build` | succeeds; no circular-import warnings | Reliability |
|
||||
| AC-2 + AC-3 | Clean clone, `bun install` complete | `bun run --bun scripts/check-arch-imports.mjs --mode=arch-imports` | exit 0; no exemption block matches classColors | — |
|
||||
| AC-5 | Clean clone, `bun install` complete | `bun run test` | full suite passes | — |
|
||||
|
||||
## Constraints
|
||||
|
||||
- The file move must be a single atomic commit (or one PR's worth of commits). Splitting "move file" from "update imports" creates a broken intermediate state where neither path works.
|
||||
- The new directory name is `src/class-colors/` — kebab-case, matching every other component dir established by AZ-485. Do NOT use `src/classColors/` (camel-case) or `src/shared/class-colors/` (opens F6).
|
||||
- The barrel must re-export ALL four current public symbols. Dropping `FALLBACK_CLASS_NAMES` (currently used by `DetectionClasses.tsx` for the empty-state fallback row) would break the consumer.
|
||||
- The `EXEMPT_RE` regex literal in `scripts/check-arch-imports.mjs` may be a single combined pattern — read the script first to understand its shape before editing.
|
||||
|
||||
## Risks & Mitigation
|
||||
|
||||
**Risk 1: A consumer was missed**
|
||||
- *Risk*: A test file, story, or sample (`tests/**`, `e2e/**`, `_docs/02_document/modules/*.md`) imports `classColors` from the old path and breaks after the move.
|
||||
- *Mitigation*: Before deletion, `rg "features/annotations/classColors" .` from the repo root. Every match outside `_docs/` is a consumer that must be updated. Doc references inside `_docs/` are addressed in the documentation changes above.
|
||||
|
||||
**Risk 2: Vite hot-module resolution caches the old path**
|
||||
- *Risk*: After the move, a stale dev-server HMR session continues to resolve `'../features/annotations/classColors'` from cache.
|
||||
- *Mitigation*: Cold-restart `bun run dev` after the move. CI is unaffected.
|
||||
|
||||
**Risk 3: A circular import resurfaces from a different direction**
|
||||
- *Risk*: A future contributor re-introduces a circle by importing something from `06_annotations` inside `src/class-colors/classColors.ts`. The new physical separation doesn't make all circles impossible.
|
||||
- *Mitigation*: Out of scope for this task. The general "no cross-component deep imports" rule (STC-ARCH-01) is already in place and now applies to `class-colors` symmetrically; that's the standing protection.
|
||||
|
||||
**Risk 4: The architecture test fixture deletion loses regression coverage**
|
||||
- *Risk*: The current `tests/architecture_imports.test.ts` fixture asserts that the exemption WORKS. Deleting the fixture removes that regression check; if a future change accidentally re-introduces a similar exemption, the test won't catch it.
|
||||
- *Mitigation*: Replace the fixture with a stronger assertion: "no `EXEMPT_RE` entries match any path under `src/`". That keeps the safety net while removing the F3-specific coupling.
|
||||
|
||||
## References
|
||||
|
||||
- `_docs/02_document/architecture_compliance_baseline.md` — F3 (High / Architecture); to be marked CLOSED on completion.
|
||||
- `_docs/02_document/module-layout.md` — Layout Rule #3, Per-Component Mapping `11_class-colors`, `06_annotations`, Verification Needed #1, `## Shared / Cross-Cutting` → `### shared/class-colors`.
|
||||
- `_docs/02_document/components/11_class-colors/description.md` — Caveats §7, Module Inventory.
|
||||
- `_docs/LESSONS.md` — 2026-05-12 architecture lesson on the 5-coupled-places exemption pattern.
|
||||
- `_docs/02_tasks/done/AZ-485_refactor_public_api_barrels.md` — establishes the per-component barrel pattern this task extends.
|
||||
Reference in New Issue
Block a user