aw-spec-cli 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +291 -0
  2. package/assets/docs/UI.Visualization/PACKAGING.md +191 -0
  3. package/assets/docs/UI.Visualization/UI.Visualization.Reference.pack.txt +11768 -0
  4. package/assets/docs/UI.Visualization/UI.Visualization.pack.txt +11214 -0
  5. package/assets/docs/UI.Visualization/pack-foundation.ps1 +165 -0
  6. package/assets/docs/UI.Visualization/pack-foundation.sh +206 -0
  7. package/assets/docs/UI.Visualization/pack-reference-foundation.ps1 +159 -0
  8. package/assets/docs/UI.Visualization/pack-reference-foundation.sh +205 -0
  9. package/assets/docs/UI.Visualization/unpack-foundation.ps1 +126 -0
  10. package/assets/docs/UI.Visualization/unpack-foundation.sh +217 -0
  11. package/assets/docs/UI.Visualization/unpack-reference-foundation.ps1 +129 -0
  12. package/assets/docs/UI.Visualization/unpack-reference-foundation.sh +218 -0
  13. package/assets/docs/domainspecs/UIVisualization/chart-bubble.md +70 -0
  14. package/assets/docs/domainspecs/UIVisualization/chart-dimred.md +58 -0
  15. package/assets/docs/domainspecs/UIVisualization/chart-heatmap.md +62 -0
  16. package/assets/docs/domainspecs/UIVisualization/chart-network.md +69 -0
  17. package/assets/docs/domainspecs/UIVisualization/chart-parallel.md +75 -0
  18. package/assets/docs/domainspecs/UIVisualization/chart-scurve.md +66 -0
  19. package/assets/docs/domainspecs/UIVisualization/chart-survival.md +69 -0
  20. package/assets/docs/domainspecs/UIVisualization/chart-trellis.md +68 -0
  21. package/assets/docs/domainspecs/UIVisualization/chart-violin.md +61 -0
  22. package/assets/docs/domainspecs/UIVisualization/chart-volcano.md +63 -0
  23. package/assets/docs/domainspecs/UIVisualization/charting-standards.domain.md +80 -0
  24. package/assets/docs/domainspecs/UIVisualization/clean-architecture.domain.md +87 -0
  25. package/assets/docs/domainspecs/UIVisualization/coding-standards.domain.md +47 -0
  26. package/assets/docs/domainspecs/UIVisualization/comandrulemap.md +130 -0
  27. package/assets/docs/domainspecs/UIVisualization/component-contracts.domain.md +67 -0
  28. package/assets/docs/domainspecs/UIVisualization/data-source.domain.md +68 -0
  29. package/assets/docs/domainspecs/UIVisualization/domain-requirements.md +110 -0
  30. package/assets/docs/domainspecs/UIVisualization/folder-structure.domain.md +55 -0
  31. package/assets/docs/domainspecs/UIVisualization/state-management.domain.md +67 -0
  32. package/assets/docs/domainspecs/UIVisualization/testing.domain.md +52 -0
  33. package/assets/docs/domainspecs/UIVisualization/ui-viz-terms.md +39 -0
  34. package/dist/commands/init.d.ts.map +1 -1
  35. package/dist/commands/init.js +54 -7
  36. package/dist/commands/init.js.map +1 -1
  37. package/dist/commands/update.d.ts +3 -0
  38. package/dist/commands/update.d.ts.map +1 -0
  39. package/dist/commands/update.js +142 -0
  40. package/dist/commands/update.js.map +1 -0
  41. package/dist/index.js +2 -0
  42. package/dist/index.js.map +1 -1
  43. package/dist/utils/manifest.d.ts +31 -0
  44. package/dist/utils/manifest.d.ts.map +1 -0
  45. package/dist/utils/manifest.js +91 -0
  46. package/dist/utils/manifest.js.map +1 -0
  47. package/dist/utils/update-engine.d.ts +52 -0
  48. package/dist/utils/update-engine.d.ts.map +1 -0
  49. package/dist/utils/update-engine.js +203 -0
  50. package/dist/utils/update-engine.js.map +1 -0
  51. package/package.json +1 -1
  52. package/assets/docs/requirement-spec.txt +0 -15
@@ -0,0 +1,69 @@
1
+ # SurvivalCurveChart — Chart Rule
2
+
3
+ > Load **only when "Survival / Kaplan-Meier / retention" (or "all plots") is selected** (see [[domain-requirements]]).
4
+ > Component: `SurvivalCurveChart` in `components/charts/generic/SurvivalCurveChart.tsx`. Built on [[charting-standards.domain]].
5
+
6
+ ## Purpose
7
+ Kaplan-Meier–style **step-function** curves with optional CI shading, median markers, and a
8
+ significance annotation. Use for clinical OS/PFS, user-cohort retention, component MTTF, churn.
9
+
10
+ ## Props contract
11
+ ```ts
12
+ interface SurvivalPoint {
13
+ time: number
14
+ survival: number // 0–1 (×100 applied) or 0–100
15
+ ciLower?: number; ciUpper?: number // same scale as survival
16
+ nAtRisk?: number
17
+ }
18
+ interface SurvivalArm {
19
+ label: string; color: string // colour REQUIRED — distinguishes arms
20
+ points: SurvivalPoint[]
21
+ medianTime?: number | null // null = not reached
22
+ }
23
+ interface SurvivalCurveChartProps {
24
+ arms: SurvivalArm[] // REQUIRED
25
+ timeLabel?: string // default "Time"
26
+ survivalLabel?: string // default "Survival Probability (%)"
27
+ eventLabel?: string // "Death", "Churn", "Failure" …
28
+ medianLabel?: string // "mOS", "mPFS", "Median retention"
29
+ curveType?: string // corner badge: "OS", "KM", "Retention"
30
+ pValue?: string // "< 0.001", "n.s."
31
+ showCI?: boolean // default true (needs ciLower/ciUpper)
32
+ xMax?: number; height?: number
33
+ }
34
+ ```
35
+
36
+ ## Rules
37
+ - Curve is a **step function** (`shape: 'hv'`) — survival is constant between events. Pass points
38
+ at event/censor times; the chart draws the steps.
39
+ - `survival` accepts either 0–1 or 0–100 — the chart normalises; be consistent within an arm.
40
+ - CI shading requires `ciLower`/`ciUpper` on the points and `showCI` (default on).
41
+ - `medianTime: null` renders "Not reached" — use it, don't fake a value.
42
+
43
+ ## Adapter example (agent reference)
44
+ ```tsx
45
+ 'use client'
46
+ import { SurvivalCurveChart } from '@/components/charts/generic'
47
+ import type { TrialArm } from '@/lib/types/pharma'
48
+
49
+ export default function KaplanMeierChart({ arms, height }: { arms: TrialArm[]; height?: number }) {
50
+ return (
51
+ <SurvivalCurveChart
52
+ arms={arms.map(a => ({
53
+ label: a.name, color: a.color, medianTime: a.medianSurvival,
54
+ points: a.points.map(p => ({ time: p.time, survival: p.survival,
55
+ ciLower: p.ciLower, ciUpper: p.ciUpper, nAtRisk: p.nAtRisk })),
56
+ }))}
57
+ timeLabel="Days" survivalLabel="Survival Probability (%)" medianLabel="mOS"
58
+ curveType="OS" pValue="< 0.001" showCI height={height}
59
+ />
60
+ )
61
+ }
62
+ ```
63
+
64
+ ## Scaffolds when selected
65
+ - generic `SurvivalCurveChart` + `app/survival/` (or `trials/`) route + nav tab + optional adapter;
66
+ an optional number-at-risk table consumes `nAtRisk`.
67
+
68
+ ## Related
69
+ - [[charting-standards.domain]] · [[component-contracts.domain]] · [[clean-architecture.domain]]
@@ -0,0 +1,68 @@
1
+ # TrellisGrid — Chart Rule
2
+
3
+ > Load **only when "Trellis / facet / small-multiples" (or "all plots") is selected** (see [[domain-requirements]]).
4
+ > Component: `TrellisGrid` in `components/charts/generic/TrellisGrid.tsx`. Built on [[charting-standards.domain]];
5
+ > uses Plotly subplot `grid`.
6
+
7
+ ## Purpose
8
+ An **N×M grid of the same chart type** — one panel per data subset (small multiples / facets).
9
+ Use for KPI by region, IC₅₀ by target class, sensor readings by machine, feature distributions
10
+ per class.
11
+
12
+ ## Props contract
13
+ ```ts
14
+ interface TrellisTrace {
15
+ type: 'bar' | 'scatter' | 'line' | 'box'
16
+ x: (string|number)[]; y: number[]
17
+ label: string; color?: string
18
+ mode?: 'markers' | 'lines' | 'lines+markers' // scatter/line only
19
+ }
20
+ interface TrellisPanel { title: string; traces: TrellisTrace[] }
21
+
22
+ interface TrellisGridProps {
23
+ panels: TrellisPanel[] // REQUIRED — one per subset
24
+ cols?: number // grid columns (default 3); rows auto
25
+ xLabel?: string; yLabel?: string // shared axis labels
26
+ sharedXAxis?: boolean // align x-range across panels
27
+ sharedYAxis?: boolean // align y-range — ESSENTIAL for fair comparison
28
+ panelHeight?: number // px per panel (total = rows × panelHeight)
29
+ title?: string
30
+ }
31
+ ```
32
+
33
+ ## Rules
34
+ - All panels render the **same trace type** — that is the point of small multiples. Don't mix bar
35
+ and line across panels.
36
+ - Turn on **`sharedYAxis`** whenever comparing magnitudes across panels — otherwise each panel
37
+ auto-scales and the comparison misleads.
38
+ - `panels` is built by grouping the dataset on the facet dimension (target, region, class) in the
39
+ adapter/page.
40
+ - `TrellisGrid` sizes by `rows × panelHeight` (it does not fill-parent); pick `panelHeight` for the
41
+ card and let the page scroll if needed.
42
+
43
+ ## Page/adapter example (agent reference)
44
+ ```tsx
45
+ 'use client'
46
+ import { TrellisGrid } from '@/components/charts/generic'
47
+ import { PHARMA_COLORS } from '@/components/charts/PlotlyChart'
48
+ import type { Compound } from '@/lib/types/pharma'
49
+
50
+ export default function Ic50ByTarget({ compounds }: { compounds: Compound[] }) {
51
+ const targets = [...new Set(compounds.map(c => c.target))]
52
+ const panels = targets.map((t, i) => {
53
+ const g = compounds.filter(c => c.target === t).sort((a, b) => a.ic50_nM - b.ic50_nM)
54
+ return {
55
+ title: t,
56
+ traces: [{ type: 'bar' as const, label: t, color: PHARMA_COLORS[i % PHARMA_COLORS.length],
57
+ x: g.map(c => c.name), y: g.map(c => Math.min(c.ic50_nM, 800)) }],
58
+ }
59
+ })
60
+ return <TrellisGrid panels={panels} cols={4} xLabel="Compound" yLabel="IC₅₀ (nM)" sharedYAxis panelHeight={210} />
61
+ }
62
+ ```
63
+
64
+ ## Scaffolds when selected
65
+ - generic `TrellisGrid` + `app/trellis/page.tsx` + nav tab + optional adapter.
66
+
67
+ ## Related
68
+ - [[charting-standards.domain]] · [[component-contracts.domain]] · [[clean-architecture.domain]]
@@ -0,0 +1,61 @@
1
+ # ViolinPlot — Chart Rule
2
+
3
+ > Load **only when "Violin / distribution" (or "all plots") is selected** (see [[domain-requirements]]).
4
+ > Component: `ViolinPlot` in `components/charts/generic/ViolinPlot.tsx`.
5
+ > Built on [[charting-standards.domain]]; uses Plotly's native `violin` (KDE + box computed for you).
6
+
7
+ ## Purpose
8
+ Distribution **shape (KDE)** of a numeric variable across groups, with optional box plot and
9
+ jittered points. Use for biomarker expression by cohort, API latency by endpoint, salary by band,
10
+ any group-wise distribution comparison.
11
+
12
+ ## Props contract
13
+ ```ts
14
+ interface ViolinGroup {
15
+ label: string // x-axis category
16
+ values: number[] // RAW observations — Plotly computes KDE/IQR/whiskers
17
+ color?: string
18
+ }
19
+ type PointDisplayMode = 'none' | 'outliers' | 'all' | 'suspected'
20
+
21
+ interface ViolinPlotProps {
22
+ groups: ViolinGroup[] // REQUIRED
23
+ yLabel?: string; xLabel?: string
24
+ showBox?: boolean // overlay median/IQR box (default true)
25
+ showMean?: boolean // mean line (default false)
26
+ showPoints?: PointDisplayMode // default 'outliers'
27
+ side?: 'both' | 'positive' | 'negative' // split violin for back-to-back compare
28
+ bandwidth?: 'normal reference' | 'scott' | 'silverman'
29
+ fillOpacity?: number
30
+ title?: string; height?: number
31
+ }
32
+ ```
33
+
34
+ ## Rules
35
+ - Pass **raw values** — never pre-binned or pre-summarised; the chart computes KDE, quartiles and
36
+ whiskers. Each group needs enough points (≥ ~10) for a meaningful KDE.
37
+ - Use `showPoints="outliers"` for clinical/quality data; `"all"` only for small n.
38
+ - `side="positive"`/`"negative"` enables split (back-to-back) violins for two-condition compares.
39
+
40
+ ## Page/adapter example (agent reference)
41
+ ```tsx
42
+ 'use client'
43
+ import { ViolinPlot } from '@/components/charts/generic'
44
+
45
+ // readings: { group: string; value: number }[]
46
+ export default function ExpressionViolin({ readings }: { readings: { group: string; value: number }[] }) {
47
+ const groups = [...new Set(readings.map(r => r.group))].map(g => ({
48
+ label: g, values: readings.filter(r => r.group === g).map(r => r.value),
49
+ }))
50
+ return (
51
+ <ViolinPlot groups={groups} yLabel="Expression (log₂FC)" xLabel="Treatment"
52
+ showBox showMean showPoints="outliers" />
53
+ )
54
+ }
55
+ ```
56
+
57
+ ## Scaffolds when selected
58
+ - generic `ViolinPlot` + `app/violin/page.tsx` + nav tab + optional adapter.
59
+
60
+ ## Related
61
+ - [[charting-standards.domain]] · [[component-contracts.domain]] · [[clean-architecture.domain]]
@@ -0,0 +1,63 @@
1
+ # VolcanoPlot — Chart Rule
2
+
3
+ > Load **only when "Volcano" (or "all plots") is selected** (see [[domain-requirements]]).
4
+ > Component: `VolcanoPlot` in `components/charts/generic/VolcanoPlot.tsx`. Built on [[charting-standards.domain]].
5
+
6
+ ## Purpose
7
+ **Magnitude vs. significance** scatter, partitioned into up / down / not-significant by two
8
+ thresholds. Use for differential expression (RNA-seq/proteomics), A/B-test lift vs significance,
9
+ GWAS hits, ML feature importance, adverse-event signals.
10
+
11
+ ## Props contract
12
+ ```ts
13
+ interface VolcanoPoint {
14
+ x: number // magnitude (e.g. log₂FC, effect size)
15
+ y: number // significance (e.g. -log₁₀ p-value)
16
+ label: string
17
+ meta?: Record<string, string|number>
18
+ }
19
+ interface VolcanoPlotProps {
20
+ points: VolcanoPoint[] // REQUIRED
21
+ xLabel?: string // default "log₂(Fold Change)"
22
+ yLabel?: string // default "-log₁₀(p-value)"
23
+ foldChangeThreshold?: number // |x| above → "changed" (default 1.0)
24
+ significanceThreshold?: number // y above → significant (default 1.301 ≈ p<0.05)
25
+ upColor?: string; downColor?: string; nsColor?: string
26
+ upLabel?: string; downLabel?: string; nsLabel?: string
27
+ labelTopN?: number // annotate top-N by |x·y| (default 10; 0 disables)
28
+ title?: string; height?: number
29
+ }
30
+ ```
31
+
32
+ ## Rules
33
+ - The caller supplies **already-computed** statistics: `x` = effect/log₂FC, `y` = `-log10(p)`.
34
+ The chart does not run the test.
35
+ - `significanceThreshold` is in **`-log10(p)`** units (1.301 = p 0.05; 2 = p 0.01). State the test
36
+ basis in `yLabel`.
37
+ - The chart partitions points by the two thresholds and labels the top-N hits — keep `labelTopN`
38
+ small (≤ 15) to avoid clutter.
39
+
40
+ ## Page/adapter example (agent reference)
41
+ ```tsx
42
+ 'use client'
43
+ import { VolcanoPlot } from '@/components/charts/generic'
44
+
45
+ // genes: { name, log2FC, pValue }[]
46
+ export default function DiffExpressionVolcano({ genes }: { genes: { name: string; log2FC: number; pValue: number }[] }) {
47
+ return (
48
+ <VolcanoPlot
49
+ points={genes.map(g => ({ x: g.log2FC, y: -Math.log10(g.pValue), label: g.name,
50
+ meta: { 'p-value': g.pValue.toExponential(2) } }))}
51
+ xLabel="log₂(Fold Change)" yLabel="-log₁₀(p-value)"
52
+ foldChangeThreshold={1} significanceThreshold={1.301}
53
+ upLabel="Up-regulated" downLabel="Down-regulated" labelTopN={10}
54
+ />
55
+ )
56
+ }
57
+ ```
58
+
59
+ ## Scaffolds when selected
60
+ - generic `VolcanoPlot` + `app/volcano/page.tsx` + nav tab + optional adapter.
61
+
62
+ ## Related
63
+ - [[charting-standards.domain]] · [[component-contracts.domain]] · [[clean-architecture.domain]]
@@ -0,0 +1,80 @@
1
+ # Charting Standards — UI Visualization Domain
2
+
3
+ > The base Plotly wrapper, theme, and rendering rules every chart depends on. NON-NEGOTIABLE.
4
+ > Commands: `/aw-spec-plan`, `/aw-spec-tasks`, `/aw-spec-implement`.
5
+
6
+ ## Single base wrapper
7
+
8
+ - **All** charts render through one component: `components/charts/PlotlyChart.tsx`. No chart imports
9
+ `plotly.js` directly.
10
+ - Plotly is loaded via **dynamic import inside `useEffect`** (SSR-safe — Plotly touches `window`).
11
+ Never import it at module top level; never render it in a Server Component.
12
+ - The wrapper exposes a shared `BASE_LAYOUT`, `BASE_CONFIG`, and `PHARMA_COLORS` palette that every
13
+ generic chart spreads over its own layout.
14
+ - **Responsive fill:** when a chart is given no explicit `height`, it passes `fillHeight` and the
15
+ wrapper sizes to the parent (`height: 100%`); when given a number, that wins. Charts therefore
16
+ fill a flex card without manual measuring.
17
+
18
+ ## Canonical base wrapper (agent reference)
19
+
20
+ ```tsx
21
+ // components/charts/PlotlyChart.tsx
22
+ 'use client'
23
+ import { useEffect, useRef } from 'react'
24
+
25
+ export const PHARMA_COLORS = ['#00d4b4','#3b82f6','#8b5cf6','#f59e0b','#ef4444','#10b981','#f97316','#ec4899']
26
+ export const BASE_LAYOUT = {
27
+ paper_bgcolor: '#0a1628', plot_bgcolor: '#0a1628',
28
+ font: { color: '#8ba3c7', family: 'Inter, system-ui, sans-serif', size: 11 },
29
+ margin: { t: 30, r: 20, b: 50, l: 60 },
30
+ xaxis: { gridcolor: 'rgba(59,130,246,0.10)', zerolinecolor: 'rgba(59,130,246,0.10)' },
31
+ yaxis: { gridcolor: 'rgba(59,130,246,0.10)', zerolinecolor: 'rgba(59,130,246,0.10)' },
32
+ hoverlabel: { bgcolor: '#0f1e38', bordercolor: 'rgba(0,212,180,0.3)', font: { color: '#e2ecff' } },
33
+ }
34
+ export const BASE_CONFIG = { displayModeBar: true, displaylogo: false, responsive: true }
35
+
36
+ interface Props { data: unknown[]; layout?: Record<string, unknown>; config?: Record<string, unknown>; className?: string; fillHeight?: boolean }
37
+
38
+ export default function PlotlyChart({ data, layout = {}, config = {}, className, fillHeight = false }: Props) {
39
+ const ref = useRef<HTMLDivElement>(null)
40
+ useEffect(() => {
41
+ if (!ref.current) return
42
+ const el = ref.current; let cancelled = false
43
+ import('plotly.js-dist-min').then(Plotly => {
44
+ if (cancelled || !el) return
45
+ Plotly.react(el, data, { ...BASE_LAYOUT, ...layout }, { ...BASE_CONFIG, ...config })
46
+ })
47
+ return () => { cancelled = true; import('plotly.js-dist-min').then(P => { try { P.purge(el) } catch {} }) }
48
+ // eslint-disable-next-line react-hooks/exhaustive-deps
49
+ }, [JSON.stringify(data), JSON.stringify(layout)])
50
+ return <div ref={ref} className={className} style={{ width: '100%', height: fillHeight ? '100%' : undefined }} />
51
+ }
52
+ ```
53
+
54
+ ## Generic-chart contract (every chart in `generic/`)
55
+
56
+ 1. `'use client'` at the top; renders only via `PlotlyChart`.
57
+ 2. Accepts an **optional `height?: number`**; spreads `height` into layout only when defined,
58
+ else passes `fillHeight={height === undefined}` and adds `h-full` to the className.
59
+ 3. Builds `data` + `layout` from props, spreading `BASE_LAYOUT`.
60
+ 4. **No domain vocabulary** — all labels/units/colours come from props
61
+ (see [[component-contracts.domain]]).
62
+ 5. Colours default from `PHARMA_COLORS` (rename palette per project; keep the export name stable).
63
+
64
+ ## Theme tokens
65
+
66
+ - Dark "glass" theme: `bg-mesh` background, `glass-card` + `gradient-border` chart cards,
67
+ accent teal `#00d4b4` / purple `#7c3aed`. Tokens live in `globals.css` and `tailwind.config.ts`.
68
+ - Chart text/grid colours come from `BASE_LAYOUT` so every chart matches the shell automatically.
69
+
70
+ ## Rules
71
+
72
+ - Purge the Plotly instance on unmount (the wrapper does this) to avoid leaks on route change.
73
+ - Re-render keys off `JSON.stringify(data/layout)` — keep prop objects stable or memoised for
74
+ large datasets.
75
+ - Never set a fixed pixel height in a page card; let `fillHeight` size to the flex parent.
76
+
77
+ ## Related
78
+ - [[component-contracts.domain]] — the per-chart prop contract built on this base
79
+ - [[clean-architecture.domain]] — the generic ring depends only on this wrapper
80
+ - All `chart-*` rule files build on this base.
@@ -0,0 +1,87 @@
1
+ # Clean Architecture — UI Visualization Domain
2
+
3
+ > Front-end layering for the visualization app. NON-NEGOTIABLE.
4
+ > Commands: `/aw-spec-plan`, `/aw-spec-tasks`, `/aw-spec-implement`.
5
+
6
+ ## Dependency direction
7
+
8
+ Dependencies flow **inward only**, toward the generic chart library:
9
+
10
+ ```
11
+ Page (app/*/page.tsx)
12
+ │ composes
13
+ ▼
14
+ Adapter (components/charts/<Domain>Chart.tsx) ── maps domain data → generic props
15
+ │ depends on
16
+ ▼
17
+ Generic Chart (components/charts/generic/*) ← innermost ring; depends on nothing domain-specific
18
+ ▲
19
+ │ provides data (never imports a chart)
20
+ Data Layer (lib/*, store/*)
21
+ ```
22
+
23
+ The **generic chart library** is the innermost ring — every layer may depend on it; it depends on
24
+ nothing but `PlotlyChart` + the shared palette/theme.
25
+
26
+ ## Layer responsibilities
27
+
28
+ - **Page** (`app/*/page.tsx`) — route surface. Reads data from the store, lays out the chart card,
29
+ passes props to an adapter (or directly to a generic chart). MUST NOT contain Plotly trace
30
+ construction.
31
+ - **Adapter** (`components/charts/<Domain>Chart.tsx`) — translates a **project/domain type**
32
+ (e.g. `Compound[]`, `TrialArm[]`) into a generic chart's props. The **only** place domain
33
+ vocabulary meets a chart (see [[component-contracts.domain]]).
34
+ - **Generic chart** (`components/charts/generic/*`) — builds Plotly traces/layout from
35
+ **caller-supplied data, labels, colours**. Domain-agnostic and reusable across projects.
36
+ - **Data layer** (`lib/*`, `store/*`) — types, parsing, formatting, state. Feeds data **into**
37
+ pages; MUST NOT import chart components.
38
+
39
+ ## Forbidden patterns
40
+
41
+ - Domain logic, project types, or hard-coded domain labels inside `components/charts/generic/`.
42
+ - A page constructing Plotly `data`/`layout` arrays directly (that belongs in a chart/adapter).
43
+ - A generic chart importing from `lib/sample-data`, the store, or any `app/*` route.
44
+ - The data layer importing a chart component (inversion of the dependency rule).
45
+
46
+ ## Canonical example (agent reference)
47
+
48
+ The adapter is the dependency seam — the **page** depends on the **adapter**, the **adapter**
49
+ depends on the **generic chart**; the generic chart knows nothing about the domain:
50
+
51
+ ```tsx
52
+ // Page — app/compounds/page.tsx (composition only)
53
+ 'use client'
54
+ import CompoundScatterPlot from '@/components/charts/CompoundScatterPlot'
55
+ import { useDataStore } from '@/store/data-store'
56
+
57
+ export default function CompoundsPage() {
58
+ const { compounds } = useDataStore()
59
+ return <CompoundScatterPlot compounds={compounds} />
60
+ }
61
+
62
+ // Adapter — components/charts/CompoundScatterPlot.tsx (domain → generic props)
63
+ 'use client'
64
+ import { BubbleChart } from '@/components/charts/generic'
65
+ import type { Compound } from '@/lib/types/pharma'
66
+
67
+ export default function CompoundScatterPlot({ compounds }: { compounds: Compound[] }) {
68
+ const targets = [...new Set(compounds.map(c => c.target))]
69
+ return (
70
+ <BubbleChart
71
+ series={targets.map(t => ({
72
+ seriesLabel: t,
73
+ points: compounds.filter(c => c.target === t).map(c => ({
74
+ x: c.molecularWeight, y: Math.log10(c.ic50_nM),
75
+ size: c.selectivityRatio, label: c.name,
76
+ })),
77
+ }))}
78
+ xLabel="Molecular Weight (Da)" yLabel="log₁₀(IC₅₀, nM)" sizeLabel="Selectivity"
79
+ />
80
+ )
81
+ }
82
+ ```
83
+
84
+ ## Related
85
+ - [[component-contracts.domain]] — adapter prop contract
86
+ - [[charting-standards.domain]] — the `PlotlyChart` base + theme the generic ring depends on
87
+ - [[folder-structure.domain]] · [[state-management.domain]]
@@ -0,0 +1,47 @@
1
+ # Coding Standards — UI Visualization Domain
2
+
3
+ > TypeScript / React / Next.js conventions for the viz front-end. NON-NEGOTIABLE.
4
+ > Commands: `/aw-spec-plan`, `/aw-spec-tasks`, `/aw-spec-implement`, `/aw-spec-analyze`.
5
+
6
+ ## TypeScript
7
+
8
+ - `strict: true`. No implicit `any`; for Plotly's loose trace objects use a single
9
+ `as never[]` / `Record<string, unknown>` at the wrapper boundary, never sprinkled through code.
10
+ - Data contracts are `interface`s in `lib/types/`; chart prop types are exported from each
11
+ generic chart and re-exported from `generic/index.ts`.
12
+ - Prefer `type` unions for closed sets (`'sample' | 'excel' | 'api'`).
13
+
14
+ ## React / Next.js
15
+
16
+ - Any component using hooks, Plotly, the store, or browser APIs is a **Client Component**
17
+ (`'use client'`). Pages that only compose may still be client when they read the store.
18
+ - Charts and Plotly are **never** in Server Components (SSR-unsafe — see [[charting-standards.domain]]).
19
+ - Keep render pure: no `set`/fetch in render bodies; mutations go through store actions
20
+ (see [[state-management.domain]]).
21
+ - Memoise large derived datasets (`useMemo`) before passing to a chart so the wrapper's
22
+ `JSON.stringify` diff stays cheap.
23
+
24
+ ## Naming & layout
25
+
26
+ - Generic charts: PascalCase noun (`Heatmap`, `BubbleChart`). Adapters: domain concept
27
+ (`CompoundScatterPlot`). Routes: kebab-case folder (`dose-response/`).
28
+ - One component per file; co-locate a route's page in `app/<route>/page.tsx`.
29
+ - Import charts from the barrel: `import { Heatmap } from '@/components/charts/generic'`.
30
+
31
+ ## Styling
32
+
33
+ - Tailwind utility classes + the shared `cn()` helper (`clsx`). Theme tokens (glass, gradient,
34
+ accent) come from `globals.css` / `tailwind.config.ts` — don't inline ad-hoc colours that
35
+ fight the chart theme.
36
+ - Chart text/grid colour comes from `BASE_LAYOUT`, not per-page overrides.
37
+
38
+ ## Forbidden patterns
39
+
40
+ - `plotly.js` imported anywhere except inside `PlotlyChart`'s `useEffect`.
41
+ - Domain strings/types inside `components/charts/generic/`.
42
+ - A component calling Zustand `set` directly (use a named action).
43
+ - Fixed pixel chart heights in page cards (use `fillHeight`).
44
+
45
+ ## Related
46
+ - [[charting-standards.domain]] · [[component-contracts.domain]] · [[state-management.domain]] ·
47
+ [[testing.domain]]
@@ -0,0 +1,130 @@
1
+ # UI Visualization Domain — Command → Rule-File Map
2
+
3
+ Per-AW-Spec-command list of the **UIVisualization domain** rule files in this folder.
4
+ Technology standards already auto-load inside each command; the files below are the
5
+ domain-specific ones to load **in addition** for a data-visualization front-end project.
6
+
7
+ - All paths are workspace-relative and live in this folder: `docs/domainspecs/UIVisualization/`.
8
+ - A skill reads this file and loads every path under the matching command heading.
9
+ - `/aw-spec-select-domain UIVisualization` selects this folder as active.
10
+
11
+ ---
12
+
13
+ ## ⚠️ Chart-selection rule (applies to every command below)
14
+
15
+ The `chart-*.md` files are **conditional**. Load the **core** rule files unconditionally; load a
16
+ `chart-<name>.md` **only if that chart is in the developer's selection** (see
17
+ [[domain-requirements]] → *Chart Selection*).
18
+
19
+ - If the requirement says **"all plots" / "all charts" / "all"** → load **all 10** `chart-*` files.
20
+ - If it names a subset → load only those `chart-*` files (match via the selection-token table in
21
+ [[domain-requirements]]).
22
+ - If selection is **unspecified** → `/aw-spec-specify` / `/aw-spec-clarify` MUST ask which charts
23
+ before planning; do not assume "all".
24
+
25
+ The 10 chart files: `chart-heatmap.md` · `chart-bubble.md` · `chart-scurve.md` ·
26
+ `chart-survival.md` · `chart-volcano.md` · `chart-dimred.md` · `chart-parallel.md` ·
27
+ `chart-violin.md` · `chart-network.md` · `chart-trellis.md`.
28
+
29
+ ---
30
+
31
+ ## /aw-spec-constitution
32
+ - docs/domainspecs/UIVisualization/domain-requirements.md
33
+
34
+ ## /aw-spec-specify
35
+ - docs/domainspecs/UIVisualization/domain-requirements.md
36
+ - docs/domainspecs/UIVisualization/ui-viz-terms.md
37
+ - docs/domainspecs/UIVisualization/component-contracts.domain.md
38
+ - docs/domainspecs/UIVisualization/data-source.domain.md
39
+ - (+ selected) docs/domainspecs/UIVisualization/chart-<name>.md ← per selection, or ask
40
+
41
+ ## /aw-spec-clarify
42
+ - docs/domainspecs/UIVisualization/domain-requirements.md
43
+ - docs/domainspecs/UIVisualization/ui-viz-terms.md
44
+ - docs/domainspecs/UIVisualization/component-contracts.domain.md
45
+ - (resolve the chart selection here if not yet specified)
46
+
47
+ ## /aw-spec-plan
48
+ - docs/domainspecs/UIVisualization/folder-structure.domain.md
49
+ - docs/domainspecs/UIVisualization/clean-architecture.domain.md
50
+ - docs/domainspecs/UIVisualization/state-management.domain.md
51
+ - docs/domainspecs/UIVisualization/data-source.domain.md
52
+ - docs/domainspecs/UIVisualization/charting-standards.domain.md
53
+ - docs/domainspecs/UIVisualization/component-contracts.domain.md
54
+ - docs/domainspecs/UIVisualization/coding-standards.domain.md
55
+ - docs/domainspecs/UIVisualization/testing.domain.md
56
+ - (+ selected) docs/domainspecs/UIVisualization/chart-<name>.md ← one per selected chart
57
+
58
+ ## /aw-spec-tasks
59
+ - docs/domainspecs/UIVisualization/folder-structure.domain.md
60
+ - docs/domainspecs/UIVisualization/clean-architecture.domain.md
61
+ - docs/domainspecs/UIVisualization/component-contracts.domain.md
62
+ - docs/domainspecs/UIVisualization/charting-standards.domain.md
63
+ - docs/domainspecs/UIVisualization/state-management.domain.md
64
+ - docs/domainspecs/UIVisualization/data-source.domain.md
65
+ - docs/domainspecs/UIVisualization/coding-standards.domain.md
66
+ - (+ selected) docs/domainspecs/UIVisualization/chart-<name>.md
67
+
68
+ ## /aw-spec-analyze
69
+ - docs/domainspecs/UIVisualization/clean-architecture.domain.md
70
+ - docs/domainspecs/UIVisualization/component-contracts.domain.md
71
+ - docs/domainspecs/UIVisualization/charting-standards.domain.md
72
+ - docs/domainspecs/UIVisualization/coding-standards.domain.md
73
+ - (+ selected) docs/domainspecs/UIVisualization/chart-<name>.md
74
+
75
+ ## /aw-spec-implement
76
+ - docs/domainspecs/UIVisualization/folder-structure.domain.md
77
+ - docs/domainspecs/UIVisualization/clean-architecture.domain.md
78
+ - docs/domainspecs/UIVisualization/state-management.domain.md
79
+ - docs/domainspecs/UIVisualization/data-source.domain.md
80
+ - docs/domainspecs/UIVisualization/charting-standards.domain.md
81
+ - docs/domainspecs/UIVisualization/component-contracts.domain.md
82
+ - docs/domainspecs/UIVisualization/coding-standards.domain.md
83
+ - docs/domainspecs/UIVisualization/testing.domain.md
84
+ - (+ selected) docs/domainspecs/UIVisualization/chart-<name>.md ← one per selected chart
85
+
86
+ ## /aw-spec-fast-implement
87
+
88
+ > Fast path collapsing plan + tasks + analyze + implement into one pass. Deduplicated union of
89
+ > those headings. Load **once** for the whole pass — do not reload per phase.
90
+
91
+ - docs/domainspecs/UIVisualization/folder-structure.domain.md
92
+ - docs/domainspecs/UIVisualization/clean-architecture.domain.md
93
+ - docs/domainspecs/UIVisualization/state-management.domain.md
94
+ - docs/domainspecs/UIVisualization/data-source.domain.md
95
+ - docs/domainspecs/UIVisualization/charting-standards.domain.md
96
+ - docs/domainspecs/UIVisualization/component-contracts.domain.md
97
+ - docs/domainspecs/UIVisualization/coding-standards.domain.md
98
+ - docs/domainspecs/UIVisualization/testing.domain.md
99
+ - (+ selected) docs/domainspecs/UIVisualization/chart-<name>.md
100
+
101
+ ## /aw-spec-minimal-implementation
102
+
103
+ > Single-step set — the per-domain knob. Loads the core charting rules + the selected chart files
104
+ > to implement in one pass. For an audited build use `## /aw-spec-fast-implement`.
105
+
106
+ - docs/domainspecs/UIVisualization/domain-requirements.md
107
+ - docs/domainspecs/UIVisualization/folder-structure.domain.md
108
+ - docs/domainspecs/UIVisualization/clean-architecture.domain.md
109
+ - docs/domainspecs/UIVisualization/charting-standards.domain.md
110
+ - docs/domainspecs/UIVisualization/component-contracts.domain.md
111
+ - docs/domainspecs/UIVisualization/state-management.domain.md
112
+ - (+ selected) docs/domainspecs/UIVisualization/chart-<name>.md
113
+
114
+ ---
115
+
116
+ ## Quick reference (command → core file count, excluding per-chart)
117
+
118
+ | Command | Core domain rule files | + per selected chart |
119
+ |---|---|---|
120
+ | /aw-spec-constitution | 1 | — |
121
+ | /aw-spec-specify | 4 | 1 each |
122
+ | /aw-spec-clarify | 3 | resolve selection |
123
+ | /aw-spec-plan | 8 | 1 each |
124
+ | /aw-spec-tasks | 7 | 1 each |
125
+ | /aw-spec-analyze | 4 | 1 each |
126
+ | /aw-spec-implement | 8 | 1 each |
127
+ | /aw-spec-fast-implement | 8 | 1 each |
128
+ | /aw-spec-minimal-implementation | 6 | 1 each |
129
+
130
+ > "all plots" = +10 chart files. A 3-chart project = +3.