docs(spec): amend §8 severity-map + §6 stories-location + §8.X enforcement
- §8 severity table now covers all 21 values of the 5 mirrored enums (ShiftAssignment/ArtistEngagement/Payment/Person/MatchStatus); drops 3 phantom rows (active/inactive/expired, in no enum). Closes the silent grey-fallback gap for 11 production values found in the Plan 3 brainstorm self-audit. - §6 stories-placement reworded: custom/wrapper components (incl. PrimeVue wrappers) co-locate; only the ~80 PrimeVue catalog + Foundations centralize. Plan 2 misread this. - New §8.X: bidirectional Vitest consistency test (apps/app/tests/unit/utils/statusSeverity.consistency.spec.ts), added in Plan 3 — fails on any unmapped enum value OR orphan key. Plan 3 cleanup tasks (tracked in the Plan 3 plan doc, not here): (a) migrate Plan 2's 6 centralized stories to co-located. (b) refactor AppTopbar to wrap PrimeVue Menubar per RFC AD-3. Background: discovered during Plan 3 (Tier-1 primitives) brainstorm self-audit. Fixes spec-vs-reality drift and two Plan 2 deviations from binding spec/RFC text; prevents recurrence for future enums. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -281,9 +281,28 @@ Custom components are first-class in Storybook exactly like PrimeVue
|
||||
ones. crewli-starter `ComponentsPage.vue` (~80 PrimeVue components) is
|
||||
the **source of truth for the standard-component catalog**.
|
||||
|
||||
**Story placement:** custom/wrapper stories co-located next to the
|
||||
`.vue` (moves with the file at cutover); PrimeVue standard catalog and
|
||||
Foundations centralized under `stories/`.
|
||||
**Story placement (binding — two disjoint classes):**
|
||||
|
||||
1. **Custom/wrapper components.** Every component authored in this repo
|
||||
— shell pieces (`AppSidebar`, `AppTopbar`, `WorkspaceSwitcher`,
|
||||
`RightDrawer`, …), Tier-1 primitives (`StatusTag`, `StatCard`,
|
||||
`StateBlock`, `PageHead`, `TagsInput`, `EnergyDots`, `EnergyPicker`),
|
||||
`DraggableBlock`, and the template layer — **including components
|
||||
that internally wrap a PrimeVue component**. Their `.stories.ts` is
|
||||
**co-located next to the `.vue`** so it moves with the component at
|
||||
cutover and is deleted with it. This is the default for essentially
|
||||
all `components-v2/**` work.
|
||||
2. **PrimeVue standard catalog + Foundations.** The ~80-component
|
||||
pure-PrimeVue demo gallery (source of truth: crewli-starter
|
||||
`ComponentsPage.vue`) and the Foundations stories
|
||||
(Color/Typography/Spacing/Icons/Dark/Density) — neither has an owning
|
||||
`.vue`. These are **centralized under `stories/`**.
|
||||
|
||||
"Wraps a PrimeVue component" does **not** reclassify a component into
|
||||
the catalog — a wrapper is still custom and co-locates. (Plan 2 misread
|
||||
the prior wording and centralized 6 shell stories under
|
||||
`src/stories/v2/`; Plan 3 carries a cleanup task to migrate them — see
|
||||
commit body.)
|
||||
|
||||
**Story tree:** `Foundations/` (Color, Typography, Spacing, Icons, Dark
|
||||
mode, Density) · `PrimeVue/` (~80, grouped as in ComponentsPage) ·
|
||||
@@ -395,18 +414,42 @@ knowledge, not a per-page decision** — it lives in one map
|
||||
|
||||
| Status value(s) | `severity` | Semantics |
|
||||
|---|---|---|
|
||||
| `approved`, `confirmed`, `completed`, `active` | `success` | terminal-good / active |
|
||||
| `pending`, `pending_approval`, `invited` | `warn` | awaiting action |
|
||||
| `rejected`, `cancelled`, `declined` | `danger` | terminal-bad |
|
||||
| `draft` | `secondary` | not yet live |
|
||||
| `inactive`, `expired` | `secondary` (muted) | dormant |
|
||||
| (unmapped fallback) | `info` | + dev-warn so gaps surface |
|
||||
| `approved`, `completed`, `confirmed`, `contracted`, `paid_in_full` | `success` | terminal-good / fully settled |
|
||||
| `pending_approval`, `pending`, `applied`, `option`, `offered`, `reverted` | `warn` | organizer action required |
|
||||
| `invited`, `requested`, `deposit_paid` | `info` | awaiting external party / in-progress — no viewer action |
|
||||
| `none`, `draft`, `dismissed` | `secondary` | muted — absent / not-yet-live / archived |
|
||||
| `rejected`, `cancelled`, `declined`, `no_show` | `danger` | terminal-bad |
|
||||
| (unmapped at runtime) | renders `info` + dev console warn | unreachable in a passing build — §8.X consistency test fails on any gap |
|
||||
|
||||
Rule: **every** backend status enum mirrored into `src/types/` gets a
|
||||
row here in the same PR that adds the enum (extends the existing
|
||||
"mirror backend PHP enums" project rule). `StatusTag` never inlines a
|
||||
severity; it always resolves through this map.
|
||||
|
||||
### 8.X Enforcement (binding)
|
||||
|
||||
The §8 severity map is mechanically enforced by a single Vitest unit
|
||||
test, `apps/app/tests/unit/utils/statusSeverity.consistency.spec.ts`,
|
||||
added in Plan 3 alongside `statusSeverity.ts`. It imports the live enum
|
||||
modules (`ShiftAssignmentStatus`, `ArtistEngagementStatus`,
|
||||
`PaymentStatus`, `PersonStatus`, `MatchStatus`) and asserts **both**
|
||||
directions:
|
||||
|
||||
1. **Completeness** — every value of every listed enum resolves to an
|
||||
explicit severity in `statusSeverity.ts`, never the dev-fallback.
|
||||
Guards the failure mode that left 11 values silent-falling to grey
|
||||
`info`.
|
||||
2. **No phantoms** — every key in `statusSeverity.ts` corresponds to a
|
||||
value present in at least one listed enum. Guards the inverse mode
|
||||
(the original table mapped `active`/`inactive`/`expired`, which exist
|
||||
in no enum).
|
||||
|
||||
Adding a new mirrored enum, or a new value on an existing one, requires
|
||||
extending **both** `statusSeverity.ts` and this test's enum-list in the
|
||||
**same commit**. A silent fallback or an orphan key is a test failure
|
||||
that blocks CI, not a convention. This extends the existing "mirror
|
||||
backend PHP enums" rule (CLAUDE.md) with a mechanical gate.
|
||||
|
||||
**Tier-2 — Smart Filter subsystem (secure generic version now):**
|
||||
`SmartFilterBar` + `FilterChip` + `FilterPopover` + `AddFilterMenu` +
|
||||
5 editors (Text / NumberRange / MultiSelect / EnumGrid / Tag) +
|
||||
|
||||
Reference in New Issue
Block a user