plan.md
c135 plan: Component Cleanup (draft, before kick-off)
Gate: none. Mark's word. It can run beside everything else and helps both the web app (c134) and the token bridge (c132).
Reader: Mark; the layer-expert and extraction-expert agents in ../../../q-nuxt-layer; the executor who upgrades the docs here.
Mode: archaeology (surface what real use made of the catalog) → formula (apply the principles, group by group). Later stage, more order.
Why
The layer grew with the work: c92 through c128 added components as pages needed them, qdash staged its own library-grade pieces, and two parallel apps (c99) left a list of fixes. The catalog has duplicates and near cousins, components whose shape predates component_philosophy.md, code with no annotation, and documentation pages that show a default rather than the flavors the dashboard actually uses. The control plane web app will stand on this layer for years; the native app's token bridge needs the tokens clean. This is the moment Mark named: clean up the components and tighten the documentation.
What exists
- The layer:
components/in 23 groups (actor,agent,alert,compliance,data,dev,endpoint,filter,form,health,icon,icon-nav,integration,layout,nav,people,policy,policy-config,prose,security,sentence,transcript,typography,ux), about 250.vuefiles. Released by tag (v0.9.37 current). Consumers: design, qdash UI, www, app.qpoint.io. - The docs:
component-registry.ts(the count of record), 193 demo files withadminProps, the coverage system,/patterns,/layer/consolidation-gaps, the/document-components,/document-patternand/scan-patternsskills. - The principles:
component_philosophy.md(unified pantry: visual components live in the layer; business logic stays local; composition over configuration; Tailwind-native; replicate first, optimize later),design_tokens.md, the layer's authoring rules (no relative imports, no arbitrary-value Tailwind, no unscoped element selectors). - Waiting lists:
LAYER-CANDIDATES.mdin the qdash UI (ProjectedBadge, Panel, StatTile, Spark, MetricCell, BarList, Attention*, JsonTree, useVirtualRows, AlertHandlers, SkeletonRows, StateEmpty, plus astateport for DataTable and friends) and the Opus track's 59 fixes (UxIconid, UxPill danger tone, logo-only AgentAvatar, highlight.js optimizeDeps, and more).
The scorecard
Every component gets one row. The five checks are Mark's, in his order:
| Check | Pass means |
|---|---|
| Modular | one purpose; a clean interface to the whole; internals free (purpose + protocol) |
| Clean | no dead props, no arbitrary values, no relative imports, no unscoped selectors; passes the layer's lint |
| Documented | a doc comment on the component and on every prop, emit and slot (the annotation standard, Phase 0) |
| Shaped | composition over configuration; slots where consumers compose; no deep prop trees; tokens not hex |
| Docs page | a registry entry, a demo with adminProps for every useful prop, and examples that show the dashboard's real flavors (empty, minimal, typical, overflow, error where they apply) |
Plus three columns: used by (consumer and count, from a scan), cousins (components it overlaps), and resolution (keep · merge into X · alias and deprecate · split · retire · extract from qdash).
Resolution strategies for duplicates and cousins
- Merge when two components show the same thing with different props: one survives, the other becomes an alias that warns, removed two minor releases later.
- Split when one component carries two purposes (a prop that changes what it is).
- Alias and deprecate when consumers can't move in one release.
- Retire when no consumer uses it and no pattern needs it (checked against the scan, not memory).
- Extract when qdash staged a library-grade piece the layer lacks (the waiting lists).
- Keep with a note when the overlap is deliberate (a dense and a roomy variant that a pattern documents).
Decisions (defaults)
| # | Question | Default |
|---|---|---|
| D1 | Order of groups | ux → data → filter, nav, layout → form → the domain groups (actor, agent, policy, compliance, …) → icon, typography, prose. The most-used first. |
| D2 | What counts as a duplicate | two components a consumer could swap without the page meaning something else (the 5-question framework's "is it necessary?"). |
| D3 | Deprecation window | two minor releases, with a console warning and a note in the release. |
| D4 | Domain groups | stay in the layer (unified pantry), but each must show a qdash flavor in its docs or it is a retire candidate. |
| D5 | Flavors in the docs | harvested from the qdash UI by /scan-patterns and recorded as named examples in the demo, not hand-invented. |
| D6 | Annotation standard | JSDoc-style doc comments on the component, props, emits and slots; a lint rule that fails the layer's build when one is missing (added after the first group passes, so the rule is written from practice). |
| D7 | Releases | one per group pass, with the consumers' lockfiles bumped by update-consumers.sh. |
| D8 | The waiting lists | merged into one list in the layer repo at Phase 1 and extracted during Phase 2, each ahead of the group it belongs to, so the control plane web app (c134) finds them in the layer from its first page. Ruled 2026-11-09. |
Phases
0. Tooling
A script that produces the scorecard skeleton: every component, its props, emits and slots, its demo and adminProps coverage, and its usages across the four consumers. The annotation standard drafted. A scorecard.md committed in this cycle directory.
1. Census
The cousins and duplicates named across the whole catalog, with a proposed resolution each. The two waiting lists merged. Review stop with Mark: the resolutions ruled.
2. Group passes (D1 order)
For each group: apply the resolutions, bring every component to five passes, write the annotations, upgrade the docs pages with harvested flavors and adminProps, release, bump consumers, record. Review stop per group.
3. The lint
D6's rule, from what the first two groups taught; turned on for the whole layer.
4. Close
Coverage numbers before and after, the retired and merged lists, component_philosophy.md updated with anything the work changed, and the /document-components skill updated to produce the new docs shape by default.
Clarifying questions
app.qpoint.io a consumer?Answered 2026-11-09: yes, in the form of its successor, c134's control plane web app (whether it keeps the app.qpoint.io name is a c0 item). It starts from a blank slate, so the layer must already hold what it needs.- Release cadence during the cleanup: per group (D7) or fewer, larger releases?
Extractions here?Answered 2026-11-09: yes, now. Mark: plan on adding the missing components to the layer now, since the successor app starts from a blank slate and builds from the ground up (D8 revised).- Any component families you already know are duplicates, so the census starts from your list?
Patterns to consider
- The scorecard as a living page on the design site (like
/layer/consolidation-gaps), regenerated by the script, so the cleanup's progress is visible and the standard outlives the cycle. - Flavors harvested, not invented: a demo example that names the qdash page it came from is a test of the component against real use.
graduatedFromon the registry entry (apipeline.mdfollow-up): the cycle and mock each component came from, filled in during the group passes.- The token audit as a by-product: every hex or arbitrary value found becomes a token or a bug, feeding c132's bridge.
- The 5-question framework per component in the scorecard's notes: useful, clear, precise, necessary, beautiful.