@micha.bigler/ui-core-micha 3.0.1 → 3.1.1

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.
@@ -0,0 +1,198 @@
1
+ # UCM-CHART-14 — The removal was right. The reason on the record is false, and the error message says the opposite of the docblock.
2
+
3
+ - **Repo:** `ui-core-micha`, branch `main`
4
+ - **Tier:** 3 — shared-core. Version **`3.1.1`** (patch — see "Why 3.1.1 and not 4.0.0").
5
+ - **Status:** planned
6
+ - **Workstream:** `CHART-*`
7
+ - **Files:** `src/components/charts/ChartFrame.jsx`, `docs/CHART-LAYOUT.md`,
8
+ `tests/ChartFrame.test.jsx`, `package.json`, and one new dev script + its tests.
9
+
10
+ > **`UCM-CHART-13` shipped the right change for a stated reason that is false.** The mechanics are
11
+ > correct and are not being reopened: `height` and `aspect` are gone, `minHeight` stays,
12
+ > `warnOnChartFrameHeightMismatch` is deleted, and parameterising `assertRemovedChartProp` with
13
+ > `removedIn` was a genuine improvement over what the WO asked for — the error now attributes the
14
+ > right WO instead of always blaming `UCM-CHART-12`.
15
+ >
16
+ > What is wrong is the **justification** recorded alongside it, and one user-visible consequence.
17
+
18
+ ## Part A — Envelope (authoritative WHAT/WHY)
19
+
20
+ ### The three findings
21
+
22
+ **F1 — the shipped consumer measurement is false.** Three places state that nothing passed `aspect`:
23
+
24
+ | where | text |
25
+ |---|---|
26
+ | `ChartFrame.jsx:29-30` (docblock) | "no consumer across the five apps passes it (measured against 3.0.1)" |
27
+ | `docs/CHART-LAYOUT.md` | "it is gone because no consumer across the five apps passed it (measured against 3.0.1)" |
28
+ | commit `676af5c` message | "aspect was applied … but unused by all five consuming apps" |
29
+
30
+ **Four `ChartFrame`s pass `aspect`**, at `origin/main` of fitness-monitor and in its working tree
31
+ right now:
32
+
33
+ ```
34
+ fitness-monitor/frontend/src/pages/BodyHistoryPage.jsx:295 <ChartFrame minHeight aspect>
35
+ fitness-monitor/frontend/src/pages/BodyHistoryPage.jsx:444 <ChartFrame minHeight aspect>
36
+ fitness-monitor/frontend/src/pages/EnvironmentPage.jsx:245 <ChartFrame minHeight aspect>
37
+ fitness-monitor/frontend/src/pages/EnvironmentPage.jsx:279 <ChartFrame minHeight aspect>
38
+ ```
39
+
40
+ Measured 2026-08-22 by parsing JSX opening tags with brace- and string-awareness, across all 13 app
41
+ repos plus ucm. Same scan confirms **hram is clean**: 16 `ChartFrame`s, 11 carrying `minHeight` only,
42
+ zero carrying `aspect` or `height` — so `HRAM-CHT-4` (landed, `4e55d1ae`) is unaffected by this WO.
43
+
44
+ **F2 — the runtime error message states the opposite of the docblock 50 lines above it.**
45
+
46
+ ```js
47
+ // ChartFrame.jsx:79
48
+ 'Removed -- it was never applied to the frame. Use size on the chart inside the frame …'
49
+ ```
50
+
51
+ ```js
52
+ // ChartFrame.jsx:28, the same file
53
+ // it WAS wired to `aspectRatio` on the box at 3.0.1, and worked.
54
+ ```
55
+
56
+ **The four consumers who hit this error are the four whose cards actually change shape**, and the
57
+ message tells them the prop never did anything. Deleting it on that advice is a silent layout change.
58
+ This WO's predecessor argued that "a prop accepted and silently ignored is worse than one that
59
+ errors" — an error that misdescribes what it is guarding is worse than both.
60
+ `tests/ChartFrame.test.jsx:254` repeats the same false claim in a comment.
61
+
62
+ **F3 — `3.1.0` is a minor for removing an applied prop with four live call sites.** The removal is
63
+ breaking, and the minor was chosen *because* of F1. `3.1.0` is published and cannot be unpublished.
64
+ **The remedy is a corrected record and a truthful error message, NOT a compensating major** — see
65
+ below; this was argued the other way first and the operator was right.
66
+
67
+ ### Goal
68
+
69
+ The record matches what was measured, the error message tells the truth to the four callers who will
70
+ see it — and **the consumer count stops being a claim and becomes a command.**
71
+
72
+ ### The actual deliverable: a census, not three corrected sentences
73
+
74
+ `UCM-CHART-12` established the pattern — *the deliverable is the invariant, not the fix*. The
75
+ analogue here is blunt: **this is the sixth wrong consumer count in this series**, and every one of
76
+ them came from a grep.
77
+
78
+ | # | claim | reality |
79
+ |---|---|---|
80
+ | 1 | `UCM-CHART-8`: 3 `aspect` sites in fitness-monitor | 8 hits; `EnvironmentPage` never listed |
81
+ | 2 | "8 call sites" | 4 charts (4 frame+chart pairs) |
82
+ | 3 | `HRAM-CHT-4`: "18 preset files" | 14 files, 19 old-API sites |
83
+ | 4 | "0 consumers pass `aspect`/`height` to `ChartFrame`" | 4 pass `aspect` |
84
+ | 5 | "`aspect` is never applied in `ChartFrame`" | applied at `:139`; a `head`-truncated grep hid it |
85
+ | 6 | `UCM-CHART-13`: "no consumer across the five apps passed it" | the same 4 |
86
+
87
+ Greps cannot see JSX structure: a prop three lines below its component name, an arrow function whose
88
+ `=>` ends the match early, an apostrophe inside a comment, a `{a > b}` in a sibling prop. Every entry
89
+ above is one of those. **Ship the parser, and "measured against X" becomes reproducible output
90
+ instead of a sentence somebody has to trust.**
91
+
92
+ ### Definition of Done
93
+
94
+ - [ ] **`scripts/chart-api-census.mjs`** — takes a workspace root, walks every sibling repo's
95
+ `frontend/src` (falling back to `src/`), and reports per app: every `<ChartFrame>` and every ucm
96
+ chart preset element, with which of `aspect` / `height` / `minHeight` / `margin` / `xAxisAngle`
97
+ each one carries, and file:line. Only counts components actually imported from
98
+ `@micha.bigler/ui-core-micha` — a local `BarChart` of the same name is not a consumer.
99
+ - [ ] **It parses, it does not grep.** Opening-tag scanning must track string literals, template
100
+ literals, `{}` depth, and `//` + `/* */` comments. **A tag it cannot close is reported as
101
+ `UNPARSED`, never skipped and never counted as clean** — a census that silently drops what it
102
+ cannot read is the failure it exists to prevent.
103
+ - [ ] **Its own tests, over fixtures carrying the four traps that actually broke the ad-hoc scans:**
104
+ an arrow function in a prop, an apostrophe inside a JSX comment, nested braces, and a prop on a
105
+ line far below the component name. Each fixture asserts the exact props found.
106
+ - [ ] **`aspect`'s error message rewritten to be true and actionable.** It must say the prop *was*
107
+ applied (`aspectRatio` on the card box, up to 3.0.1), that the card's height now follows its
108
+ content with `minHeight` as the floor, and that a caller who wants the chart taller or shorter
109
+ sets `size` on the chart inside. Do not describe it as never-applied anywhere.
110
+ - [ ] **`height`'s message left as it is** — it *was* genuinely dead, so that one is already true.
111
+ - [ ] **F1's text corrected in all three places** — docblock, `docs/CHART-LAYOUT.md`, and the comment
112
+ at `tests/ChartFrame.test.jsx:254`. Replace "no consumer passed it" with what the census
113
+ reports: four call sites in fitness-monitor, removed by `FM-CHART-1`. **Do not quietly delete
114
+ the sentence** — the point is that a measurement was wrong, and that is worth leaving legible.
115
+ - [ ] **Version `3.1.1`**, with a CHANGELOG entry saying plainly that **`3.1.0` removed an applied
116
+ prop under a minor**, that four call sites were affected, and that the dev-mode error is what
117
+ makes the break loud. Do not publish a compensating `4.0.0`.
118
+ - [ ] **Run the census and paste its output into this WO's register Notiz.** A WO about unverified
119
+ counts that lands with an unverified count is self-refuting.
120
+
121
+ ### Why `3.1.1` and not `4.0.0`
122
+
123
+ **This WO changes no API.** Corrected prose, one error-message string, one dev script that never
124
+ ships. On its own diff it is a patch, and labelling it `4.0.0` would announce a breaking change it
125
+ does not contain.
126
+
127
+ The counter-argument, made first in this WO and **withdrawn**: no consumer has crossed `3.1.0` —
128
+ hram is on `3.0.1` (`HRAM-CHT-4`, landed), fitness-monitor on `2.37.0` committed / `3.0.1` in its
129
+ working tree, jg-ferien on `2.41.1` — so the break is still ahead of all three, and a major would put
130
+ the boundary where they will actually meet it.
131
+
132
+ **What settles it: the break is not silent.** `assertRemovedChartProp` throws on first render in dev
133
+ and names the replacement. The protection a major version buys — "read the notes before upgrading" —
134
+ is already delivered by a hard error at the exact call site, which is strictly better than a version
135
+ number nobody reads. A major would buy a second copy of a signal that already exists, at the cost of
136
+ a version number that lies about its own contents.
137
+
138
+ **This is conditional, and the condition is F2.** The guard is only a safety net if it tells the
139
+ truth. An error saying `aspect` "was never applied" invites precisely the wrong action from the four
140
+ callers whose cards change shape. **`3.1.1` is defensible because F2 is fixed in it — not
141
+ independently of that.** If F2 were deferred, this argument collapses and the major comes back.
142
+
143
+ `3.1.0` may additionally be deprecated on npm (`npm deprecate`, operator-only — a registry mutation).
144
+ Low value here since nobody is on it and `3.1.1` supersedes it immediately; noted as available, not
145
+ recommended.
146
+
147
+ ### Non-goals
148
+
149
+ - **Do not reinstate `aspect`, and do not touch `minHeight`.** The removal stands; only its stated
150
+ reason and its error text are wrong.
151
+ - Do not migrate fitness-monitor's four call sites — `FM-CHART-1` owns them.
152
+ - Do not rewrite history, unpublish `3.1.0`, or publish a compensating `4.0.0`.
153
+ - Do not extend the census beyond chart props. It answers "who passes what to the chart API", not
154
+ "who uses ucm".
155
+
156
+ ### Risks
157
+
158
+ - **The census must stay out of the published package.** It is a dev script: keep it off the
159
+ `exports` map and out of `files`, and confirm the existing `packageTreeShaking` test still passes —
160
+ that test has been flaky under concurrent load before (`UCM-CHART-12`'s note), so a failure there
161
+ needs re-running alone before it is believed.
162
+ - **The census reads sibling repos and must degrade gracefully** when a repo is absent, has no
163
+ frontend, or is a fresh clone — report "not present", never throw. It must never write anything.
164
+ - **`FM-CHART-1` is mid-flight** with fitness-monitor's pin at `3.0.1` and all four `aspect` props
165
+ still in place. Until it lands, the census correctly reports 4 — that is the expected output, not a
166
+ failure. Do not "fix" fitness-monitor from here.
167
+ - The corrected error message will be seen by that session. Getting F2 right is what makes its
168
+ remaining work safe, so **do F2 before anything else in this WO.**
169
+
170
+ ### Tests to WRITE — narrow
171
+
172
+ - `ChartFrame` + `aspect`: the thrown message names `minHeight` and `size`, and **does not contain
173
+ "never applied"**. Assert on content, not just that it throws — `13`'s test matched
174
+ `/ChartFrame.*aspect.*size/s`, which the false message passes.
175
+ - `ChartFrame` + `height`: unchanged, still green.
176
+ - The census fixtures above.
177
+ - Nothing else. `13`'s suite stays as it is apart from the corrected comment and the tightened
178
+ message assertion.
179
+
180
+ No full suite.
181
+
182
+ ---
183
+
184
+ ## Part B — Implementation map
185
+
186
+ > **TO BE FILLED BY THE ORCHESTRATOR** on `git pull`. Must carry: `ChartFrame.jsx:22-35` (docblock)
187
+ > and `:72-81` (the two `assertRemovedChartProp` calls); `assertRemovedChartProp` itself at
188
+ > `chartDefaults.js:566`; the `docs/CHART-LAYOUT.md` "What stays unchanged" block; the test file's
189
+ > `describe` at `:257` and comment at `:254`; the absolute working directory; the progress contract;
190
+ > and the preamble. **Do not dispatch while this placeholder stands.**
191
+
192
+ ---
193
+
194
+ ## Part C — Orchestrator-only
195
+
196
+ > **TO BE FILLED BY THE ORCHESTRATOR.** Review routing (Tier 3: `reviewer` + `ui_reviewer`
197
+ > concurrent), register maintenance including the pasted census output, publish verification for
198
+ > `3.1.1`, commit, and the execution directive with its self-address guard.