docs(plan-2.5): closure — RFC supersession, BACKLOG landing, applyDomAttributes dedupe

Plan 2.5 final phase (P8). Closes the PrimeVue shell-migration workstream.

- RFC-WS-PRIMEVUE-PLAN-2-5: added Supersessions section recording the
  governing-RFC divergences (§4 dark mode `<body>`→`<html>` per AD-2.5-D1;
  §7.4 workspace sub option A reversed to placeholder after visual
  review). Added closure summary (phases, ADs, brand-square recipe,
  suite delta, lessons). Status → COMPLETE.
- BACKLOG: landed 8 items surfaced during Plan 2.5 (MOBILE-SHELL-PARITY,
  WORKSPACE-DROPDOWN-SUB-CONTENT, DENSITY-AWARE-SPACING, TOPBAR-H-VAR-
  DECLARE, CSP-FONT-SRC-LOCKDOWN, AUTO-IMPORTS-V2-SCAN, PNPM-RESOLUTIONS-
  ROOT, SHELLUI-STALE-DATA-THEME-CLEANUP). Marked GRADIENT-BRAND-
  ALIGNMENT as resolved.
- useShellUiStore.toggleDensity: removed redundant applyDomAttributes()
  call (the AppShellV2 watch already covers density changes). Moved the
  DOM-write assertion to AppShellV2 watcher-coverage specs.

Plan 2.5 status: COMPLETE.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-03 02:23:39 +02:00
parent c9e417690c
commit 1ba5d5bb9b
6 changed files with 248 additions and 14 deletions

View File

@@ -676,6 +676,130 @@ voor third-party integraties (ticketing, HR, etc.)
## Technische schuld
> Plan 2.5 shell follow-ups (landed at P8 closure, juni 2026). See
> `dev-docs/RFC-WS-PRIMEVUE-PLAN-2-5.md` → Plan 2.5 Closure.
### MOBILE-SHELL-PARITY — Mobile drawer chrome parity with desktop sidebar
**Prioriteit:** Middel
Mobile drawer chrome doesn't match the desktop sidebar polish: logo
placement is incorrect, an extraneous X close button overlaps the drawer,
and the WorkspaceSwitcher is hidden on mobile. A dedicated mobile sprint
after Plan 2.5; deliberately out of scope per Q3.
**Trigger:** before mobile users onboard / mobile traffic becomes
non-trivial.
---
### WORKSPACE-DROPDOWN-SUB-CONTENT — Real WorkspaceSwitcher sub-line content (type + metrics)
**Prioriteit:** Middel
The WorkspaceSwitcher sub line currently shows the placeholder string
'Organisatie' (per AD-2.5-W1 reversal). Real content requires an
`organisations.type` enum + a metrics endpoint (e.g., member count,
festival/event metadata). Needs a small RFC covering: type enum schema,
metrics aggregation, API shape, frontend wiring.
**Trigger:** when organisation metadata work begins, OR when the
placeholder reads as too empty in production.
---
### DENSITY-AWARE-SPACING — Wire `data-density` to component spacing
**Prioriteit:** Laag
`<html data-density>` toggles correctly between `comfortable` and
`compact`, but no component CSS reads the attribute, so the toggle is
visually inert. Plan 4 should pick which spacing surfaces (tables, lists,
cards) respond to density and add the corresponding
`[data-density="compact"]` overrides.
**Trigger:** Plan 4 template-layer work.
---
### TOPBAR-H-VAR-DECLARE — Declare `--topbar-h` in `:root` (or drop it)
**Prioriteit:** Laag
`--topbar-h` is referenced as `var(--topbar-h, 56px)` in component CSS but
never declared in `:root`. Effectively a hardcoded 56px with no override
path. Either declare it in `:root` for real or replace usages with `h-14`
(Tailwind).
**Trigger:** Plan 4 cleanup, or when topbar height changes.
---
### CSP-FONT-SRC-LOCKDOWN — `Content-Security-Policy: font-src 'self'` lockdown
**Prioriteit:** Laag
The P2-followup webfontloader lesson exposed a structural risk: dynamic
font-loading JS can pull from external domains (Google Fonts), bypassing
GDPR/privacy posture. A `Content-Security-Policy: font-src 'self' data:`
directive provides structural defense — even if a stray font-loader is
reintroduced, browsers would block external requests.
**Trigger:** pre-launch security hardening.
---
### AUTO-IMPORTS-V2-SCAN — `components-v2/` not in the auto-import scan dirs
**Prioriteit:** Laag
`vite.config.ts:79-94` `Components({dirs})` doesn't scan `components-v2/`,
so v2 components must be explicitly imported. The P5-followup AppBreadcrumb
auto-import surprise was traced to this. Either add `components-v2/` to the
scan dirs or accept explicit imports (the current trade-off).
**Trigger:** when explicit imports become tedious, or a new contributor
stumbles.
---
### PNPM-RESOLUTIONS-ROOT — `resolutions` field in app package.json is a no-op
**Prioriteit:** Laag
`apps/app/package.json` has a `resolutions` field, but pnpm only honors
resolutions in the workspace root `package.json`. Currently a no-op. Move
to root `package.json` or remove.
**Trigger:** next dependency conflict requiring a resolution override.
---
### SHELLUI-STALE-DATA-THEME-CLEANUP — Clean up stale legacy `data-theme` on init
**Prioriteit:** Laag
`useShellUiStore.applyDomAttributes()` writes `<html class="dark">` and
`<html data-density>` but doesn't clean up an old `data-theme` attribute if
it ever existed (from a prior Vuetify-era implementation). Pre-launch this
is a non-issue; for cleanliness, remove the stale attribute on init.
**Trigger:** cleanup pass before launch, or if anyone hits attribute-related
styling weirdness.
---
### ~~GRADIENT-BRAND-ALIGNMENT — gradient palette off-brand teal anchor~~ ✅ RESOLVED
~~The `utils/v2/gradient.ts` GRADIENT_PALETTE clustered in the Tailwind
blue-green family with off-brand teal `#0d9488` for the anchor slot.~~
Resolved in P7-followup-gradient-brand: palette replaced with the
crewli-starter diverse 8-color palette, slot 1 anchored to Crewli
`#0D9394`/`#075F60`. User-avatar fallback also corrected. Regression-spec
locks the brand-teal slot.
---
### TECH-OBSERVER-TEST-CONVERGENCE — Drop `bootstrap_on_org_create` flag once tests converge
**Aanleiding:** Session 3 introduceerde `OrganisationObserver` om elke nieuwe

View File

@@ -7,6 +7,15 @@
| **Design spec** | `dev-docs/superpowers/specs/2026-05-15-crewli-starter-gui-redesign-design.md` |
| **Impl plans** | `dev-docs/superpowers/plans/2026-05-16-gui-redesign-foundation.md` (Plan 1 of 5) |
> **Superseded in part during Plan 2.5.** Two design-SoT decisions diverged
> at implementation: dark-mode selector (`.dark` on `<html>`, not `<body>`;
> AD-2.5-D1) and the WorkspaceSwitcher sub line (option A reversed to a
> placeholder; AD-2.5-W1). The authoritative record is
> [`RFC-WS-PRIMEVUE-PLAN-2-5.md`](./RFC-WS-PRIMEVUE-PLAN-2-5.md) →
> Supersessions. (No discrete §4 dark-mode / §7.4 workspace-sub sections
> exist in this file — its §4 is "Out of scope" — so the supersession lives
> in the Plan 2.5 RFC rather than as per-section notes here.)
## Status
| Plan | State | Scope |

View File

@@ -2,7 +2,7 @@
| Field | Value |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
| **Status** | Draft — awaiting approval |
| **Status** | ✅ Complete (2026-06-03) |
| **Date** | 2026-05-19 |
| **Author** | Bert + Claude Chat |
| **Predecessors** | Plan 2 (`1429abf4` on `main`), Plan 3 (range `537ec098..637d77b3`, suite 564, 4 DEFERRED-HITL baselines) |
@@ -26,6 +26,28 @@ Closure of Plan 2.5 unblocks Plan 3 parity-batch baseline capture and establishe
---
## Supersessions vs the governing RFC (RFC-WS-GUI-REDESIGN-CREWLI-STARTER)
During implementation, two decisions diverged from the governing RFC. Both are deliberate and documented here:
### §4 — Dark mode selector
- Governing RFC specified: `.dark` class on `<body>`.
- Plan 2.5 implemented (AD-2.5-D1, P3 commit `d0dd45c0`): `.dark` on `<html>`.
- Rationale: PrimeVue's `darkModeSelector` and Tailwind v4's `@custom-variant dark (&:where(.dark, .dark *))` both target the document root by convention; placing the class on `<html>` aligns the entire dark-mode stack (PrimeVue + Tailwind + Crewli utilities) and avoids the cascading mismatch where AppTopbar reacted but downstream surfaces did not.
- Regression lock: `useShellUiStore.applyDomAttributes()` writes the class to `document.documentElement`.
### §7.4 — Workspace switcher sub line
- Governing RFC specified option A: no sub line under the workspace name.
- Plan 2.5 initially implemented option A (P4P5).
- After visual review against the crewli-starter SoT, **reversed**: a light-grey placeholder sub line is now rendered in the expanded trigger and dropdown rows; collapsed remains bare. The placeholder is a neutral string ('Organisatie'); real type + metrics data is deferred under backlog `WORKSPACE-DROPDOWN-SUB-CONTENT` (future backend work).
- Rationale: the two-line layout reads materially better; the placeholder honors the no-backend constraint without sacrificing the visual.
> **Cross-doc note.** Appendix A of this RFC asks for per-section supersession notes in `RFC-WS-GUI-REDESIGN-CREWLI-STARTER.md` §4 / §7.4. That file does not have discrete dark-mode / workspace-sub sections under those numbers (its §4 is "Out of scope"; there is no §7.4) — the §4 / §7.4 numbering above refers to the design SoT, per §1.2 of this RFC. A single top-level pointer was added to the governing RFC's status block instead; **this Supersessions section is authoritative.**
---
## 1. Context
### 1.1 Where Plan 2 / Plan 3 landed
@@ -978,6 +1000,46 @@ Plan 4 designs and implements the **template layer** — `PageTemplate`, `DataTa
---
## Plan 2.5 Closure (June 2026)
### Phases completed
- **P1** — Navigation registry + breadcrumb refactor
- **P2** — Inter typography via @fontsource/inter (+ P2-followup: removed webfontloader Public Sans JS path)
- **P3** — Dark mode mechanism (`.dark` on `<html>` + Tailwind v4 `@custom-variant dark`)
- **P4** — WorkspaceSwitcher refactor + APP_NAVIGATION as single SoT
- **P5** — Shell parity fixes 15 (breadcrumb retirement, dropdown panel structure)
- **P6** — Shell parity fixes 610 (sidebar height, density toggle, divider)
- **P6 followups** — brand-square symmetry, logo anchor (no-jump), switcher align/spacing/sub/hover/parity (the inset-shadow unification ended the recurring "not identical" perception)
- **P7** — CREWLI-DESIGN-TOKENS.md (Track B foundation doc) + gradient brand-alignment fix (palette diversification + Crewli teal anchor)
- **P8** — Closure (this phase): RFC supersession notes, BACKLOG landing, applyDomAttributes dedupe
### Architectural decisions of record
- **AD-2.5-T1** — Inter via @fontsource/inter (local, weights 400/500/600/700); Public Sans fully removed from BOTH CSS and JS webfontloader paths. Regression-locked.
- **AD-2.5-D1** — `.dark` on `<html>` (supersedes governing RFC §4)
- **AD-2.5-W1** — Option A (no sub) initially implemented, then reversed to placeholder sub after visual review (supersedes governing RFC §7.4)
- **AD-2.5-B1** — APP_NAVIGATION as single source of truth for sidebar + breadcrumb (eliminates legacy meta-based breadcrumb)
### Brand square recipe (cemented)
- 32px (`w-8 h-8`), `rounded-lg`, shared `shadow-[inset_0_-2px_0_#00000014]` utility on BOTH the header logo and the workspace avatar (single source — cannot drift). Offset 16px from the rail edge; collapsed rail width 64px = 32 + 2×16 keeps the square stationary across collapse toggle.
### Suite delta
Plan 2.5 added ~50 specs across phases (baseline → P8 final = **574 verified**, 84 files). Notable regression locks: typography (Inter on both CSS and JS paths), gradient palette (brand-teal slot pinned to #0D9394), avatar/logo size + shadow parity. P8 itself: the store's `toggleDensity` DOM-write assertion moved to AppShellV2's watcher-coverage specs (1 assertion in the store spec, +2 specs in `AppShellV2.spec.ts`).
### Lessons of record
- **Audit-first beats pixel-math.** The recurring switcher iterations came from prescribing pixel values without first measuring rendered state. The final parity pass succeeded because it produced a precise side-by-side comparison table BEFORE editing.
- **Sub-perceptual divergences need spec locks.** The inset-shadow 8% vs 10% mismatch and the gradient #0D9394 vs #0d9488 mismatch were both invisible to eyeballing; only hex-value specs catch them.
- **Shared definitions prevent drift.** The header logo and workspace avatar now reference the same Tailwind utility classes for size/radius/shadow — structurally impossible to diverge.
- **One DOM-write authority.** P8 collapsed the density toggle's redundant `applyDomAttributes()` call into AppShellV2's `watch([theme, density])`, so `toggleDensity` and `setTheme` are now both pure state mutations — the watcher is the single root-attribute writer.
### Status: COMPLETE
---
## Appendix A — Cross-doc updates required at closure
At Plan 2.5 closure, the following dev-docs receive **content updates** (not just SHA bumps in the sync manifest):