@fasl-work/caos-app-shell 0.19.6 → 0.19.7
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.
- package/CHANGELOG.md +1237 -0
- package/README.md +6 -1
- package/VERSION +1 -0
- package/package.json +4 -2
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,1237 @@
|
|
|
1
|
+
## [0.19.007] - 2026-10-29
|
|
2
|
+
|
|
3
|
+
### Fixed
|
|
4
|
+
|
|
5
|
+
- The version numbering reads as one release everywhere. npm showed only the semver form (`0.19.6`) while the tags, `VERSION`, the CHANGELOG and the README badge showed the display form (`0.19.006`), and nothing on the npm page said they were the same release: the package shipped neither `VERSION` nor the CHANGELOG. The package now carries both, the README shows the npm badge beside the release-tag badge and states the two spellings, and [`docs/09_versions.md`](docs/09_versions.md) maps every version published on npm to its display form, its tag and its commit, with the numbers that never reached npm (0.04.000; 0.06.009 to 0.06.012) and why. The npm uploads that had no tag (0.1.1, 0.1.2, 0.6.0 to 0.6.4) are tagged at the commit npm records for them; no published tag was moved or deleted. `docs/08_releasing.md` and the SDD state how a release reaches npm today: with the owner's direct-publish token from a clean clone of the tag, because `publish-npm.yml` has never published (every run answered E404 on upload: no Trusted Publisher is configured on the package page). Found by Felipe on 2026-10-29 ("why the numbering is not coherent"); SHR-001 to SHR-004. A product adopting it changes nothing but its pin.
|
|
6
|
+
|
|
7
|
+
## [0.19.006] - 2026-10-28
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- The footer marks the product licence `translate="no"`: a licence identifier is a name, not a quantity, and an SPDX id that carries a version (Apache-2.0, GPL-3.0, CC-BY-4.0) was read as a number with a decimal point by gate G11 on every Spanish page, and could be mangled by browser translation. The licence text is unchanged, the deprecated `footer.license` path gets the same attribute, and no other footer text is marked (base defect BD-1, found by CEFOP_DinHot on 2026-10-28; SHF-037).
|
|
12
|
+
|
|
13
|
+
## [0.19.005] - 2026-10-27
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- A product opts the notes of its filling cards out of the 35% cap with `data-caos-note-fit` on any ancestor, or `noteFit` on a `CaseWorkbench`, which marks its root: at 1280 px and wider, where the body keeps the stage floor, the note takes the height it needs and shrinks and scrolls in its own box only where the drawing needs its floor; below 1280 px the cap stays. CAOS_Contraste's C04 notes are data the reader needs whole, and the cap cut 9 to 117 px of them while the product could not restyle `.caos-plot-note` (the template's web-baseline guard refuses that) (known shell defect 46; SHC-101).
|
|
18
|
+
|
|
19
|
+
## [0.19.004] - 2026-10-27
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- A lane badge in the workbench rail wraps inside the rail: the Spanish replay label of 0.19.3 ("Reproduce el resultado precalculado") is wider than the 248 px rail and, with `nowrap`, spilled out of it and widened it, so G5 reported "rail element(s) outside the rail" and the case select cut 14 px of content. A badge outside the rail keeps `nowrap` (known shell defect 44; SHW-044).
|
|
24
|
+
- Gate G6 judges a drawing only by the part of it inside the viewport, and only when that part is at least the drawing's minimum size (16 px for a canvas or a table, 48 px otherwise). A table card with 5 px of its body inside the fold of a 390 x 844 page was called blank ("table, 337x5 is blank") from a sliver of padding while it renders whole once scrolled to (CAOS_Contraste full gate; SHG-075). A blank drawing inside the viewport still fails.
|
|
25
|
+
|
|
26
|
+
## [0.19.003] - 2026-10-27
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
|
|
30
|
+
- The shell's own labels read in Spanish on a Spanish page: the lane badges say "Reproduce el resultado precalculado" and "Solo precalculado" instead of "offline", and a reference without a DOI is linked as "enlace" instead of "link" (CAOS_Contraste capture review U16-R3, batches c17 and c24; SHT-011).
|
|
31
|
+
|
|
32
|
+
## [0.19.002] - 2026-10-25
|
|
33
|
+
|
|
34
|
+
### Fixed
|
|
35
|
+
|
|
36
|
+
- Gate G5 now distinguishes controls inside a static content `<header>` from controls inside the sticky site header. The covered viewport area is computed from the actual sticky or fixed header, so document source links remain reachable in the tablet regression (SHG-074).
|
|
37
|
+
|
|
38
|
+
## [0.19.001] - 2026-10-24
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
|
|
42
|
+
- A filling `PlotCard` on a narrow screen (900 px and below) whose body holds flowing content takes the height of that content and scrolls sideways, instead of the 260 to 440 px clamp with hidden overflow that cut whole tables and their right columns at 390 px (CAOS_Contraste U16-R2b, eight review batches; SHC-100). Flowing content is a table that is the body's own child, or any element marked `data-caos-flow` (a stack of a drawing and its tables, a table in a scroll box, panels of small multiples); a body that holds a drawing alone keeps the clamp; nothing changes at 1280 px. Products stop restyling `.caos-plot-body` to get it (the template's web-baseline guard refuses that).
|
|
43
|
+
- An `.equation` that scrolls sideways on a narrow screen fades its right edge and keeps a gap after its end, so the cut reads as more to scroll to (moved into the shell from CAOS_Contraste, which restyled the shell's class; SHC-100).
|
|
44
|
+
- The time axis of a `UPlotChart` names months and weekdays in the page language (`es-CL`, `en-US`): a Spanish page read uPlot's English "Jan", "Apr" under its dates (CAOS_Contraste U16-R2b c15 M1; SHC-099). New: `dateNames` in the chart's interaction rules.
|
|
45
|
+
|
|
46
|
+
## [0.19.000] - 2026-10-23
|
|
47
|
+
|
|
48
|
+
### Added
|
|
49
|
+
|
|
50
|
+
- Tier A of the interactive-visualization rubric on every shell chart (the Contraste 1.00.000 capture review, U16-R2). On by default, no change at a call site (SHC-063 to SHC-085):
|
|
51
|
+
- `UPlotChart`: zoom by the wheel (while the chart holds the focus, Ctrl or Meta included, and only while that changes the range; otherwise the wheel, and the browser's page zoom, are the page's), by the brush (a drag under 5 px is a click) and by pinch; pan by Shift and drag and by touch; a visible **Reset zoom** control while zoomed, double-click, `0` and Escape; the keyboard model (arrows move the crosshair and its readout, Home and End, `+` and `-`, Shift and the arrows, Enter picks); one tab stop with an accessible name; a hidden data table and a one-line summary; the zoom survives a theme, a language and a size change. New props `title`, `zoomY` and `zoomOff` (the reason zoom is turned off, 12 letters and digits at least).
|
|
52
|
+
- `BarChart`: a crosshair band and a readout per bar (pointer and keyboard), zoom and pan by category (wheel, brush, Shift and drag, pinch, keys), the reset control, the same tab stop, table and summary; new prop `zoomOff`. Its markup is wrapped in `.caos-bars-host`, with the foot (readout and reset control) under the drawing.
|
|
53
|
+
- Gate G20: every chart is a tab stop with a name, a summary (`aria-describedby`) and a table (`aria-details`); driven once per state it moves its crosshair with the arrow keys, zooms with `+` and with a scripted brush, shows one reset control and resets with `0`; a chart that turns zoom off, an empty reason included, is listed among the waivers (a short reason fails). A hand-drawn SVG chart is not measured (`docs/07_gate.md`). Plants `chart-not-focusable`, `chart-no-name`, `chart-no-table`, `chart-no-reset`, `chart-reset-hidden`, `chart-no-zero`, `chart-no-arrows`, `chart-dead-brush`, `zoom-off-empty`, `zoom-off-unexplained` and `bar-repeat-ticks`.
|
|
54
|
+
- Text kit: `niceStepAt`; `repeatedLabels` moves to it (still exported from `chart`); the interaction rules live in `src/chart/interaction.ts`.
|
|
55
|
+
- `BarChart`, the two forms the products still drew by hand (D16-21; SHC-090 to SHC-093), each with the whole of Tier A and no change to a call site that does not use them:
|
|
56
|
+
- Floating bars: `BarDatum.span` gives the bar's two ends on the value axis (a waterfall of layers, a bridge of signed steps). `value` stays the number the bar states; the readout and the table add the ends ("from a to b", From and To columns); a span of zero length is a dot as thick as a bar; ends in any order draw the same bar; a span outside `axis.range` is cut to it; with a span `axis.range` is the axis as given and may exclude zero.
|
|
57
|
+
- Grouped bars: `BarDatum.group` puts consecutive data in one band (side by side when vertical, one under another when horizontal) with the group label printed once, `BarChartProps.legend` draws what each tone means, the readout reads "group, label: value", the table gains a Group column, and the keyboard, zoom, pan and brush go group by group.
|
|
58
|
+
- `UPlotChart`: the labels of x marks and y marks share one set of placed boxes (SHC-094, SHC-095): no x label lies over a y label or another x label (the Contraste U16-R2 forms V04-2 and V16-3), a label that fits no row is cut with an ellipsis and kept whole in the plot's title, the readout and a new table of marks. The host declares `data-mark-overlaps`, `data-mark-boxes` and `data-mark-cut`; `drawMarks` and `drawYMarks` take an optional `boxes` array and `drawMarks` returns the labels it cut.
|
|
59
|
+
- Gate G20 fails a chart whose `data-mark-overlaps` is above 0, and drives the floating and the grouped bars (the walk reaches every bar and reads its ends and its group; the table has From, To and Group; a declared legend is visible); five plants prove it (SHC-096).
|
|
60
|
+
- The re-review of 0.19.0: `BarDatum.format` (optional `FormatOptions`): the format of one bar's value, readout, ends and table cells, over `axis.format` (SHC-097).
|
|
61
|
+
- `placeYLabel` in the chart's interaction rules; `drawYMarks` returns the labels it cut or could not write.
|
|
62
|
+
- The gate's legit page `legit-bar-adoption` (the forms CAOS_Contraste adopted).
|
|
63
|
+
|
|
64
|
+
### Fixed
|
|
65
|
+
|
|
66
|
+
- `BarChart`: a value axis of counts ticked at fractions and rounded them ("0, 1, 1, 2, 2"): it now ticks at whole numbers, and an axis of fixed decimals at multiples of their unit (SHC-078); it declares `data-ticks-repeat` and the gate fails a repeated label under G6, as for `UPlotChart` (SHC-079).
|
|
67
|
+
- The review of 0.19.0 (Opus, 2026-10-22), fixed before the release (SHC-065 to SHC-089):
|
|
68
|
+
- The brush works on every chart form: a parity plot, a chart with an overlay series and one with `x.range` ignored it, because uPlot's own `setScale` turned a fixed range back into the fixed one. The selection is applied through the zoom operations, ordered, inside the full range and not below the least span; the bars and the lines share one 5 px drag threshold.
|
|
69
|
+
- A vertical `BarChart` narrower than its value column draws no negative width and logs no error (it drew `rect` widths of -0.8 at 70 px); at 0 px it draws nothing.
|
|
70
|
+
- Zoomed to its least span, no axis repeats a tick label: an axis of significant digits (depth 1000 to 1490 m read "1,000" ten times) cannot be zoomed below the span its labels can tell apart (`leastLabelSpan`).
|
|
71
|
+
- On `x.time` the data table, the summary and the keyboard readout print dates in the page language, not epoch seconds.
|
|
72
|
+
- A wheel that cannot change the range (a wheel out at the full range, a wheel in at the least span) reaches the page, so a focused chart no longer stops the page from scrolling past it; a focused chart shows a 2 px ring. Ctrl or Meta with the wheel zooms a chart only while it holds the focus; over any other chart it stays the browser's page zoom.
|
|
73
|
+
- `zoomOff` of any text, an empty reason in one language included, sets `data-zoom-off`, and G20 fails an empty or short reason (it passed silently before).
|
|
74
|
+
- New data is drawn even when it differs from the data on show only by a swap of two values or by a change too small for a sum (the fingerprint is replaced by an element-wise `sameData`).
|
|
75
|
+
- The reset control is at least 24 by 24 px; the drawing of a `BarChart` is `role="presentation"` beside the named group (its name was said twice); the plot is described by its summary only and linked to its table by `aria-details`, so a screen reader no longer reads up to 1000 rows on every focus.
|
|
76
|
+
- The re-review of 0.19.0 (Opus, 2026-10-22) and the CAOS_Contraste adoption of the bar forms (U16-F8), fixed before the release (SHC-090 to SHC-098):
|
|
77
|
+
- A dot total at an end of `axis.range` ran past the plot: its value label was cut and the dot covered its category label. With a dot the value axis is inset by its radius at both ends (MJ1).
|
|
78
|
+
- A plain bar beside floating bars, on an axis that excludes zero, was drawn from zero across the category labels: it is cut to the axis (MJ2), and it reads its two ends as the table writes them, so G20 passes a chart that mixes the two (F8-2).
|
|
79
|
+
- A floating or grouped bar that takes a choice (`onSelect`) failed G5: the middle of its box was empty drawing. It is now a target over its whole slot (`rect[data-bar-hit]`) (F8-1).
|
|
80
|
+
- G20's scripted brush dragged a fixed share of the drawing, which on a short horizontal chart of three or four bars spanned every category, so it reported a working brush as dead: it drags between the bars (F8-3). The chart's brush was right.
|
|
81
|
+
- Reference-line labels close together overlapped (they were clamped at the left edge): a y label is placed against the shared boxes, on rows near its line, and cut with an ellipsis when no place clears (`placeYLabel`); G20 names each overlapping pair with its kind, x or y (m1). An x mark with an empty label no longer takes a row.
|
|
82
|
+
- The shell's test of V04-2 drew the same pixels before and after the mark labels of 0.19.0; it now draws Contraste's C04 chart and measures the ink (m2).
|
|
83
|
+
- Grouped members were told apart by colour alone: each is named on the drawing when its slot has room (m4). The summary of a floating chart compared a step with a total: it states the first and the last ends (m5). A highlighted bar with a tone looked like its neighbours: it is outlined (m3).
|
|
84
|
+
- `.prose svg { height: auto }` collapsed KaTeX's square-root SVG to under 2 px, so every root of a documentation page vanished: `.prose .katex svg` keeps its own height (SHC-080).
|
|
85
|
+
- An axis title never cuts: a rotated y title longer than the plot moves above it as a horizontal line, an x title wider than the chart wraps below it, and a `BarChart` title wraps over as many lines as it needs (SHC-081, SHC-082).
|
|
86
|
+
|
|
87
|
+
### Changed
|
|
88
|
+
|
|
89
|
+
- The plot of a `UPlotChart` is now the first tab stop of the chart, before the series key (SHC-052 says so); the brush needs a 5 px drag, so a click that moves a pixel no longer zooms.
|
|
90
|
+
- `UPlotChart` and `BarChart` draw their Tier A markup only once the chart has a size; before that they render as in 0.18.0 (SHC-085).
|
|
91
|
+
- Styles: `styles.css` gains `.caos-bars-host`, `.caos-bars-foot`, `.caos-bars-readout`, `.caos-bars-brush`, `.caos-bars-cursor`, `.caos-chart-axis-title`, `.caos-chart-foot` and `.caos-chart-reset`; `reserved-classes.json` lists them.
|
|
92
|
+
|
|
93
|
+
## [0.18.000] - 2026-10-20
|
|
94
|
+
|
|
95
|
+
### Added
|
|
96
|
+
|
|
97
|
+
- `UPlotChart`: what CAOS_Fragmenta's own wrapper did and the shell's chart could not (CAOS_Fragmenta 0.09.000, BL-042). Each option is off by
|
|
98
|
+
default: a chart that uses none renders and declares as in 0.17.0.
|
|
99
|
+
- Named x ticks, `x.ticks: { value, label: BiText }[]`: the axis ticks exactly at those values and labels each in the page language; the
|
|
100
|
+
readout names an x on a tick by its label (within 1e-9 of the x span; a value listed twice keeps its first label); the host declares
|
|
101
|
+
`data-x-tick-labels` and drops it with the ticks; two ticks with one name, adjacent or not, fail G6, which names the label (SHC-047 to SHC-049, SHC-060, SHC-062).
|
|
102
|
+
- `x.range: [lo, hi]`: the x scale spans at least that range, as `y.range` fixes the y scale, so an end tick's label is not cut; on a log axis a range reaching 0 is ignored alone; on a parity chart it is ignored (SHC-050, SHC-061).
|
|
103
|
+
- `solo`: each entry of the key is a button (`aria-pressed`, Tab, click, Enter or Space) that dims every other series (alpha 0.12, 1 px) and a second
|
|
104
|
+
press releases; the chart is redrawn, not rebuilt; the host declares `data-solo` (SHC-051 to SHC-054). The solo is held by the series key, the new `ChartSeries.id` or else its English label, not by position (SHC-059).
|
|
105
|
+
- `ChartSeries.dots`: a dot at each value of a line, none at a null (SHC-055).
|
|
106
|
+
- A `yMarks` entry may omit `label`: the line is drawn with no label box and nothing reserved for one; a draggable one names its handle "Reference line", numbered when several are draggable (SHC-056, SHC-058).
|
|
107
|
+
- New exports `tickSplits`, `tickLabelAt`, `xScaleRange`, `namedRepeats`, `soloKey`, `soloStyle`, `SOLO_DIM_ALPHA`, `referenceLineName`, type `ChartTick`; the stylesheet gains `.caos-chart-key-button`.
|
|
108
|
+
- The gate fixture has a Categories view of each option and the plants `named-ticks-repeat` and `named-ticks-far`.
|
|
109
|
+
|
|
110
|
+
## [0.17.000] - 2026-10-20
|
|
111
|
+
|
|
112
|
+
### Added
|
|
113
|
+
|
|
114
|
+
- `UPlotChart`: draggable reference lines. A `yMarks` entry takes `drag: { min, max, step? }` and the chart `onYMarkChange(index, y)`; the line carries a slider handle the reader drags or moves with the arrows, Page keys, Home and End, inside its range, and the chart is redrawn, not rebuilt, while it moves (SHC-037 to SHC-041, BL-029). New exports `clampMark`, `nudgeMark`, type `YMarkDrag`; the host declares `data-y-drag`.
|
|
115
|
+
- `UPlotChart`: a `points` series with an `x` of its own is drawn over the plot on its own x values, the axes taking its extent in; the host declares `data-overlay` and `data-overlay-drawn` (SHC-042 to SHC-044, BL-029). New export `overlayExtent`.
|
|
116
|
+
- `parityBox` (the side of the square parity box, SHC-034 and SHC-035), `decadeOnly`; the gate fixture has a Forms view of each new form (a log x axis with a draggable percentile line, measured points on their own sizes and marks apart; a log axis with a draggable limit).
|
|
117
|
+
- Gate: G5 fails a select, in the App or in Focus, whose selected text does not fit the room it leaves, naming the route, the state, the text and
|
|
118
|
+
what was measured: for a case select with the shell's display, a name cut in its box (the real `.cs-select-text` element overflows, as a product
|
|
119
|
+
stylesheet that clamps it or an overflow the wrap cannot break, or the display's own box smaller than the name) and a stale display (the shown name differs from the option the select holds); for
|
|
120
|
+
any other select, a text wider than its content box less the native arrow (measured with a probe select, 0 with `appearance: none`). SHG-072,
|
|
121
|
+
plants `select-cut`, `select-cut-token`, `select-cut-display`, `select-display-stale`, `select-arrow`, `select-focus-rail`, and the pages that must pass,
|
|
122
|
+
`legit-select-two-lines` and `legit-select-three-lines`.
|
|
123
|
+
- Gate: under `--require-focus`, G18 fails a workbench route (`--workbench`) that is not among the measured routes, as 0.16.0 does for a
|
|
124
|
+
surface App route, so a run cannot measure no Focus at all (SHG-073, plant `workbench-route-unwalked`).
|
|
125
|
+
|
|
126
|
+
### Changed
|
|
127
|
+
|
|
128
|
+
- `UPlotChart`: a log x axis labels decades whatever uPlot's tick filter does (`decadeOnly`, SHC-030 to SHC-033, CAOS_APP_SHELL#65): with uPlot 1.6.32 the labels are those of 0.16.0 (it already labelled only the ticks whose mantissa is 1) except a non-decade tick whose mantissa is 1, such as 0.15 on a 0.15 to 15 axis, which loses its label; the host declares the labels shown in `data-log-labels`. An axis whose range holds no power of ten keeps uPlot's labels.
|
|
129
|
+
- The `katex` peer range accepts 0.16 to 0.19 (`^0.16.0 || ^0.17.0 || ^0.18.0 || ^0.19.0`; it was `^0.16.0`, so a product pinning katex 0.19.0,
|
|
130
|
+
its current release, failed `npm ci` with ERESOLVE, CAOS_Fragmenta 0.09.000's dependency round). The shell develops and tests on katex 0.19.0,
|
|
131
|
+
which ships its own types (`@types/katex` dropped). 0.18.0 prefixed katex's internal classes; the classes the shell's stylesheet and the gate
|
|
132
|
+
select (`.katex`, `.katex-display`, `.katex-mathml`) are unchanged in 0.19.0, and the build and every suite pass on it.
|
|
133
|
+
|
|
134
|
+
### Fixed
|
|
135
|
+
|
|
136
|
+
- The workbench's case select no longer cuts a case name (SHW-041, SHW-042, BL-074). Since 0.14.1 the **Focus** control shared the select's
|
|
137
|
+
row and, at 1280x800, a name was cut inside the native select with no ellipsis (CAOS_Fragmenta 0.08.001: "Mina de cob"). The control now ends
|
|
138
|
+
the group tab row, in the slot `Tabs` reserves (`trailing`), as a surface's does since 0.16.0, whatever the case picker (select, chips or
|
|
139
|
+
none); the select takes the rail head's whole width. Measured at 390, 768 and 1280 px: the rail head, the tab row and the panel start are the
|
|
140
|
+
same with and without `focus`. Focus keeps its URL, Escape, exit button and return to the same case, group and sub-view; inside Focus there
|
|
141
|
+
is no control, as before. `CaseSelectorProps.accessory` stays for a product's own control and still shares the select's row.
|
|
142
|
+
- `CaseWorkbench` no longer drops a product's own `cases.accessory` while `focus` is on: in 0.16.0 and before, a select picker with `focus` replaced the
|
|
143
|
+
accessory by the Focus control, so the accessory never showed in the App. It now shows on the select's row, and the Focus control is in the tab row.
|
|
144
|
+
- The case select shows real case names whole (SHW-043; the consumer trial of 0.17.0 at a584b08: CAOS_Fragmenta failed 112 states and CAOS_Contraste 413,
|
|
145
|
+
all `select.cs-select[data-control="case"]`, with names of 202 to 311 px in 181 px of room, such as "Degenerate design: the negative control" at
|
|
146
|
+
241 px and "Corporate PD across 1 to 5 year horizons (planned)" at 311 px; the template passed with short names). `CaseSelector` with
|
|
147
|
+
`layout: 'select'` now shows the selected name whole, at any length, in a display (`.cs-select-display`, `aria-hidden`) with the native
|
|
148
|
+
`select` kept in place on top of it, transparent by colour: the keyboard, the screen reader (accessible name and value) and the native list are
|
|
149
|
+
unchanged. There is no line cap and no ellipsis: the name wraps to the lines it needs and a token wider than the room breaks inside
|
|
150
|
+
(`overflow-wrap: anywhere`); the display is as tall as the longest name of the visible list needs at the current width, measured in the DOM
|
|
151
|
+
(the display's own font, padding and content width) and re-measured when the list, the width or the fonts change, so the rail head never moves
|
|
152
|
+
when the reader switches cases, and a list whose names all fit keeps one line as tall as a plain select. Same in the App rail and the Focus
|
|
153
|
+
rail. The consumer trial of 8e6e254 (CAOS_Fragmenta 8 states, CAOS_Contraste 90, names of 354 and 398 px that need three lines in 182 px) is why
|
|
154
|
+
there is no cap: any cap cuts the next longer name; a product that finds its rail head too tall shortens its names. The display names the case the
|
|
155
|
+
native select holds (the selected case, else the first enabled visible case, as React selects it: a selected id outside the visible source lane no
|
|
156
|
+
longer shows another case than the select). Under forced colours (Windows High Contrast) the native select stays transparent, so its one cut line
|
|
157
|
+
is not painted over the display; the focus ring is the display's alone, on `:focus-visible`.
|
|
158
|
+
|
|
159
|
+
## [0.16.000] - 2026-10-20
|
|
160
|
+
|
|
161
|
+
### Added
|
|
162
|
+
|
|
163
|
+
- Focus mode for a `SurfacePage` App (SHF-031 to SHF-036, BL-068, ADR-0070). `SurfacePage` takes `focus?: boolean | SurfaceFocusConfig`
|
|
164
|
+
(`param`, `onChange`) and each view with a stage takes `TabDef.focus?: boolean | ViewFocusConfig` (`title`, `description`, `hud`,
|
|
165
|
+
`rail`). While the open view is focusable, a **Focus** button ("Focus" / "Enfocar", named "Open this view in focus mode" / "Abrir
|
|
166
|
+
esta vista en modo enfoque", new `FOCUS_TEXT.enterViewLabel`) sits at the end of the tab row, in a slot beside the tab list (`Tabs`
|
|
167
|
+
takes it as `trailing`), never in the head and never inside the `tablist`, with its space always reserved while the surface has `focus`
|
|
168
|
+
and any view sets it: on a view with no stage it is hidden from sight, the accessibility tree and the keyboard (`visibility: hidden`,
|
|
169
|
+
`aria-hidden`, `tabindex=-1`), so the tab row and the head do not move and no row is added. Measured on a headless surface, a
|
|
170
|
+
title-only one, one with title and actions and one with a lede, at 390, 768 and 1280 px: the tab row's top and height and the head's
|
|
171
|
+
height are the same on every view and equal to a surface without `focus`; at 390 px the tabs scroll beside the control. It opens the view in `FocusShell`
|
|
172
|
+
(`landmark={false}`: one `main`), the view as the stage and its `rail` as the parameter column, the title the view's label unless
|
|
173
|
+
given, the HUD per view. The URL holds `?focus=1` beside `?view=`; Escape or the exit button return to the same view and sub-view
|
|
174
|
+
(the view memory `CaseWorkbench` keeps), drop the parameter and return keyboard focus to the Focus button; the page behind is
|
|
175
|
+
`inert`. A link with `focus=1` for a view with no stage, an unknown view, or no view when the first has no stage opens no Focus and
|
|
176
|
+
the parameter is removed. A view with no `rail` leaves the stage the whole frame (`FocusShell` `rail` may now be omitted, class
|
|
177
|
+
`caos-focus-norail`) and keeps its own controls in its body. The frame carries `data-surface-focus`, `data-focus-view` and
|
|
178
|
+
`data-focus-group`; the surface and the frame also carry `data-view-param`, the query parameter that holds the open view (`view`, or the
|
|
179
|
+
product's `deepLinkView` name), which the gate reads. Why: a console App (CAOS_Neuraxis: Tasks, Investigations, Engine) is a `SurfacePage`, and a surface with a
|
|
180
|
+
simulation could not meet ADR-0070 on the shell. Without `focus` a surface renders exactly as in 0.15.0.
|
|
181
|
+
- `useFocusMode(config, { enabled, initialAllowed })`, exported with `FocusMode`, `FocusModeConfig` and `FocusModeOptions`: the one
|
|
182
|
+
Focus behaviour (the URL parameter, Escape, the inert page, keyboard focus in and out, the view memory) that `CaseWorkbench` and
|
|
183
|
+
`SurfacePage` share; for a product with a frame of its own.
|
|
184
|
+
- Gate: G18 on an App that is a surface (SHG-058 to SHG-062). With `--workbench ''` the gate measures the route of the new option
|
|
185
|
+
`--app-route` (default `/app`) as a surface: it opens every view of its tab row, enters Focus from each view that offers the control
|
|
186
|
+
(from its last sub-view; outside the primary mode, from the last such view), and applies the failures it applies to a workbench with
|
|
187
|
+
the view and sub-view in place of the case and the group: another view or sub-view in Focus or after the return, a URL in Focus that
|
|
188
|
+
does not hold `?focus=1` and the view, a `?focus` left in the URL after the return, a page or a rail that scrolls, a tab row that
|
|
189
|
+
wraps, a stage under half the viewport, a stage control under the Focus chrome, a Focus control inside the frame, an exit control that
|
|
190
|
+
does not work, Tab leaving the frame, a `main` inside a `main`, and a Focus control that does not open Focus. With
|
|
191
|
+
`--require-focus` a surface none of whose views offers the control fails with "the surface App (/console) offers no Focus control
|
|
192
|
+
([data-focus-enter]) on any of its 3 view(s)". The fixture gains the route `/console` (a surface with a view with no stage, a view with a
|
|
193
|
+
rail, a HUD and sub-views, and a view with no rail), a clean run of it at 390 and 1280 px in both languages and themes, and sixteen
|
|
194
|
+
plants `surface-focus-*`. The gate also fails (SHG-063 to SHG-066) a surface whose tab row or head moves between views, an Escape that
|
|
195
|
+
does not return (each focusable view is left both by the exit button and by Escape in the primary mode), a Focus URL that drops the
|
|
196
|
+
view parameter whatever its name, and, under `--require-focus` with `--workbench ''`, an App route that is not among the measured
|
|
197
|
+
routes. The fixture gains a headless surface that holds its view in `?mode=` (the shape of CAOS_Neuraxis), which passes.
|
|
198
|
+
- `--spa-fallback` for `caos-shell-gate --serve` (SHG-067): the server answers as nginx does for a single-page app on a VPS
|
|
199
|
+
(`try_files $uri $uri/ /index.html`): an extensionless path that matches no file gets `index.html` with 200; a path with an extension
|
|
200
|
+
that matches no file stays 404, so a missing artifact still fails. Default off: the server still answers as GitHub Pages does. Edge
|
|
201
|
+
paths are documented in `docs/07_gate.md` and tested: a directory with no index answers the app shell, a dot in a directory name
|
|
202
|
+
reads as an extension (404), a missing dotfile answers the app shell (an existing file, a dotfile included, is served as it is), the query string is no part of the path.
|
|
203
|
+
- The Focus frame (workbench and surface) carries `data-focus-param`, the query parameter that holds Focus; G18 reads it instead of the
|
|
204
|
+
literal `focus` (a product that renames it with `param` was failed falsely, and a renamed parameter left after the return passed).
|
|
205
|
+
G18 also fails a surface with Focus that renders a head with no title, lede or actions (an empty head row), and its message for a
|
|
206
|
+
tab row or head that moves between views no longer blames the Focus control. It also fails a tab row taller than its tabs need
|
|
207
|
+
(a taller Focus control in the slot adds height on every view; plant `surface-tall-control`).
|
|
208
|
+
|
|
209
|
+
### Changed
|
|
210
|
+
|
|
211
|
+
- `CaseWorkbench` keeps its Focus behaviour in `useFocusMode`, no longer in its own state and effects. Its DOM, its URL behaviour and
|
|
212
|
+
its tests and plants are unchanged. `FocusShell`'s `rail` prop is optional (a rail is still rendered when one is given).
|
|
213
|
+
`window.__caosGate.focusFacts()` reads a surface App's instrument as well as a workbench's, preferring the workbench, then the Focus
|
|
214
|
+
frame, then the surface, by explicit order.
|
|
215
|
+
- `FocusShell`: `rail={null}` (or no `rail`) now renders no rail column and the frame is one column (class `caos-focus-norail`); before
|
|
216
|
+
it rendered an empty rail column. A direct consumer of `FocusShell` that passed `rail={null}` gets a frame whose stage is the whole
|
|
217
|
+
width; pass an empty element to keep the column. `CaseWorkbench` always passes a rail and is unchanged.
|
|
218
|
+
- `SurfacePage` with `actions={null}` renders no actions element and, with no title or lede, no head (before, a null `actions` rendered an
|
|
219
|
+
empty head row; an `undefined` one was already ignored).
|
|
220
|
+
|
|
221
|
+
### Fixed
|
|
222
|
+
|
|
223
|
+
- A language switch inside Focus no longer loses the reader's sub-view on the return (SHW-040). The view memory keyed a tab row on its
|
|
224
|
+
localized `ariaLabel`, so the key changed with the language; it now keys on the row's kind, its place and its ids. The place is the
|
|
225
|
+
path of the open panels above the row (`PanelPathContext`, provided by `Tabs` and `SubTabs` around their open panel and by the Focus
|
|
226
|
+
frames), so two sub-view rows with the same ids in different groups or views keep separate selections, and a row honours its own
|
|
227
|
+
`initial` (keying on the ids alone would have merged them). This is a defect of Focus on a workbench since 0.14.0, not of the
|
|
228
|
+
surface; it is fixed for both.
|
|
229
|
+
- The DOI of a reference is printed inside `translate="no"` (SHD-086), in the end-of-page references and in the reference list, so G11
|
|
230
|
+
(Spanish numbers) no longer reads the dotted number of an identifier such as `doi:10.1523/ENEURO.0159-20.2020` as a decimal point on a
|
|
231
|
+
Spanish page. A plain number with a decimal point in a Spanish paragraph still fails G11.
|
|
232
|
+
- The bibliographic text of a reference (the citation: title, venue, edition or version, publisher) is printed inside `translate="no"` in
|
|
233
|
+
the end-of-page references block and the reference list (SHD-087): it is the source's own and is never translated, so G11 no longer
|
|
234
|
+
reads `Version 3.4` in a NIST title as a Spanish decimal (about 300 false failures on CAOS_Aerovia's documentation pages). The block
|
|
235
|
+
heading and the `link` label stay translatable; the DOI handling above is unchanged. A plain `3.4` in a Spanish paragraph of the same
|
|
236
|
+
page still fails G11 (plant `decimal-point-plain-34`). The citation text also leaves G19 (values whole), which skips `translate="no"`
|
|
237
|
+
as it does G11; a value in a bibliographic title is not measured either.
|
|
238
|
+
- A `CaseWorkbench`, or a `SurfacePage`, placed inside a `Tabs` panel keeps the reader's sub-view entering and leaving Focus: the Focus
|
|
239
|
+
frames provide the inherited panel path plus the open id (`PanelPathContext`), not an absolute one (found in the re-review before
|
|
240
|
+
the release; no current consumer nests them).
|
|
241
|
+
|
|
242
|
+
### Migration
|
|
243
|
+
|
|
244
|
+
- A product whose App is a `SurfacePage` and that has a simulation or a dynamic scenario (ADR-0070): set `focus` on the `SurfacePage`
|
|
245
|
+
and `focus` on each view with a stage (a simulation, a drawing, a live run; not a list or a form); move that view's controls into its
|
|
246
|
+
`focus.rail` (they stay in its body when it has no rail; the view's content renders in both places, so the product shows the control
|
|
247
|
+
in the body only outside Focus, as the fixture's engine view does); the control sits on the tab row, so the head needs no title or
|
|
248
|
+
actions; then run the gate with `--workbench '' --require-focus` (and `--app-route` when the App route is not `/app`). A
|
|
249
|
+
surface App with no simulation changes nothing; a product whose App is a `CaseWorkbench` changes nothing.
|
|
250
|
+
|
|
251
|
+
## [0.15.000] - 2026-10-15
|
|
252
|
+
|
|
253
|
+
### Added
|
|
254
|
+
|
|
255
|
+
- Gate check G19, values whole (SHG-057, BL-066). In every measured state, a short value written in the page's text must sit on
|
|
256
|
+
one line. A value is a run of characters without breaking whitespace in one text node (U+00A0 and U+202F do not end it), 2 to 16
|
|
257
|
+
characters long once the sentence's own punctuation is stripped from its ends, with a digit, at most 4 letters and no other
|
|
258
|
+
character than digits, signs, separators, currency signs and `% ‰ × °`: `35%`, `0,96`, `US$1.2bn`, `2026-10-15`, `-3,2pp`,
|
|
259
|
+
`ADR-0071`. The probe `window.__caosGate.brokenValues()` cuts each value into segments right after a hyphen, a dash or a slash,
|
|
260
|
+
reads each segment's `Range` and counts the groups of its client rects by top; a segment on more than one line fails the value as `"35%" breaks across 3 lines (<element>)`, also when it is longer than its container,
|
|
261
|
+
and runs in every route, size, theme and language, in the wide-font pass and in Focus mode. Why: shell 0.14.2 fixed a share that
|
|
262
|
+
broke into "3", "5", "%" at 390px on every product's executive view, and none of G5 to G10 saw it, because the pieces are neither
|
|
263
|
+
clipped nor outside their box. Not read: a value split across elements (`<b>35</b>%`), SVG text (G10), canvas text, `code`, `pre`,
|
|
264
|
+
`kbd`, `samp`, KaTeX, `translate="no"` and `aria-hidden` content; `12 %` with a regular space is two runs and may wrap. The
|
|
265
|
+
self-test plant `value-broken` reproduces the pre-0.14.2 row (a shrinking flex value with `overflow-wrap: anywhere`), the plant
|
|
266
|
+
`value-broken-range` cuts `599-653` inside `653`, and the clean fixture passes in every state.
|
|
267
|
+
- Adopting 0.15.0: a product may meet new G19 failures it did not have under 0.14.x. Each names the value and the element: a number,
|
|
268
|
+
percentage, amount or unit that a narrow container, a flex row that lets the value shrink, or `overflow-wrap: anywhere` on a
|
|
269
|
+
parent cuts into pieces. Give the value `white-space: nowrap` (and `flex: none` in a flex row), or write it with U+00A0 between
|
|
270
|
+
the number and its unit where the unit may wrap away. A break right after a hyphen, a dash or a slash is a normal
|
|
271
|
+
line break and passes (the fixture's citation pages `599-653` break at the hyphen at 390px in Spanish and pass); only a break inside
|
|
272
|
+
a segment between those places fails. No shell component or stylesheet changed in this release.
|
|
273
|
+
|
|
274
|
+
### Fixed
|
|
275
|
+
|
|
276
|
+
- `e2e/animated-illustration.test.ts` waits (at most 3 s) for the paused final frame of the SMIL illustration before it measures
|
|
277
|
+
the bar: the shell pauses SMIL at its last frame in an effect and the frame is sampled later, and a slow CI runner read the bar
|
|
278
|
+
at its first frame (80px of 640px). Test only; the component is unchanged.
|
|
279
|
+
|
|
280
|
+
## [0.14.003] - 2026-10-15
|
|
281
|
+
|
|
282
|
+
### Fixed
|
|
283
|
+
|
|
284
|
+
- Focus mode: the stage label no longer covers the stage's controls. On Contraste's C10 at 1280px the title ("Portfolio credit
|
|
285
|
+
capital: ASRF, Vasicek fit, copula MC") wrapped to two lines and the label sat over the open group's sub-tab row, because the
|
|
286
|
+
stage cleared the label by a fixed 4.6rem (6.6rem under 900px). `FocusShell` now measures its overlay chrome (the label, the HUD
|
|
287
|
+
tiles, the actions; a layout effect, one `ResizeObserver`, the `resize` event, values written only when they change) and sets
|
|
288
|
+
three lengths on `.caos-focus-stage`: `--caos-focus-clear-top`, `--caos-focus-clear-bottom` and `--caos-focus-label-bottom`.
|
|
289
|
+
The `CaseWorkbench` focus stage pads by them (4.6rem and 6.6rem remain the fallbacks before the first measurement and in a
|
|
290
|
+
non-browser render), the desktop HUD starts under the measured label instead of at a fixed 104px, and under 900px the stage clears
|
|
291
|
+
a bottom HUD. A product that renders its own instrument in `FocusShell` can use the same properties. No prop changes (SHW-038).
|
|
292
|
+
- Focus mode: the Focus control no longer shows inside Focus. Since 0.14.1 the rail inside the focus frame carried the Focus button
|
|
293
|
+
beside the case select, a control that opens the mode the reader is already in. The focus frame's rail head is now the case
|
|
294
|
+
picker and the variant bar without it, in every layout; a product's own `cases.accessory` still shows, and the App's rail head is
|
|
295
|
+
unchanged (SHW-037).
|
|
296
|
+
- Gate G18 now fails both: a stage control under the Focus chrome (the stage label, the HUD or the Focus actions) and a Focus
|
|
297
|
+
control inside the Focus frame (SHG-056). The self-test plants `focus-chrome-covers` and `focus-enter-inside` prove it, and the
|
|
298
|
+
clean fixture now has a Focus title that wraps at 1280px, so every clean run walks the wrapping path.
|
|
299
|
+
- The repository's CI base-integrity guard judged a tracked `.env` wrongly both ways: a real `.env` passed whenever a root
|
|
300
|
+
`.env.example` was tracked, and a tree whose only example file is nested failed. The step now reads `git ls-files` once and
|
|
301
|
+
tests it on here-strings (`git ls-files | grep -q` also fails at random under pipefail, as the products' CI found); any `.env`
|
|
302
|
+
other than an `.example` file fails. `test/ciGuards.test.ts` runs the step itself on planted trees (red on the old step).
|
|
303
|
+
|
|
304
|
+
## [0.14.002] - 2026-10-15
|
|
305
|
+
|
|
306
|
+
### Fixed
|
|
307
|
+
|
|
308
|
+
- The executive view's "Where it comes from" shares stay whole at phone width: the cause row lets its label wrap anywhere, and its
|
|
309
|
+
squeezed value broke into "3", "5", "%" at 390px (seen on the template's example and on every product's executive view). The value
|
|
310
|
+
no longer shrinks or wraps (`.caos-exec-cause-head > .caos-exec-value`); `e2e/executive-view.test.ts` counts the line boxes of every
|
|
311
|
+
visible value at 390px in both languages (it fails without the fix).
|
|
312
|
+
|
|
313
|
+
## [0.14.001] - 2026-10-15
|
|
314
|
+
|
|
315
|
+
### Fixed
|
|
316
|
+
|
|
317
|
+
- The Focus control of `CaseWorkbench` sits on the case select's row (`CaseSelector` takes an `accessory`, rendered after the select
|
|
318
|
+
in one row, the select shrinking to make room), so the rail head is no taller with it. On a row of its own it added 37px to the
|
|
319
|
+
rail head, and rails with little slack scrolled 6 to 10px (ADR-0071 rule 6: Contraste's C04 and C22, 19 gate failures when it
|
|
320
|
+
adopted 0.14.0). With case chips, or with no case picker, the control keeps a row of its own, as in 0.14.0. The visible word
|
|
321
|
+
("Focus" / "Enfocar") and the accessible name are unchanged (SHW-031).
|
|
322
|
+
|
|
323
|
+
## [0.14.000] - 2026-10-14
|
|
324
|
+
|
|
325
|
+
Flip cards, the card carousel, animated illustrations and Focus mode for the App (CAOS_MANAGE `plans/app-shell/0-14-0-plan.md`,
|
|
326
|
+
backlog BL-060 to BL-063). Additive: a product that changes nothing renders as before, except that the executive view's four
|
|
327
|
+
card groups now flip. The gate gains G16, G17 and G18.
|
|
328
|
+
|
|
329
|
+
### Added
|
|
330
|
+
|
|
331
|
+
- `FlipCard` (exported): a small card whose face shows its title and whose back shows its content after a click, Enter or Space,
|
|
332
|
+
and back again. A real button carries `aria-expanded` and `aria-controls` on each face; keyboard focus moves to the face that
|
|
333
|
+
shows; the hidden face is out of the accessibility tree and the tab order (`aria-hidden` and `inert`) while its content stays in
|
|
334
|
+
the markup; Escape closes; `prefers-reduced-motion: reduce` swaps the faces without the turn; theme tokens only; the face says it
|
|
335
|
+
turns (an icon and a hidden "Show details" / "Mostrar detalles"). The rule of use: SMALL cards only (a title of at most 8 words
|
|
336
|
+
in English and 10 in Spanish, a back of at most 40 and 50), where the reader scans the titles and opens the ones that matter.
|
|
337
|
+
- `CardDeck` (exported): a list of cards plain, as flip cards (`flip`), as a row up to `carouselAbove` cards (default 4) and as a
|
|
338
|
+
carousel above it: as many cards as fit (at least one), previous and next buttons, swipe on touch, arrow keys, Home and End, a
|
|
339
|
+
position ("2 of 5" / "2 de 5"), no autoplay, every card reachable by keyboard, never a sideways scroll of the page or its panel;
|
|
340
|
+
reduced motion removes the slide. With `FLIP_LIMITS`, `FLIP_TEXT`, `DECK_TEXT`, `perPageFor`, `deckWindow` and `deckPosition`.
|
|
341
|
+
- The executive view shows `pain.bearers`, `situation.roles`, `situation.state_of_the_art` and `proposal.four_cs` as flip cards
|
|
342
|
+
(a row of four or fewer, a carousel of five); `context.forces`, `trends.items` and `proposal.actions` stay plain. The data
|
|
343
|
+
contract (`executive.schema.json` 2.0.0) is unchanged.
|
|
344
|
+
- Animated illustrations: an executive illustration (or any figure) may be an SVG with CSS keyframes or SMIL inside the file, a
|
|
345
|
+
gentle loop or a single play of at most ten seconds, theme tokens, labels that stay put, and a `@media (prefers-reduced-motion:
|
|
346
|
+
reduce)` block that shows the static final frame. The shell pauses a SMIL animation at its last frame under reduced motion, and
|
|
347
|
+
`cleanSvg` removes an animation that writes a link or an event handler. `analyseSvgAnimation` and `animationFailures` (in
|
|
348
|
+
`gate/areas.mjs`) are the analysis the template's guard script reuses.
|
|
349
|
+
- Focus mode for the App: `CaseWorkbench` takes `focus` (`true` or `CaseFocusConfig`). A Focus button in the rail head opens the
|
|
350
|
+
selected case's open group in the full viewport through `FocusShell` (the stage is the view, the rail stays), holds `?focus=1`
|
|
351
|
+
beside `?case=` and `?view=`, and returns with Escape or the exit button to the same case, group and sub-view (the open sub-tab of
|
|
352
|
+
each tab row is kept across the frame change). `removeQueryParam`, `FOCUS_TEXT` and `FOCUS_PARAM` are exported; `FocusShell`
|
|
353
|
+
marks `data-focus-shell`, `data-rail` and `data-focus-exit`. The plan named `WorkbenchShell`; the case, group and view live in
|
|
354
|
+
`CaseWorkbench`, so the control is there, and `WorkbenchShell` is unchanged. `WorkbenchLayout` exports its rail body as `RailBody`.
|
|
355
|
+
- The gate: G16 (flip cards and card decks: the size limits, real buttons, Enter and Space, focus, the hidden face out of the
|
|
356
|
+
accessibility tree, the carousel reaching every card without a sideways scroll), G17 (animated drawings: the reduced-motion block,
|
|
357
|
+
ten seconds at most, still under emulated reduced motion) and G18 (Focus mode, entered by clicking for every case and left by the
|
|
358
|
+
exit control and by Escape: the same case and group, no page scroll, the rail without scroll, one tab row); `--require-focus`
|
|
359
|
+
fails an App without a Focus control. 13 plants prove them. The executive-view checks read the back of a flip card and the cards
|
|
360
|
+
a carousel hides, so the floors, the 4 C's and the writing limits still apply to them.
|
|
361
|
+
|
|
362
|
+
### Fixed (review of 0.14.0)
|
|
363
|
+
|
|
364
|
+
- The executive-view checks of the gate are back at their 0.13.1 strength: a flip card's back is read with the card turned, hidden 4 C's and hidden bearers' details fail ADR-0017.2 again; only a card the carousel's window hides is exempt.
|
|
365
|
+
- Focus mode makes the page behind it inert and no longer nests a `main` in the App's `main` (`FocusShell` takes `landmark={false}`).
|
|
366
|
+
- G16 checks that an opened back shows content, that a hidden face keeps no reachable control and that a carousel without controls hides no card; G17 analyses `img` SVG figures and multiplies finite iteration counts; G18 starts from the last group and sub-view, compares both, keeps Tab in the frame and refuses a nested `main`; 10 plants.
|
|
367
|
+
- The carousel's focus guard moves focus to the toggle of the face that shows.
|
|
368
|
+
|
|
369
|
+
### Changed
|
|
370
|
+
|
|
371
|
+
- The fixture product's executive view holds five bearers (a carousel) and an animated `pain` illustration.
|
|
372
|
+
|
|
373
|
+
## [0.13.001] - 2026-10-13
|
|
374
|
+
|
|
375
|
+
### Fixed
|
|
376
|
+
|
|
377
|
+
- `STANDARD_ROUTES` is again App, Introduction, Methodology, Implementation, Experiments, Benchmark: the App is the leftmost
|
|
378
|
+
tab, always (Felipe, 2026-10-13). 0.13.0 had put the Introduction first when the landing moved to it; the landing is
|
|
379
|
+
unchanged (the root and unknown paths open the Introduction's executive view through `Landing`) and no longer moves
|
|
380
|
+
the tabs. A product on 0.13.0 needs no change beyond the version: its header reads the order from `STANDARD_ROUTES`.
|
|
381
|
+
- Every documentation route takes the full width of the page, the Introduction included (Felipe, 2026-10-13: the
|
|
382
|
+
Introduction did not use the full width while Methodology, Implementation, Experiments and Benchmark did): `DocPage`
|
|
383
|
+
always renders the wide document layout; its `wide` prop is kept for compatibility and changes nothing.
|
|
384
|
+
- The order test (`test/workbench.test.tsx`), the navigation end-to-end test (`e2e/landing.test.ts`), requirement SHF-011
|
|
385
|
+
and the docs (`docs/01_structure.md`, `docs/06_executive-view.md`) state the order.
|
|
386
|
+
|
|
387
|
+
## [0.13.000] - 2026-10-13
|
|
388
|
+
|
|
389
|
+
### Changed
|
|
390
|
+
|
|
391
|
+
Every product lands on its executive view, and the view is the standard Felipe set on 2026-10-13 (CAOS_MANAGE `conventions/problem-context-first.md`): an executive frame of the industry's problem, not of the product, never tied to a client and never a pitch. A landing block (the problem's title, a key statement, two or three headline figures with linked sources) sits above five sub-tabs (the pain, the context, the current situation, the trends, the proposal with the 4 C's Choice, Context, Cost and Control), each opening with its key message line and holding its depth floor. Sources are links. The view and every lede take the full width of the document column. BREAKING: `executive.schema.json` 2.0.0 replaces the 0.12.0 fields; the App moves to `/app` (old links forward with their query string), one router edit per product.
|
|
392
|
+
|
|
393
|
+
- The executive view is redefined (schema 2.0.0, breaking): it frames the industry's problem for a decision maker, general,
|
|
394
|
+
never tied to a client and never a pitch (CAOS_MANAGE `conventions/problem-context-first.md`, decided 2026-10-13). The data file
|
|
395
|
+
is `title`, `key_statement`, `headline_figures` (2 or 3: heading, value, unit, source), one object per sub-tab (`pain`,
|
|
396
|
+
`context`, `situation`, `trends`, `proposal`, each with its `key_message` and its supporting fields at the floors of the
|
|
397
|
+
structure as minimum and maximum counts of rows), the three `illustrations` `pain`, `situation` and `proposal`, and `sources`.
|
|
398
|
+
The 0.12.0 fields (`executive`, `organisation`, `initiative`, `why_now`, `vision`, `outcomes`, a top-level `four_cs`,
|
|
399
|
+
`dialogue`) are gone; a product rewrites its `content/executive.json` and its three illustrations (`docs/06_executive-view.md`
|
|
400
|
+
has the fields, the floors and the writing limits).
|
|
401
|
+
- The view shows a landing block (the title, the key statement, the headline figures) above five sub-tabs titled "The pain",
|
|
402
|
+
"The context", "The current situation", "The trends", "The proposal" (Spanish "El problema", "El contexto", "La situación
|
|
403
|
+
actual", "Las tendencias", "La propuesta"), each opening with its key message line, then the numbered linked sources and two
|
|
404
|
+
onward links ("How the work explores this problem", "Open the App"). The sections come from one definition,
|
|
405
|
+
`EXEC_SECTION_DEFS` in `executive.ts`. No rubric label and no rubric question is printed; the gate fails a view that prints one.
|
|
406
|
+
- The 4 C's are required in the proposal: `FOUR_CS` holds Choice, Context, Cost and Control with Felipe's definitions in English
|
|
407
|
+
and Spanish (2026-10-13), `proposal.four_cs` has exactly those four rows in that order, each with `applies` (what the C means
|
|
408
|
+
for the proposal). The pending state of section 3 is gone.
|
|
409
|
+
- Sources are links: each `sources` entry is `{ id, title, url, note? }` with an https `url`; every figure and every claim of the
|
|
410
|
+
state of the art and of the trends cites one by id, every source is cited, and the notes number in the order of first use. The
|
|
411
|
+
validator and the gate fail a source without a url, with a non-https url, over the writing limits, or citing a file name or
|
|
412
|
+
number in place of the link (`file 7`, `archivo 7`, a `.pdf` name, "Published on").
|
|
413
|
+
- Extra rules of the validator, mirrored by the gate on the rendered page: the causes' weights add to at most 100; each action's
|
|
414
|
+
owner is a role of the current situation; a paragraph has at least 25 words; one sentence for the key messages, captions,
|
|
415
|
+
actions and checks, two for the key statement.
|
|
416
|
+
- General, never a client, never a pitch: the validator and the gate fail promotional or client-bound wording ("our client",
|
|
417
|
+
"nuestro cliente", "contact us", "contáctenos", "buy", "comprar", "price", "precio", "offer", "oferta" and their plurals, whole
|
|
418
|
+
words, either case) in any text field; one gate plant per word.
|
|
419
|
+
- Gate: it gathers the facts of every sub-tab it visits (both languages) and checks the landing block, the five sub-tabs, the key
|
|
420
|
+
message lines, every floor on the rendered rows, the 4 C's, the sources, the onward links, the rubric text, the full width and the
|
|
421
|
+
illustrations; about fifty executive plants. The `G5: shrunk-tabs` plant is repaired (below).
|
|
422
|
+
- Full width: the lede of every `DocPage` takes the full width of the document column (the 70ch measure on `.lede` is gone) and the
|
|
423
|
+
executive view takes the full width of the column too (an illustration may stay centred inside its figure). A browser test
|
|
424
|
+
measures both at 1280 and 1600 px; the gate fails a lede or an executive block narrower than the column (plants `lede-narrow`,
|
|
425
|
+
`exec-narrow`). In the shell's own browser harness only the lede was narrow; a narrower Introduction in a product comes from the
|
|
426
|
+
product's own CSS or a non-prose wrapper.
|
|
427
|
+
- Landing (breaking for the router of a product): every product lands on the Introduction with its executive view open. New
|
|
428
|
+
exports `Landing`, `LANDING_ROUTE` and `APP_ROUTE`; `STANDARD_ROUTES` is now Introduction (`/introduction`), App (`/app`),
|
|
429
|
+
Methodology, Implementation, Experiments, Benchmark. A product changes its router once: `/` and `*` render `<Landing />`, `/app`
|
|
430
|
+
renders the App, `fixedRoutes` names `/app`, a static site materialises `app/index.html` (`docs/06_executive-view.md`, The
|
|
431
|
+
landing). An old App link such as `/?case=B2#x` is forwarded to `/app?case=B2#x`. The gate default `--workbench` is `/app`,
|
|
432
|
+
checks that the root opens the Introduction on its executive view and that an old App link keeps its query string and hash
|
|
433
|
+
(plant `landing-app`); its static server keeps the query string through its trailing-slash redirect.
|
|
434
|
+
- The gate plant `G5: shrunk-tabs` failed on develop and on the 0.12.0 release commit in the current Chromium (153.0.8010.12): the
|
|
435
|
+
plant shrinks the tab row with a flex rule, which that Chromium absorbs without overflowing the tabs, so the gate's cut measure
|
|
436
|
+
read zero. The plant now also caps the row's height below its tabs, which reproduces the cut that known shell defect 16 describes;
|
|
437
|
+
the gate's measure is unchanged.
|
|
438
|
+
- The executive view's source notes wrap a long word explicitly (`overflow-wrap: anywhere`, as its facts and why-now
|
|
439
|
+
line already do; BL-053). A long URL in a note was reported to widen a 390 px page by CAOS_Contraste BL-070; the
|
|
440
|
+
overflow was not reproduced in the shell's browser test or in Contraste's build, and the rule makes the wrap explicit
|
|
441
|
+
either way.
|
|
442
|
+
- The executive-view browser test renders the view as products do (a `DocPage` with the two `Tabs` of an
|
|
443
|
+
Introduction) and adds a long-URL note case at 390 px.
|
|
444
|
+
|
|
445
|
+
## [0.12.000] - 2026-10-12
|
|
446
|
+
|
|
447
|
+
### Changed
|
|
448
|
+
|
|
449
|
+
The executive view of every CAOS app is one standard rendered by the shell (CAOS_MANAGE `conventions/problem-context-first.md`): the four sections of Felipe's executive-pitch rubric, verbatim, from one validated data file, with three authored illustrations of the initiative, the problem and the proposed solution.
|
|
450
|
+
|
|
451
|
+
- `ExecutiveView` and `executive.schema.json` 1.0.0: the executive view of every Introduction is now one component fed by the
|
|
452
|
+
product's `content/executive.json` (four sections with Felipe's rubric titles and questions, three inline illustrations,
|
|
453
|
+
numbered source notes). It takes no children; invalid data renders an error state listing each field path. Exports:
|
|
454
|
+
`ExecutiveView`, `validateExecutive`, `FOUR_CS`, `EXECUTIVE_SCHEMA_VERSION`. `FOUR_CS` is empty until Felipe names the 4 C's;
|
|
455
|
+
section 3 shows its declared pending state meanwhile.
|
|
456
|
+
- BREAKING for products: the Introduction areas `initiative`, `outcomes`, `positioning` and `credibility` are removed from
|
|
457
|
+
`DOC_AREAS` and from the gate's table; a section declaring one fails as an unknown area. The executive view cannot be waived.
|
|
458
|
+
- Gate: a new executive-view check on `/introduction` (the view is the shell's `ExecutiveView`, first and default, its data
|
|
459
|
+
valid in the page, the writing limits on the rendered text in both languages, nothing placed beside it, readable fields,
|
|
460
|
+
one source note per figure, and for each illustration: place, caption, inline, loaded, theme tokens only, no `data-chart`,
|
|
461
|
+
labels inside the viewBox and at least 9 px). Self-test plants added (`exec-*`); the plants of the removed areas are replaced.
|
|
462
|
+
- Styles: `.caos-exec*` classes for the view; `reserved-classes.json` regenerated.
|
|
463
|
+
- Docs: `docs/06_executive-view.md`; requirement rows SHD-034 to SHD-047.
|
|
464
|
+
- Package: `executive.schema.json` is published (`files`) and exported as `@fasl-work/caos-app-shell/executive.schema.json`.
|
|
465
|
+
|
|
466
|
+
## [0.11.002] - 2026-10-12
|
|
467
|
+
|
|
468
|
+
### Fixed
|
|
469
|
+
|
|
470
|
+
Found by CAOS_Contraste 0.07.000 on the release gate of shell 0.11.1 (G6 at 138 px, Spanish, 1280x800, wide font):
|
|
471
|
+
|
|
472
|
+
- The filling card's stage floor now holds on the stage itself: at 1280 px and wider the body of a `PlotCard fill` (the
|
|
473
|
+
box the gate measures) keeps at least `--caos-stage-floor` (140 px), so the card grows when its header or its note
|
|
474
|
+
wraps and the containing panel scrolls. 0.11.1 derived a card height from a fixed chrome, which a header wrapping to
|
|
475
|
+
a third line defeated (a 400 px column with a note left 106 px). The browser test now covers cards without a note and
|
|
476
|
+
the narrow column of a three-view row.
|
|
477
|
+
|
|
478
|
+
## [0.11.001] - 2026-10-12
|
|
479
|
+
|
|
480
|
+
### Fixed
|
|
481
|
+
|
|
482
|
+
Found by CAOS_Contraste 0.07.000, whose CI web baseline (correctly) refused the product rule it had needed:
|
|
483
|
+
|
|
484
|
+
- A filling `PlotCard` keeps a minimum height of its own at 1280 px and wider, derived from its layout (the header, the padding and the note's 35% cap), so its drawing keeps the gate's stage floor (140 px) when filling cards share a short column, in every language and in the wide font. Products no longer restyle `.caos-plot.fill` to pass G6. Below 1280 px nothing changes. The gate fixture's Fit tab stacks two filling cards in one column.
|
|
485
|
+
|
|
486
|
+
Adoption: a product drops any rule of its own that gave `.caos-plot.fill` a minimum height (CAOS_Contraste's
|
|
487
|
+
`@media (min-width: 1280px) { .caos-plot.fill { min-height: 23rem; } }`).
|
|
488
|
+
|
|
489
|
+
## [0.11.000] - 2026-10-12
|
|
490
|
+
|
|
491
|
+
### Added
|
|
492
|
+
|
|
493
|
+
The shell's first software design document (ADR-0075) and the gate that holds it to its tests (#100):
|
|
494
|
+
|
|
495
|
+
- `docs/design/SDD.md`: the problem and non-goals, the dimensioning of `src/` measured by a script (45 modules,
|
|
496
|
+
4,251 lines), technology and versions, the public contracts (entries, stylesheets, reserved classes, the `data-*`
|
|
497
|
+
attributes the gate reads, the gate CLI), the components by area, how each component behaves without data, with
|
|
498
|
+
partial data, in error and while loading, verification, versions and adoption, risks, ADR fit.
|
|
499
|
+
- `docs/design/features/<area>/requirements.md`: nine areas, 188 EARS requirements at release, each naming the test or gate
|
|
500
|
+
plant that verifies it; every test file and every plant is cited.
|
|
501
|
+
- `scripts/check_sdd.py` (`npm run check:sdd`, a step of the `guards` job): the ten sections in order, unique
|
|
502
|
+
`SH[DFWCKNTAG]-NNN` ids, SHALL in every statement, and every gate reference resolved to a test defined in the named
|
|
503
|
+
file (comments stripped) or to a plant id in `test/gate-selftest.mjs`; its own tests run in CI too; after an adversarial review it rejects names inside strings, comments or another test's body, skipped and todo tests, `describe` blocks, plain paths, paths outside the repository, malformed rows and stray ids, planned or superseded areas without a reviewed `.status-allow` entry, and SDD headings inside fences or comments.
|
|
504
|
+
- CONTRIBUTING.md and docs/08_releasing.md: a change starts with its requirement row, then a failing test that names
|
|
505
|
+
it, then the code.
|
|
506
|
+
|
|
507
|
+
The required content of the documentation pages, declared by the page and measured by the gate (ADR-0017 section 2.1;
|
|
508
|
+
the core of every product is its tailoring to a real problem, so the Introduction opens for a decision maker):
|
|
509
|
+
|
|
510
|
+
- The Introduction has two views: `executive` first (areas `initiative`, `outcomes`, `positioning`, `credibility`,
|
|
511
|
+
in business language, no equation, every value claim a number with its unit and source) and `technical` (`problem`,
|
|
512
|
+
`principles`, `math` with a symbol glossary, `pipeline`, `honesty`). The executive view cannot be waived.
|
|
513
|
+
- Methodology, Implementation, Experiments and Benchmark each have their named areas and floors (the tables in
|
|
514
|
+
`docs/04_views.md`, from one table, `gate/areas.mjs`).
|
|
515
|
+
- A section declares what it covers: `<DocSection area="...">` (and `kind="classical" | "learned"` for a method).
|
|
516
|
+
New components: `Stat` (a value, its unit, its source), `Question` (a business question and its answer) and
|
|
517
|
+
`Glossary`. `DocPage` takes `floorWaivers`: a floor a page cannot meet is declared with its reason, listed in the
|
|
518
|
+
gate report, and reviewed with the pull request that adds it.
|
|
519
|
+
- The gate fails (`ADR-0017.2`) a page that lacks a required area, or whose area lacks its required content, in either
|
|
520
|
+
language, counting only what a reader can see where the glyphs are painted. The executive view must be the view the
|
|
521
|
+
page opens on; no Introduction content sits outside the two views; a tab list inside a section belongs to that
|
|
522
|
+
section and is judged across every state; a Methodology method cites references; the Benchmark's live panel needs a
|
|
523
|
+
registered control. The language of a page stays a reviewer's duty.
|
|
524
|
+
|
|
525
|
+
Adoption: a product on 0.11.0 fails the gate until its five documentation pages declare their areas and its
|
|
526
|
+
Introduction carries the executive view. Write the executive brief first, in the product's design document
|
|
527
|
+
(CAOS_MANAGE `conventions/problem-context-first.md`; the template's `docs/guides/06_executive-brief.md` and
|
|
528
|
+
`07_documentation-pages.md`), then transcribe it to the page.
|
|
529
|
+
|
|
530
|
+
Contract-first products declare missing data instead of drawing an empty chart (ADR-0080; #99):
|
|
531
|
+
|
|
532
|
+
- The gate accepts an instrument that draws nothing and shows a `data-state="unavailable"` note a reader can see and
|
|
533
|
+
read (its glyphs painted inside the instrument at a legible size, not clipped, not transparent, at least 12 letters or digits in two words). An invisible, clipped or
|
|
534
|
+
empty note, a reason of punctuation, or any drawing element rendered beside the note fails G6, each with its own
|
|
535
|
+
message. The gate checks that a reason exists, not that it is true.
|
|
536
|
+
|
|
537
|
+
The gate self-test grows from 37 to 98 plants, one per check and per trap, with legitimate pages that must pass (a method with its own view tabs, outcomes as a list). Two adversarial reviews tried to break these checks; every case they found is a plant.
|
|
538
|
+
|
|
539
|
+
`yMarks` for reference levels (#94):
|
|
540
|
+
|
|
541
|
+
- A tone per line (`warn`, `bad`, `good`, `neutral`), and a y range that takes every line in, so a level outside the
|
|
542
|
+
data stays in view.
|
|
543
|
+
|
|
544
|
+
### Changed
|
|
545
|
+
|
|
546
|
+
Documentation pages (#96, found on CAOS_Contraste's Methodology):
|
|
547
|
+
|
|
548
|
+
- Text blocks of `.prose` take the full width of the document column; captions keep their measure and stay centred.
|
|
549
|
+
- References are one block at the end of the scope that shows them: the open tab or sub-tab panel, otherwise the end
|
|
550
|
+
of the `DocPage` (`section.caos-doc-references`, each citation once, in the order of first appearance). `DocSection`
|
|
551
|
+
registers its `refs` with the nearest scope instead of rendering a `Refs` row; `ReferenceList` is superseded.
|
|
552
|
+
- The gate's ADR-0017.4 fails a bibliography outside the end-of-page block, a references block that is not last, and
|
|
553
|
+
sections that cite references the page never lists (plants `refs-mid`, `refs-missing`).
|
|
554
|
+
|
|
555
|
+
A filling card (#95):
|
|
556
|
+
|
|
557
|
+
- A `PlotCard fill` note keeps at most 35% of the card and scrolls beyond it.
|
|
558
|
+
- The gate fails a drawing under `--stage-floor` (140 px by default) at 1280 px and above (G6, plant `stage-floor`).
|
|
559
|
+
|
|
560
|
+
### Fixed
|
|
561
|
+
|
|
562
|
+
- Known shell defect 35: a knob's range input kept the user agent's side margins, so at phone widths it ran past a
|
|
563
|
+
clipping card (#91). Products drop their `margin-inline: 0` override.
|
|
564
|
+
- The end-of-page references tests drive Chromium and now run with the browser suite (`e2e/`); develop CI had failed
|
|
565
|
+
since #97 because the unit job installs no browser.
|
|
566
|
+
|
|
567
|
+
## [0.10.000] - 2026-10-08
|
|
568
|
+
|
|
569
|
+
### Added
|
|
570
|
+
|
|
571
|
+
What CAOS_Fragmenta's parity plot still drew on a canvas of its own (CAOS_APP_SHELL#84; CAOS_MANAGE `plans/app-shell`
|
|
572
|
+
BL-029): with these a product draws predicted against measured, its null model and the case the reader picked on
|
|
573
|
+
`UPlotChart`.
|
|
574
|
+
|
|
575
|
+
- `yMarks`: horizontal reference lines, each labelled at its right end above the line, inside the plot, haloed
|
|
576
|
+
(`drawYMarks`; the host declares `data-y-marks`).
|
|
577
|
+
- `ChartSeries.size`: the marker diameter of a `points` series (9 px by default), so the selected case can sit in a
|
|
578
|
+
larger series of its own colour.
|
|
579
|
+
- On a chart whose series are all `points`, the cursor, the readout, `onCursor` and `onPick` take the point nearest the
|
|
580
|
+
pointer in the plane (`nearestPoint`); uPlot alone takes the nearest in x, which on a scatter named a point far above
|
|
581
|
+
or below the pointer. The readout names only the series that have the point.
|
|
582
|
+
- `readout(index)`: the caller's text for the point under the cursor, in place of the list of values (a scatter
|
|
583
|
+
names its case: the blast, its site, its error); `hint`: the readout at rest.
|
|
584
|
+
- A parity plot's range takes in its reference lines, so a null model's level is always in view; its two axes tick
|
|
585
|
+
at one step (uPlot spaces x and y ticks differently, so one range read 25, 30, 35 across and 24, 26, 28 up); filling
|
|
586
|
+
a box taller than it is wide, it is centred down as well as across.
|
|
587
|
+
- Every chart declares how many ticks each axis labels (`data-ticks-x`, `data-ticks-y`).
|
|
588
|
+
- `/chart` exports `drawYMarks` and `nearestPoint`.
|
|
589
|
+
- The gate fixture's parity plot carries a reference line and a selected point; `e2e/parity.test.ts` hovers and
|
|
590
|
+
clicks beside a point whose neighbour in x lies far below it, and reads the reference line off the canvas (it fails
|
|
591
|
+
with the nearest-in-x cursor).
|
|
592
|
+
|
|
593
|
+
### Fixed
|
|
594
|
+
|
|
595
|
+
- The lock file still said 0.9.3 after 0.9.4; it follows `package.json` again.
|
|
596
|
+
|
|
597
|
+
## [0.09.004] - 2026-10-08
|
|
598
|
+
|
|
599
|
+
### Fixed
|
|
600
|
+
|
|
601
|
+
Found by CAOS_Contraste's case C04 and the 0.9.3 gate on its build:
|
|
602
|
+
|
|
603
|
+
- Known shell defect 32: a value on the scientific boundary was written in scientific notation when it was a percent.
|
|
604
|
+
`formatNumber` writes a magnitude below 1e-4 as `1E-5`, and a percent is the value times 100; 1e-6 times 100 is
|
|
605
|
+
9.999999999999999e-5 in binary floating point, so a log axis of PDs in percent labelled its 1e-6 tick `1E-4 %`
|
|
606
|
+
between `0.01 %` and `1 %` (CAOS_Contraste C04, Fitch's generators; #81), and `formatTicks` turned a whole axis
|
|
607
|
+
scientific for the same tick. The boundary is now compared with a relative tolerance of 1e-12: `0.0001 %`; a value
|
|
608
|
+
truly below it (9.99e-5) stays `9.99E-5`. `test/base09.test.tsx` holds both, the percent, the plain value and the
|
|
609
|
+
ticks, in English and Spanish.
|
|
610
|
+
- Known shell defect 33 (#85): the hover rule `.chip:hover:not(:disabled)` outranked `.chip.on`, so the active chip
|
|
611
|
+
under the pointer, the one a reader has just clicked, wrote its label in the text colour on the accent: 3.04:1 in
|
|
612
|
+
the light theme and 1.64:1 in the dark, under G13's 4.5:1 (every rail section the gate clicks on Contraste). The
|
|
613
|
+
case selector's `.cs-chip` lost its accent the same way. The hover rules now leave the active chip alone;
|
|
614
|
+
`e2e/chips.test.ts` hovers the active chip, an inactive one and the chosen case's chip in Chromium in both themes.
|
|
615
|
+
|
|
616
|
+
On adoption: nothing to change; a tick or a cell at exactly 0.0001 % reads in fixed notation, and an active chip keeps
|
|
617
|
+
its colours under the pointer.
|
|
618
|
+
|
|
619
|
+
## [0.09.003] - 2026-10-08
|
|
620
|
+
|
|
621
|
+
### Fixed
|
|
622
|
+
|
|
623
|
+
- A `Knob` in the rail drew its value under its label: the rail's rule for a labelled control
|
|
624
|
+
(`.caos-wb-rail label`, a column) outranked `.caos-knob-head` (a row, the value at the right), so every knob in
|
|
625
|
+
every rail took one more line than it is designed to, since 0.7.0 (CAOS_APP_SHELL#77). Found by the 0.9.1 gate on
|
|
626
|
+
CAOS_Fragmenta, its one failure left of 890 states: at 1280x800 in Spanish with the wide font, a rail of eight design
|
|
627
|
+
variants and three knobs held 710 px in 686 (ADR-0071 rule 6). The rail's rule now leaves the knob head alone; a
|
|
628
|
+
labelled select in the rail still stacks its text above it. `e2e/rail.test.ts` measures both in Chromium.
|
|
629
|
+
|
|
630
|
+
On adoption: a product's rail gains about 25 px per knob; nothing to remove.
|
|
631
|
+
|
|
632
|
+
## [0.09.002] - 2026-10-07
|
|
633
|
+
|
|
634
|
+
### Fixed
|
|
635
|
+
|
|
636
|
+
Found by CAOS_Contraste's case C04 on 0.8.x to 0.9.1:
|
|
637
|
+
|
|
638
|
+
- Known shell defect 31 (#71): a `UPlotChart` log axis whose values reached below about 1e-22 was never drawn. uPlot
|
|
639
|
+
ticks a log axis at 1 to 9 times every power of ten from a precision table that ends there, and below it threw
|
|
640
|
+
"Invalid array length" after stalling the page for several seconds (C04's time-homogeneity p-values of 1e-124 on
|
|
641
|
+
thousands of ratings). Below `LOG_TABLE_FLOOR` (1e-22) a log axis, x or y, now ticks at powers of ten, at most eight
|
|
642
|
+
(`logDecades`), and keeps every label; above it uPlot's own ticks are unchanged. `e2e/charts.test.ts` draws p-values
|
|
643
|
+
down to 1e-124 and 1e-300 on a log y axis and on a log x axis in Chromium with no page error (without the fix every
|
|
644
|
+
case below the floor fails), and reads a year without a group separator in the cursor readout (defect 30). On
|
|
645
|
+
adoption: a product that floored p-values only to keep a chart alive may draw them as they are; a floor for reading
|
|
646
|
+
stays the product's choice.
|
|
647
|
+
|
|
648
|
+
## [0.09.001] - 2026-10-07
|
|
649
|
+
|
|
650
|
+
### Fixed
|
|
651
|
+
|
|
652
|
+
Found by the 0.9.0 gate on CAOS_Fragmenta (2,860 failures in 889 states, most of them the gate's own):
|
|
653
|
+
|
|
654
|
+
- G10 judged a drawing against every ancestor that hides its overflow, the contained `.app-shell` included, which is as
|
|
655
|
+
high as the viewport: every documentation figure below the fold read "lies outside the drawing" (2,470 of the
|
|
656
|
+
failures). A drawing is now judged against the containers between it and its scroll container; what lies beyond the
|
|
657
|
+
scroll container is a matter of scroll position, not a cut.
|
|
658
|
+
- G13 read SVG text against the page behind the drawing, so a label in the page colour on a bar measured 1.06:1. It now
|
|
659
|
+
takes the background from the last filled shape painted under the text's centre, composited over the page.
|
|
660
|
+
- The light `good` (`#197c36`) and `magenta` (`#b93785`) cleared 4.5:1 on every surface but not on the `accent-soft`
|
|
661
|
+
highlight (4.46 and 4.44): a selected row of a table carries its tone text there (Fragmenta's comparison table). The
|
|
662
|
+
test of the palette now counts the highlight as a ground.
|
|
663
|
+
- G13's message named an SVG text's CSS colour instead of the fill it is painted with, so a light label on a red bar
|
|
664
|
+
was reported as dark text; the measure was right, the message misled.
|
|
665
|
+
|
|
666
|
+
The gate fixture carries each case in its clean run: a figure after five documentation sections, values in the page
|
|
667
|
+
colour on the checkpoint bars, a highlighted row with good-tone text. The 0.9.0 gate fails that fixture (G10 2, G13 8);
|
|
668
|
+
0.9.1 passes it.
|
|
669
|
+
|
|
670
|
+
## [0.09.000] - 2026-10-07
|
|
671
|
+
|
|
672
|
+
### Added
|
|
673
|
+
|
|
674
|
+
What CAOS_Fragmenta still carried after 0.8.1 (CAOS_APP_SHELL#65; CAOS_MANAGE `plans/app-shell` BL-027, BL-028): with
|
|
675
|
+
these a product draws its size distributions, its parity plots and a weighted views row on the shell.
|
|
676
|
+
|
|
677
|
+
- `ViewsRow`: views side by side, each in a column the shell owns (a filling card keeps its height chain), the row
|
|
678
|
+
split by `shares` (`[3, 2]`); stacked below 900 px. A product removes its own column wrapper (Fragmenta's
|
|
679
|
+
`.fr-viewcol`).
|
|
680
|
+
- `UPlotChart`: `x.log`, a log x axis that spans the data (uPlot rounds out to the next decade) and leaves the ticks it
|
|
681
|
+
does not label blank; `parity`, predicted against observed on one shared range in a square box with the identity
|
|
682
|
+
line, x unsorted allowed; `onPick(index)`, the point under the cursor on a click. Every index handed back is the
|
|
683
|
+
caller's, also when the chart sorted an unsorted x (`sortOrder`).
|
|
684
|
+
- From the seventh series a repeated colour is dashed, in the plot and in the key (`seriesStyle`).
|
|
685
|
+
- `/chart` exports `seriesStyle`, `sortOrder` and `parityRange`.
|
|
686
|
+
- The gate fixture's Validation has a "Fit" sub-tab: a `ViewsRow` of three fifths and two fifths holding a parity plot
|
|
687
|
+
over an unsorted x (picking on) and a log-x curve; the clean run (G15) measures both.
|
|
688
|
+
|
|
689
|
+
### Fixed
|
|
690
|
+
|
|
691
|
+
- G11 let a number in scientific notation through: "2.7e-08" on a Spanish page writes its decimal with a point, and the
|
|
692
|
+
exponent hid it from the pattern (found on CAOS_Fragmenta's Implementation page). The exponent is now part of the
|
|
693
|
+
number; the `decimal-point` plant carries one.
|
|
694
|
+
- The gate's header-route step (every route reached by a pointer click) let a locator wait its default 30 s and
|
|
695
|
+
throw, which ended the whole run (the 0.9.0 self-test, under load); a link that does not answer in time is now a G5
|
|
696
|
+
failure of its route.
|
|
697
|
+
|
|
698
|
+
## [0.08.002] - 2026-10-07
|
|
699
|
+
|
|
700
|
+
### Fixed
|
|
701
|
+
|
|
702
|
+
- Known shell defect 30 (#62): `formatNumber` grouped every number, so a calendar year on an axis, in a readout or in a
|
|
703
|
+
table read 2,021 (2.021 in Spanish), for every option the type allowed; `time: true` was no way out, since the
|
|
704
|
+
chart's cursor readout still formatted the epoch seconds. `FormatOptions.grouping: false` drops the group separator
|
|
705
|
+
on every path (fixed decimals, significant digits, the integer path), and `formatTicks` and `UPlotChart` pass the
|
|
706
|
+
axis format through, so `x: { format: { decimals: 0, grouping: false } }` writes 2021 on the ticks and in the
|
|
707
|
+
readout, in both languages. The default still groups. Found by CAOS_Contraste's case C04 (rating cohorts 2000 to
|
|
708
|
+
2025). On adoption: a product that counted its years from a base year, or wrote them as text to avoid the
|
|
709
|
+
separator, gives its year axis `grouping: false`.
|
|
710
|
+
|
|
711
|
+
## [0.08.001] - 2026-10-07
|
|
712
|
+
|
|
713
|
+
### Fixed
|
|
714
|
+
|
|
715
|
+
Found by the 0.8.0 gate on the product template's example, the first product on 0.8.0:
|
|
716
|
+
|
|
717
|
+
- `BarChart` filling its card capped its rows at 2.2 times their height, so three horizontal bars took a quarter of a
|
|
718
|
+
tall card and failed the gate's stage-fill floor (G6, 13 to 29 percent against 30). The rows now share the card's
|
|
719
|
+
height; a bar keeps a readable thickness (half its row, at most 40px) with its label centred on it.
|
|
720
|
+
- G10 judged a label against the viewport and a header stuck at its top, so on a phone a chart's first row, scrolled
|
|
721
|
+
under the sticky header by the probe, read as "cut by 4px at the drawing's edge". A label is now judged against its
|
|
722
|
+
drawing and the containers that cut their content (overflow hidden or clip) only; a scroll container and the
|
|
723
|
+
viewport do not cut.
|
|
724
|
+
- G6 reported a table wider than a phone, scrolling inside its card as ADR-0071 rule 3 asks, as "extends past the
|
|
725
|
+
page". A surface inside a box that scrolls sideways ends where that box ends; one cut by a box that hides its
|
|
726
|
+
overflow still fails.
|
|
727
|
+
|
|
728
|
+
The gate fixture's comparison is a horizontal `BarChart` filling its card, and its "Every day" table is wider than a
|
|
729
|
+
phone; the clean run (G15) passes both only with these fixes.
|
|
730
|
+
|
|
731
|
+
## [0.08.000] - 2026-10-07
|
|
732
|
+
|
|
733
|
+
The base defines the structure every product builds on (#59; CAOS_MANAGE `plans/app-shell`, research in
|
|
734
|
+
`wip/template-archetype/base-unify-audit-2026-10-07.md`). A survey of the 89 React frontends of the line found 44 on the
|
|
735
|
+
shell, 43 of them restyling its classes, 15 to 19 writing the same containment for a tab App, 16 to 24 holding their
|
|
736
|
+
tab rows by hand, and 29 carrying their own uPlot wrapper; this release moves those into the shell. Documentation:
|
|
737
|
+
`docs/` (structure, tokens, navigation, views, drawings, icons and numbers, the gate, releasing).
|
|
738
|
+
|
|
739
|
+
### Added
|
|
740
|
+
|
|
741
|
+
- `SurfacePage`, the third route type beside the workbench and the document: a head (title, lede, actions), one row of
|
|
742
|
+
at most six views, the open view filling the viewport under `contain` and scrolling inside it.
|
|
743
|
+
- The open view in the URL: `CaseWorkbench` holds its open group and `SurfacePage` its open view in `?view=`
|
|
744
|
+
(`deepLinkView`); `useUrlView` for a tab row of a product's own.
|
|
745
|
+
- Tokens for type (`--text-*`), space (`--space-*`), radii (`--radius-*`), layout (`--measure`, `--measure-text`,
|
|
746
|
+
`--header-h`, `--rail-w`, `--fade`), icons (`--icon-*`) and z-order (`--z-*`), all in `SHELL_TOKENS`; one breakpoint
|
|
747
|
+
set, 480, 760 and 900 px (and the gate's 1280), exported as `BREAKPOINTS`.
|
|
748
|
+
- `BarChart`, a categorical chart without uPlot: margins measured from the labels, labels broken at a word and then
|
|
749
|
+
shortened with their title, round ticks in one notation, values in the interface language, `highlight`, `tone`,
|
|
750
|
+
`onSelect`.
|
|
751
|
+
- The text kit for a product's own drawings: `textWidth`, `widestLabel`, `fitLabel`, `niceTicks`, `niceStep`,
|
|
752
|
+
`fontFamily` (from CAOS_Fragmenta 0.07.000).
|
|
753
|
+
- `formatTicks` (one notation per axis), `NBSP`, `SCIENTIFIC_BELOW`, the `notation` option of `formatNumber`, the
|
|
754
|
+
type `ShellColorToken`; `/chart` exports `drawMarks`, `tickSteps` and `repeatedLabels`.
|
|
755
|
+
- A skip link to `main#main`, the first keyboard stop of every page.
|
|
756
|
+
- Icons sized by their context: lucide's `svg.lucide` in the header, tabs, sub-tabs, chips, buttons, route links,
|
|
757
|
+
badges, callout titles, plot heads and the console sidebar; a product passes no size.
|
|
758
|
+
- Gate: G10 text in drawings (labels cut, outside the drawing or overlapping, in every declared chart, instrument SVG
|
|
759
|
+
and document figure), with a wide-font pass (Verdana, else DejaVu Sans) at 390 and 1280 px; G11 a decimal point on a
|
|
760
|
+
Spanish page; G12 a vertical sub-tab list that scrolls away; G13 text under WCAG AA contrast; G14 `index.html`
|
|
761
|
+
beside the report, every capture by route with the failures first; options `--wide-font-sizes` and
|
|
762
|
+
`--no-wide-font`. The self-test (G15) plants a defect for each: 34 plants.
|
|
763
|
+
|
|
764
|
+
### Changed
|
|
765
|
+
|
|
766
|
+
- `styles.css` is written in ordered layers (tokens, base, frame, routes, navigation, content, controls, case
|
|
767
|
+
selector, workbench, frames), each class defined in one place (`.tablist` and `.subtablist` were defined twice, the
|
|
768
|
+
second overriding the first); class names are unchanged.
|
|
769
|
+
- Every tab row (`.tablist`, `.subtablist`, the rail's section row) holds its height in any flex column, not only in
|
|
770
|
+
the workbench: a product removes its own `.tablist { flex: 0 0 auto }` and `.tab { flex: 0 0 auto }`.
|
|
771
|
+
- Text blocks inside a document (paragraphs, list items, callouts, captions) keep a 78ch line (`--measure-text`);
|
|
772
|
+
figures, tables and grids keep the width. A product removes its own `max-width: 78ch` on callouts and captions.
|
|
773
|
+
- The faint text colour, and in the light theme `accent-2` and `warn`, were raised to WCAG AA on every surface: the
|
|
774
|
+
faint text read 3.49:1 on the dark raised surface and 4.08:1 on the light one (dark `--color-fg-faint` `#828b97`,
|
|
775
|
+
light `#656d77`; light `--color-accent-2` `#0a7886`, `--color-warn` `#946300`). A unit test computes every pair.
|
|
776
|
+
- `reserved-classes.json` lists `components` (never restyled) and `modifiers` (`on`, `active`, `fill`, `wide`, ...,
|
|
777
|
+
which a product may join to its own class); `classes` keeps both for 0.7 readers. The words read from the
|
|
778
|
+
`@import` lines (`css`) are gone. The gauge legend dot is `.caos-gauge-dot`.
|
|
779
|
+
- The rail's section row fades its hidden end, reveals the open section and takes the arrow keys, Home and End.
|
|
780
|
+
|
|
781
|
+
### Fixed
|
|
782
|
+
|
|
783
|
+
- Known shell defect 26: `html, body { overflow-x: hidden }` computed body's vertical overflow to auto, so body was a
|
|
784
|
+
scroll container that never scrolls and nothing in a scrolling document could stick to the viewport: the site header
|
|
785
|
+
scrolled away on every default-mode page and on a phone. `overflow-x: clip` (with `hidden` as the fallback). Below
|
|
786
|
+
900 px a contained document's page is released in both forms of its rule (the `:has()` form had kept it a scroll
|
|
787
|
+
container).
|
|
788
|
+
- Known shell defect 24 (#55): the vertical sub-tab list is sticky; it stays in view at the end of a long section.
|
|
789
|
+
- Known shell defect 23 (#54): a filling `PlotCard` in a `.caos-views-row` takes an equal share; a product removes its
|
|
790
|
+
wrapper column (CAOS_Fragmenta `.fr-viewcol`).
|
|
791
|
+
- Known shell defect 22: a percent is joined to its sign, and a unit to its value (`Knob`, `Readout`, `Gauge`, the
|
|
792
|
+
chart readout), by a no-break space.
|
|
793
|
+
- Known shell defect 19: an axis writes all its ticks in one notation.
|
|
794
|
+
- Known shell defect 20 (the gate): a control whose inputs are all disabled is not moved by the reactivity check.
|
|
795
|
+
- `UPlotChart` marks: drawn with an explicit left alignment (uPlot left the canvas right-aligned after its y axis, so
|
|
796
|
+
the template's "peak" label sat on the wrong side of its line and ran off the plot near the left edge), on the side
|
|
797
|
+
of the line where they fit inside the plot, on separate rows when they would overlap, with a halo; a mark outside
|
|
798
|
+
the x range is not drawn.
|
|
799
|
+
- `UPlotChart` y axis: measured in the font uPlot draws with at the device pixel ratio; it was too narrow on every
|
|
800
|
+
high-density screen (the gate runs at ratio 1).
|
|
801
|
+
- The gate's truncation check normalised the letter `s` instead of whitespace (`/s+/g`); its pointer probe takes a 1x1
|
|
802
|
+
hidden control (the skip link) for what it is, and scrolls a control clear of a header stuck at the top of the
|
|
803
|
+
viewport; the tab walk does the same before it clicks.
|
|
804
|
+
- `CaseSelector` keeps the router's history state when it writes `?case=` (it replaced it with `null`).
|
|
805
|
+
|
|
806
|
+
### Adoption (ADR-0078 section 5)
|
|
807
|
+
|
|
808
|
+
Pin `0.8.0` exactly. Remove: containment CSS for a tab App (use `SurfacePage`), tab-row flex and wrap overrides, chip
|
|
809
|
+
styling, `max-width: 78ch` on callouts and captions, product wrappers for a views row, label-fitting code that the
|
|
810
|
+
text kit replaces, hand-drawn bar charts (use `BarChart`), icon `size` props. Run the gate: G10 to G13 may report what
|
|
811
|
+
the product carried unseen.
|
|
812
|
+
|
|
813
|
+
## [0.07.003] - 2026-10-06
|
|
814
|
+
|
|
815
|
+
### Fixed
|
|
816
|
+
|
|
817
|
+
- Known shell defect 25: the gate's pointer probe (G5) scrolled an element that fits its scroll container until its
|
|
818
|
+
end showed plus an 8px margin, so an element with less slack than the margin had its start pushed out of the
|
|
819
|
+
container and was reported as never brought into view, by the probe that had moved it (CAOS_Contraste's
|
|
820
|
+
Methodology "Stability" sub-panel: 706.7px in a 712.2px page box at 1280x800, four false failures). The probe now
|
|
821
|
+
scrolls by the smaller of the end's overflow plus the margin and the start's distance from the container's start,
|
|
822
|
+
on both axes (#56). The gate fixture's Methodology gains a "Margins" tab, a focusable region a few pixels shorter
|
|
823
|
+
than the page box below the fold, which the clean run (G15) passes only with the fix.
|
|
824
|
+
|
|
825
|
+
## [0.07.002] - 2026-10-05
|
|
826
|
+
|
|
827
|
+
### Fixed
|
|
828
|
+
|
|
829
|
+
- Known shell defect 21: an axis of integer values (variant numbers, grades, years) formatted with `decimals: 0` got
|
|
830
|
+
uPlot's default tick steps, which include 0.5, 0.25 and 2.5, and the formatter rounded them: CAOS_Contraste's AUC
|
|
831
|
+
chart of seven variants read 1, 2, 2, 3, 3, ..., 7, 7, so every point shared its label with the tick beside it, and
|
|
832
|
+
a grade axis of three points read 1, 1, 1, 2, 2, 2, 2, 3, 3, 3. An axis whose format fixes its decimals now ticks
|
|
833
|
+
only at multiples of the smallest difference its labels can show (scaled by 100 for a percent); a time or log axis
|
|
834
|
+
keeps uPlot's own steps. `test/base07.test.tsx`.
|
|
835
|
+
- The gate could not see a repeated tick (the labels are drawn on a canvas). The chart host now declares
|
|
836
|
+
`data-ticks-repeat`, the ticks whose label repeats the one before, and the gate fails a chart that declares any
|
|
837
|
+
(G6), so an axis formatted by significant digits that still repeats is caught; the self-test plants one
|
|
838
|
+
(`repeat-ticks`, G15).
|
|
839
|
+
|
|
840
|
+
## [0.07.001] - 2026-10-05
|
|
841
|
+
|
|
842
|
+
### Fixed
|
|
843
|
+
|
|
844
|
+
Five base defects, four of them found by the first measured gate run of a product built on 0.7.0 (CAOS_Contraste,
|
|
845
|
+
583 failures in 655 states); each has a test that fails without its fix.
|
|
846
|
+
|
|
847
|
+
- Known shell defect 14: the footer wrote a separator before the build group, whose auto margin moves it to the
|
|
848
|
+
right edge, so a "·" dangled at the end of the left group on every wide screen (found on Fragmenta). The
|
|
849
|
+
separator is gone; the margin separates the two groups. `test/appShellFixed.test.tsx`.
|
|
850
|
+
- Known shell defect 15: `formatNumber` wrote any magnitude in fixed notation, so a p-value of 1e-200 rendered as
|
|
851
|
+
two hundred zeros and one table cell measured 12,790 px. A non-zero magnitude below 1e-4 is now written in
|
|
852
|
+
scientific notation with the requested significant digits (`6.53E-13`, `7,05E-5` in Spanish); a fixed number of
|
|
853
|
+
`decimals` stays the caller's explicit choice. `test/base07.test.tsx` (S8).
|
|
854
|
+
- Known shell defect 16: in the workbench the group row and the sub-tab row are scroll containers, so their automatic
|
|
855
|
+
minimum height is zero, and under a panel taller than the instrument they shrank: the rows were clipped and the
|
|
856
|
+
panel covered the sub-tabs. Both rows keep their height (`flex: none`) and the panel scrolls, and the gate fails a
|
|
857
|
+
tab row that cuts its tabs (G5). `test/base07.test.tsx`; the gate fixture's "Every day" sub-tab and the
|
|
858
|
+
`shrunk-tabs` plant (G15).
|
|
859
|
+
- Known shell defect 17: a chart of several series named them only in the cursor readout, so at rest a reader could
|
|
860
|
+
not tell one line from another. `UPlotChart` now keys every series under the plot when there are two or more: its
|
|
861
|
+
colour, a dashed swatch for a dashed series, a dot for points, and its label; the key wraps.
|
|
862
|
+
`test/base07.test.tsx`.
|
|
863
|
+
- Known shell defect 18 (the gate): the pointer probe judged whether an element fits against the window instead of
|
|
864
|
+
the scroll container it lives in, and aligned a tall element by its end, so a documentation tab panel taller than
|
|
865
|
+
the page's scroll box was reported as "cannot be brought into the viewport" or "covered by" the header. The probe
|
|
866
|
+
now brings a large element in by its start and points at the centre of the part that shows, inside every ancestor
|
|
867
|
+
that clips. The gate fixture's "Notes" tab (taller than the scroll box, shorter than the window) passes clean.
|
|
868
|
+
|
|
869
|
+
## [0.07.000] - 2026-10-04
|
|
870
|
+
|
|
871
|
+
### Added
|
|
872
|
+
|
|
873
|
+
- The workbench primitives, so a product composes its App route instead of re-deriving it (ADR-0016 s9,
|
|
874
|
+
ADR-0017 and ADR-0071 as amended 2026-10-04):
|
|
875
|
+
- `WorkbenchLayout`: a sized control rail beside the instrument on the full viewport (`.page-body.wide`),
|
|
876
|
+
`min-width: 0` down the tree, the instrument marked `data-instrument`; a rail given as sections shows one
|
|
877
|
+
section at a time instead of scrolling (ADR-0071 rule 6).
|
|
878
|
+
- `CaseWorkbench`: the variant bar, then ONE row of at most six question groups in a fixed order (the
|
|
879
|
+
instrument groups, the variant comparison, the context write-up); more than six throws. The live lane is a
|
|
880
|
+
property of each view, shown by its badge.
|
|
881
|
+
- `VariantBar` (one scrollable row of regimes, the active regime's note and lane) and `LaneBadge` (live,
|
|
882
|
+
replay, offline only).
|
|
883
|
+
- `Readout`, `Gauge`, `Verdict` and `PlotCard`, with shared tones.
|
|
884
|
+
- `DocPage` and `DocSection`: the documentation route skeleton; a section ends in its own `Refs`, and a
|
|
885
|
+
section that cites nothing must state why (`noRefsReason`).
|
|
886
|
+
- `pick` and `BiText` for bilingual strings.
|
|
887
|
+
- `ShellConfig.contain`: every route is the viewport; the workbench fills it and a documentation route scrolls
|
|
888
|
+
inside the main container, so the document never scrolls (ADR-0071 rule 1).
|
|
889
|
+
- The design-system CSS for chips (`.chip`, `.chip.on`), the one-row chip strip, the workbench grid, the
|
|
890
|
+
variant bar, lane badges, readouts, gauges, verdicts and plot cards. Products no longer copy it.
|
|
891
|
+
- `caos-shell-gate` (bin): measures a running build at three sizes, both themes and both languages (viewport
|
|
892
|
+
fit, one-row tab bars, a rail without scroll, the instrument at least half of a workbench route, centred prose,
|
|
893
|
+
no bibliography dump, captioned equations, sections with references, the theme applied, no console error) and
|
|
894
|
+
reaches every header route by a real pointer click. `playwright` is an optional peer dependency.
|
|
895
|
+
|
|
896
|
+
- ADR rules enforced at runtime (ADR-0078, "rules live in the base"): an `Equation` without a caption, a citation
|
|
897
|
+
without a DOI or URL, a duplicate citation id, a `Cite` of an unknown id, a `ReferenceList` (banned by
|
|
898
|
+
ADR-0017 s4, now deprecated) and an architecture modal with fewer than five tabs are each reported with
|
|
899
|
+
`console.error`; `caos-shell-gate` fails a page on any console error.
|
|
900
|
+
- `STANDARD_ROUTES`: the six product routes with EN/ES labels, one definition for header, router and gate.
|
|
901
|
+
- `THEME_BOOT_SCRIPT`: the inline pre-paint script that applies the stored theme and language before the first
|
|
902
|
+
frame; `AppShell` keeps `<html lang>` in step with the language toggle (ADR-0011).
|
|
903
|
+
- The base requirements of the 2026-10-04 failure history (S1 to S13, S17, S18), each with a test in
|
|
904
|
+
`test/base07.test.tsx`:
|
|
905
|
+
- S3 `PanelBoundary`: a failing view is contained, named (`data-panel-error`) and reported; every tab panel,
|
|
906
|
+
every `PlotCard` and the shell root sit inside one.
|
|
907
|
+
- S4 `Tabs` and `SubTabs` are controllable (`value`, `onChange`), render only the open panel inside a boundary,
|
|
908
|
+
carry `data-tab` and `data-panel`, report more than six peers, and fade their overflowing edge;
|
|
909
|
+
`TabGroups` puts views under question groups when one row cannot hold them.
|
|
910
|
+
- S7 to S10 the workbench state: `Provenance` (`real`, `synthetic`, `published`) beside the lane on every
|
|
911
|
+
`Readout`, `PlotCard` and workbench group; `makeStateKey` and `useWorkbenchState`, so a view showing data
|
|
912
|
+
for an earlier selection is overlaid as stale; `CaseWorkbench` writes `data-case`, `data-variant`,
|
|
913
|
+
`data-source`, `data-state-key` and `data-replay-only` for the gate.
|
|
914
|
+
- S8 `formatNumber` and `useFormat`: numbers follow the interface language (es-CL decimal comma), and an
|
|
915
|
+
absent or non-finite value reads "not available" instead of `NaN`.
|
|
916
|
+
- S10 `Knob` and `ChipGroup`: the instrument's controls, registered with `data-control` so the gate can check
|
|
917
|
+
that each one changes the state key.
|
|
918
|
+
- S11 `SHELL_TOKENS`, `resolveToken` and `useThemeTokens`: the colour tokens the shell defines, resolved to
|
|
919
|
+
concrete values for canvas and WebGL; `validateArchitectureConfig` checks the modal on mount (at least five
|
|
920
|
+
tabs, inline SVG strings only, only defined tokens, no hex colours, both languages).
|
|
921
|
+
- S12 `UPlotChart` from the separate entry `@fasl-work/caos-app-shell/chart` (with `chart.css`): sized by its
|
|
922
|
+
container, colours resolved from the theme and rebuilt on theme or language change, options compared by
|
|
923
|
+
value, null-safe localised ticks, a y axis sized to its widest label, a cursor readout row instead of the
|
|
924
|
+
clipped legend, and labelled marks. `uplot` is an optional peer dependency.
|
|
925
|
+
- S13 `Stage` and `useStageSize`: an instrument draws only once its box has a size, declares
|
|
926
|
+
`data-drawn`, `data-width` and `data-height`, and reports a stage still at zero size after 1.5 s.
|
|
927
|
+
- S17 `reserved-classes.json`: every class the stylesheet styles, generated at build, for the product guard
|
|
928
|
+
that forbids redefining them.
|
|
929
|
+
- S18 `AppShell` reports a missing router context and names the duplicated-React cause.
|
|
930
|
+
- `@fasl-work/caos-app-shell/keys`: the storage keys (`caos.theme`, `caos.lang`) for the gate and the boot
|
|
931
|
+
script.
|
|
932
|
+
|
|
933
|
+
- The instrument's height chain (failure class 4): `PlotCard fill` takes the height its panel leaves, `.caos-views-row`
|
|
934
|
+
sets filling views side by side, sub-tabs inside a panel pass the height down, and `UPlotChart height="fill"`
|
|
935
|
+
takes its container's height; below 900 px a filling view gets a fixed readable height. Before this, a `Stage`
|
|
936
|
+
inside a `PlotCard` resolved to zero height and never drew.
|
|
937
|
+
- `.caos-table`: tables in views and documents (tabular figures, a header that stays in view).
|
|
938
|
+
- `UPlotChart` series `mode: 'points'` (a scatter of cases over a curve); `.caos-pending` for a view whose data is not
|
|
939
|
+
there yet (it declares `data-state="loading"`); the `BiText` type is exported.
|
|
940
|
+
- `caos-shell-gate` rebuilt as `gate/` (G1 to G9 of the 2026-10-04 history): subject and mode identity with the
|
|
941
|
+
exported storage keys; console, page and HTTP errors; deep links with and without a trailing slash, artifacts
|
|
942
|
+
answered as JSON and a missing asset answered 404, through a built-in server that answers as GitHub Pages does
|
|
943
|
+
(`--serve dist`); boxes inside the viewport and the rail, containers that cut or scroll sideways, truncated text
|
|
944
|
+
without its full text, every control reached by the pointer the way a reader can scroll to it; painted pixels per
|
|
945
|
+
drawing stage and the drawn views covering half the viewport, measured on the screenshot; every route, tab,
|
|
946
|
+
sub-tab and case at 390x844, 768x1024, 1280x800, 1600x900 and 2560x1440, both themes and both languages, waiting
|
|
947
|
+
for declared state; animation frames and mutations at rest; every registered control changing the selection key,
|
|
948
|
+
and the rendered case being the case asked for, by selection and by deep link.
|
|
949
|
+
- G15: the gate's self-test (`npm run test:gate`, a CI job): a fixture product built on this shell passes the full
|
|
950
|
+
matrix clean, and each of 26 planted defects fails the check that owns it.
|
|
951
|
+
|
|
952
|
+
### Changed
|
|
953
|
+
|
|
954
|
+
- `CaseWorkbench` is the whole App route: it renders the layout, puts the case picker (`cases`), the variants and
|
|
955
|
+
the product's `rail` in the rail, and provides the selection key to the rail and the instrument. The per-group
|
|
956
|
+
badge row is gone (each view shows its own lane and provenance); `WorkbenchLayout` takes a `railHead`. The
|
|
957
|
+
workbench spacing is tightened (rail `clamp(248px, 19vw, 340px)`, compact group and sub-tab rows), so the drawn
|
|
958
|
+
views cover half of a 1280x800 viewport.
|
|
959
|
+
- The variant row is a registered control (`data-control="variant"`).
|
|
960
|
+
- `ShellConfig.license` and `ShellConfig.visibility` are required (S5): the footer shows the product's own
|
|
961
|
+
licence with no default, and a private product shows no source link. `ShellConfig.build` adds the build id to
|
|
962
|
+
the footer beside the version, which must be `X.XX.XXX` (S6); both are written as `data-version` and
|
|
963
|
+
`data-build`.
|
|
964
|
+
- `Readout` items take a numeric `value` (or `null`) with a unit or `unitless: true` and are formatted by the
|
|
965
|
+
shell; `lane` and `provenance` are required on `Readout` and `PlotCard`.
|
|
966
|
+
- `CaseSelector` shows each case by name only (the id is written as `data-case`).
|
|
967
|
+
- The architecture modal takes inline SVG strings only; the URL fetch and cache are removed.
|
|
968
|
+
|
|
969
|
+
### Fixed
|
|
970
|
+
|
|
971
|
+
- The document could not scroll on a page taller than the viewport (`html, body, #root { height: 100% }`); it is
|
|
972
|
+
now `height: auto; min-height: 100%` (S1).
|
|
973
|
+
- `[hidden]` lost to component `display` rules and showed hidden panels; it now always hides (S2). Each theme
|
|
974
|
+
declares `color-scheme`, so native scrollbars and form controls follow it.
|
|
975
|
+
- The header navigation pushed the actions off a narrow screen; it shrinks and scrolls at every width.
|
|
976
|
+
Native selects and inputs follow the theme, and sub-tab rows stay on one row.
|
|
977
|
+
- A partly hidden item focused by keyboard in a scrolling row (nav, tab rows, phone footer) is scrolled fully into
|
|
978
|
+
view; the routed nav re-centres its active link on every route change. The contained phone footer stays one row
|
|
979
|
+
with a faded end instead of wrapping into three lines over the instrument.
|
|
980
|
+
- Badges never wrap mid-label; stacked views in a panel keep a gap.
|
|
981
|
+
- A scrolling row reveals the reader's focused item even when a route change re-runs its effect afterwards (the
|
|
982
|
+
late effect had scrolled a focused link back out of view; the navigation e2e caught it as a flaky failure), and
|
|
983
|
+
the reveal is instant.
|
|
984
|
+
- Units are bilingual where they are words (`unit: { en: 'people', es: 'personas' }`) in `Readout`, `Gauge`, `Knob` and the
|
|
985
|
+
chart axes; a Spanish reader no longer meets an English unit. `formatNumber` shows every integer digit of a count
|
|
986
|
+
(27,345, not 27,350); significant digits round only the fraction. `Verdict compact` puts the title and the verdict
|
|
987
|
+
on one row, for a verdict above a drawing.
|
|
988
|
+
- Found by the gate on the product template: `CaseSelector` resolves a `?case=` deep link once an asynchronous case
|
|
989
|
+
list arrives (it adopted on mount only, and wrote the default case into the URL first), and its modified badge
|
|
990
|
+
names the case instead of its id and wraps in the rail; the architecture validation no longer reads a marker
|
|
991
|
+
reference (`url(#dc5-arrow)`) as a hex colour; the gate's reach check tests a fragment of a wrapped inline link,
|
|
992
|
+
not the empty centre of its box. The fixture now loads its cases asynchronously and carries a wrapped link.
|
|
993
|
+
|
|
994
|
+
- `ChromeStrings` typed each value as `string`; with `as const` the English literals made the Spanish table
|
|
995
|
+
unassignable and `tsc` 5.9 failed, which also failed the build that `npm ci` runs.
|
|
996
|
+
|
|
997
|
+
## [0.06.013] - 2026-09-26
|
|
998
|
+
|
|
999
|
+
### Added
|
|
1000
|
+
|
|
1001
|
+
- `publish-npm.yml`: trusted publishing to npm from a GitHub release (OIDC, provenance attached, no token stored).
|
|
1002
|
+
npm no longer issues 2FA-bypass tokens, which is why 0.6.9 to 0.6.12 never reached the registry; this release
|
|
1003
|
+
is the first published since 0.6.8 and carries everything those four entries describe.
|
|
1004
|
+
|
|
1005
|
+
## [0.06.012] - 2026-09-25
|
|
1006
|
+
|
|
1007
|
+
### Added
|
|
1008
|
+
|
|
1009
|
+
- Continuous integration, for the first time in this package: build, the node test suite, and the
|
|
1010
|
+
guards every product repo already carries (no tracked `.env` or `dist/`, no leaked local path,
|
|
1011
|
+
no em-dash or emoji per ADR-0067, the ADR-0074 CI budget gate, and version coherence per
|
|
1012
|
+
ADR-0068). Trunk-only triggers, a concurrency group, a timeout per job.
|
|
1013
|
+
|
|
1014
|
+
### Fixed
|
|
1015
|
+
|
|
1016
|
+
- `VERSION` had stayed at `0.06.008` through three tagged releases while `package.json` moved to
|
|
1017
|
+
`0.6.11`, and `0.06.010` and `0.06.011` had no changelog entry. All four sources now agree, and the
|
|
1018
|
+
two entries below are transcribed from the commits they tag.
|
|
1019
|
+
- Twenty-two em-dashes in comments, docstrings, the README, this changelog and one UI string
|
|
1020
|
+
(`CaseSelector.lockedNote`), replaced per ADR-0067.
|
|
1021
|
+
|
|
1022
|
+
## [0.06.011] - 2026-09-24
|
|
1023
|
+
|
|
1024
|
+
### Fixed
|
|
1025
|
+
|
|
1026
|
+
- On a phone viewport the focus HUD no longer overflows: below 860px it is a four-column grid with
|
|
1027
|
+
ellipsised labels and compact value text instead of a horizontally scrolling flex row.
|
|
1028
|
+
|
|
1029
|
+
## [0.06.010] - 2026-09-24
|
|
1030
|
+
|
|
1031
|
+
### Added
|
|
1032
|
+
|
|
1033
|
+
- `FocusShell`, the shell-owned full-viewport scenario focus frame (ADR-0070): the product supplies
|
|
1034
|
+
its instrument (`stage`), its controls (`rail`), a title, a description and HUD readouts; the shell
|
|
1035
|
+
owns the layout, the language and theme toggles, the exit action, and the phone breakpoint that
|
|
1036
|
+
stacks stage over rail. Exported from the package barrel with its props type and a contract test.
|
|
1037
|
+
|
|
1038
|
+
## [0.06.009] - 2026-09-24
|
|
1039
|
+
|
|
1040
|
+
### Fixed
|
|
1041
|
+
|
|
1042
|
+
- Keep route navigation in the same compact header row on narrow screens, with keyboard-accessible horizontal route scrolling and no document overflow.
|
|
1043
|
+
- Keep complete mobile footer provenance accessible in one horizontally scrollable row instead of consuming instrument height.
|
|
1044
|
+
|
|
1045
|
+
### Changed
|
|
1046
|
+
|
|
1047
|
+
- Build the distributable during Git dependency installation, so a pinned source revision can be consumed while registry publication is unavailable.
|
|
1048
|
+
|
|
1049
|
+
## [0.06.006] - 2026-09-10
|
|
1050
|
+
|
|
1051
|
+
### Fixed
|
|
1052
|
+
|
|
1053
|
+
- The repository link now uses the supported `CodeXml` icon. Lucide 1.x removed the `Github` export, which broke consumer browser builds despite satisfying the shell's declared peer range. The accessible repository link and destination remain intact.
|
|
1054
|
+
- Development validation now uses Lucide 1.43.0, with a browser-bundle regression test that resolves its actual ESM exports instead of externalizing the dependency.
|
|
1055
|
+
|
|
1056
|
+
## [0.06.005] - 2026-09-10
|
|
1057
|
+
|
|
1058
|
+
### Added
|
|
1059
|
+
|
|
1060
|
+
- Optional bilingual `footer.attribution` (or `false`) and `footer.license` let applications use their actual authorship/privacy requirements and code license while retaining the shared shell. Existing consumers keep their previous footer by default.
|
|
1061
|
+
|
|
1062
|
+
## [0.06.004] - 2026-09-06
|
|
1063
|
+
|
|
1064
|
+
### Fixed
|
|
1065
|
+
|
|
1066
|
+
- **A wide table in a vertical sub-tab panel pushed the page past the viewport.** The
|
|
1067
|
+
`.subtabs-vertical` grid used a bare `1fr` panel track, which is `minmax(auto, 1fr)`: the
|
|
1068
|
+
panel's min-content width is the table's width, so the grid sized itself to the table
|
|
1069
|
+
instead of letting the table scroll inside its wrapper (ADR-0071 rule 3). Measured on
|
|
1070
|
+
Porvenir's Datasets tab at 1280x800: the panel column rendered 1380px wide on a 1280px
|
|
1071
|
+
viewport. The track is now `minmax(0, 1fr)`, and `.subtabs`, `.subtabpanels` and
|
|
1072
|
+
`.subtabpanel` carry `min-width: 0` beside `.tabs` and `.tabpanel`.
|
|
1073
|
+
- **On a contained surface (`.app-shell.fixed`) the footer took 178px.** A product's
|
|
1074
|
+
provenance and disclaimer wrapped into five lines at 1600x900 and the instrument fell from
|
|
1075
|
+
56 to 42 percent of the viewport, under the ADR-0071 rule 8 floor. The footer keeps its
|
|
1076
|
+
text (ADR-0016 s2) and is set compact on fixed routes only: two to three lines.
|
|
1077
|
+
|
|
1078
|
+
## [0.06.003] - 2026-09-06
|
|
1079
|
+
|
|
1080
|
+
### Added
|
|
1081
|
+
|
|
1082
|
+
- **`ShellConfig.fixedRoutes` and `ShellConfig.fixed`**, the per-route opt-in to the contained
|
|
1083
|
+
layout ADR-0071 rule 1 requires (the app surface IS the viewport; the one container that
|
|
1084
|
+
owns long content scrolls, the document never does). `styles.css` has carried
|
|
1085
|
+
`.app-shell.fixed` since the containment fix with the note "apps that fill the viewport add
|
|
1086
|
+
it", and no app could: `AppShell` rendered a fixed class string. Measured on Porvenir before
|
|
1087
|
+
this field existed: every tab of the App route scrolled the document by 200 to 770px at
|
|
1088
|
+
1600x900, and the ADR gate could not see it because it never measured scrollHeight. A route
|
|
1089
|
+
in `fixedRoutes` (exact for `/`, prefix for any other path) gets the class; `fixed: true`
|
|
1090
|
+
contains every route of a single-surface app. Nothing changes for consumers that set neither.
|
|
1091
|
+
|
|
1092
|
+
### Fixed
|
|
1093
|
+
|
|
1094
|
+
- **`test/layout-primitives.test.ts` could not see a compound or descendant override.** It
|
|
1095
|
+
inspected only blocks whose selector list contained exactly `.page-body`; appending
|
|
1096
|
+
`.app-shell .page-body { max-width: 100%; margin-inline: 0 }` to the stylesheet removed the
|
|
1097
|
+
reading cap and the centering from every product and all five tests passed. The test now
|
|
1098
|
+
walks every rule whose subject carries the class, requires the plain rule to hold the
|
|
1099
|
+
intended value, and refuses any competing declaration outside the documented `.wide`
|
|
1100
|
+
opt-in; proven on that exact override (two failures) and clean on the shipped stylesheet.
|
|
1101
|
+
|
|
1102
|
+
## [0.06.002] - 2026-09-03
|
|
1103
|
+
|
|
1104
|
+
### Added
|
|
1105
|
+
|
|
1106
|
+
- **`CaseSelector layout="select"`**, the compact one-of-N picker ADR-0071 rule 7 asks for:
|
|
1107
|
+
a native dropdown with one `optgroup` per category, preserving the category structure the
|
|
1108
|
+
chip layout carries. The chip layout spends vertical space linearly in the number of cases,
|
|
1109
|
+
and that space comes out of the instrument on every render. Measured on Porvenir at
|
|
1110
|
+
2560x1440: ten cases in four categories occupied a 308px block, 21 percent of the viewport,
|
|
1111
|
+
for a choice one control expresses. Default stays `chips`, so nothing changes for existing
|
|
1112
|
+
consumers until they opt in.
|
|
1113
|
+
|
|
1114
|
+
## [0.06.001] - 2026-09-03
|
|
1115
|
+
|
|
1116
|
+
### Fixed
|
|
1117
|
+
|
|
1118
|
+
- **Every prose page in every product on this shell rendered full-bleed.** `styles.css` defined
|
|
1119
|
+
`.page-body { max-width: var(--maxw) }`, the 1200px reading measure ADR-0017 s1.1 specifies, and
|
|
1120
|
+
then 216 lines later a containment fix added a second unscoped `.page-body { max-width: 100% }`.
|
|
1121
|
+
CSS takes the last one, so the cap was silently removed everywhere. Measured on Porvenir at
|
|
1122
|
+
1600x900: the doc routes rendered 1600px wide instead of 1200px centered, so body text ran the
|
|
1123
|
+
full width of the display.
|
|
1124
|
+
|
|
1125
|
+
The overriding rule was itself written to fix a real bug (a `nowrap` row sizing its whole column
|
|
1126
|
+
and pushing the page wider than the viewport, ADR-0071 rule 3). Containment is about letting a box
|
|
1127
|
+
SHRINK below its content, which is `min-width: 0`; capping it at 100% does nothing for that and
|
|
1128
|
+
costs the measure. Changed to `min-width: 0`. `.page-body.wide` is more specific and still wins,
|
|
1129
|
+
so workbench routes keep the full viewport.
|
|
1130
|
+
|
|
1131
|
+
Nothing could see this. The package built, the types were correct, and every consumer imported the
|
|
1132
|
+
right class. `test/layout-primitives.test.ts` now asserts that the LAST declaration of a capped
|
|
1133
|
+
property on each layout primitive is the intended one, so a later rule overriding a primitive fails
|
|
1134
|
+
here instead of shipping to every app. Verified non-vacuous: re-adding the rule fails the test.
|
|
1135
|
+
|
|
1136
|
+
## [0.06.000] - 2026-08-23
|
|
1137
|
+
|
|
1138
|
+
### Added
|
|
1139
|
+
|
|
1140
|
+
- **Bilingual architecture diagrams (ADR-0058).** The ArchitectureModal panel now carries
|
|
1141
|
+
`data-arch-lang`, and the stylesheet ships the three rules that act on it. A diagram tags each
|
|
1142
|
+
translatable `<text>` twice at the same coordinates, `class="... l-en"` and `class="... l-es"`,
|
|
1143
|
+
and exactly one is shown. Diagrams previously rendered English text inside a fully Spanish UI,
|
|
1144
|
+
which was the last untranslated surface in an otherwise bilingual shell.
|
|
1145
|
+
|
|
1146
|
+
ONE file carries both languages on purpose. Two files would be two things to keep in step, and
|
|
1147
|
+
the one not on screen is the one that goes stale. Anything language-neutral, a number, a file
|
|
1148
|
+
name, an identifier, needs no pair.
|
|
1149
|
+
|
|
1150
|
+
Backwards compatible: a diagram with no `l-en`/`l-es` classes renders exactly as before.
|
|
1151
|
+
|
|
1152
|
+
### Fixed
|
|
1153
|
+
|
|
1154
|
+
- `npm test` listed its test files by hand, so a newly added test file silently never ran. It now
|
|
1155
|
+
discovers `test/**/*.test.ts(x)`, which immediately picked up two tests that had been invisible.
|
|
1156
|
+
|
|
1157
|
+
## [0.05.000] - 2026-08-03
|
|
1158
|
+
|
|
1159
|
+
### Added
|
|
1160
|
+
|
|
1161
|
+
- `WorkbenchShell`, a typed authenticated-console frame with shared route rendering, desktop sidebar,
|
|
1162
|
+
mobile bottom navigation and extension slots for product-owned brand, sidebar trust/actions, command
|
|
1163
|
+
surface, account/chat controls, overlays and canonical content.
|
|
1164
|
+
- A server-rendered contract test proving route activation, slot preservation, the main-content
|
|
1165
|
+
landmark and overlay placement without coupling the package to product state.
|
|
1166
|
+
|
|
1167
|
+
### Changed
|
|
1168
|
+
|
|
1169
|
+
- The shell now consumes the stable `react-router` core peer contract across major versions 6, 7 and
|
|
1170
|
+
8. Browser applications can keep `react-router-dom` 6/7, while core-only Router 8 applications are
|
|
1171
|
+
supported without a downgrade. The package is built/tested against 8.3.0 and retains `AppShell`.
|
|
1172
|
+
- Package, display version, lockfile, README and changelog now advance together for the npm release.
|
|
1173
|
+
|
|
1174
|
+
## [0.04.000] - 2026-07-28
|
|
1175
|
+
|
|
1176
|
+
### Added (the ADR-0071 UI floor, so every product inherits it instead of fixing it alone)
|
|
1177
|
+
- **`.page-body.wide`**: a workbench is not prose. App surfaces take the full viewport; the 1200px
|
|
1178
|
+
reading measure (`--maxw`) stays for prose pages. Capping an instrument at a reading width discarded
|
|
1179
|
+
400px on a 1600px display and over half of a 2560px one, which is why the visualization read as a
|
|
1180
|
+
thumbnail across the whole product line.
|
|
1181
|
+
- **`.app-shell.fixed`**: an app surface sized by flex rather than by a hardcoded guess at the chrome.
|
|
1182
|
+
Products were computing `calc(100dvh - 150px)` while real chrome measured 175px, leaving a few pixels
|
|
1183
|
+
of scroll; the constant also has to be maintained whenever the header or footer changes.
|
|
1184
|
+
- **`.app-shell.fixed .site-footer { margin-top: 0 }`**: the prose footer margin (3rem) is dead space in
|
|
1185
|
+
a viewport-filling app. It was exactly the 48px gap users saw above the footer.
|
|
1186
|
+
|
|
1187
|
+
### Changed
|
|
1188
|
+
- **The tab bar is a single row.** `flex-wrap: wrap` let a 12-to-18 tab bar occupy two and three rows,
|
|
1189
|
+
and every extra row is vertical space taken from the content permanently, on every render.
|
|
1190
|
+
- **Layout containment.** `html, body { overflow-x: hidden }` plus `min-width: 0` and `max-width: 100%`
|
|
1191
|
+
on `.tabs`, `.tabpanel` and `.tablist`. A flex or grid item defaults to `min-width: auto` and will not
|
|
1192
|
+
shrink below its content, so a single `nowrap` row silently sized the page to 1817px on a 1600px
|
|
1193
|
+
viewport and the user had to drag sideways to reach the right edge.
|
|
1194
|
+
|
|
1195
|
+
### Note for consumers
|
|
1196
|
+
A tab row that must scroll horizontally MUST NOT use `overflow-x` on the row itself if it hosts dropdown
|
|
1197
|
+
menus: in CSS a box cannot keep `overflow-y: visible` when the other axis is anything else, so the
|
|
1198
|
+
declared value computes to `auto` and the row clips its own menu. Either keep the row short enough not to
|
|
1199
|
+
scroll (group the tabs, per ADR-0071) or position the menu `fixed`.
|
|
1200
|
+
|
|
1201
|
+
# Changelog
|
|
1202
|
+
|
|
1203
|
+
All notable changes to this product. Format: `X.XX.XXX` (display, see the workspace `versioning.md`); stays `0.x` while pre-1.0. Tag every release.
|
|
1204
|
+
|
|
1205
|
+
## [0.03.000] · 2026-07-04
|
|
1206
|
+
|
|
1207
|
+
### Added
|
|
1208
|
+
- **`usePausedViz` + `createVizLoop`**, a no-compute-bomb animation loop for canvases/3D views:
|
|
1209
|
+
default paused, run-once-then-stop (looping opt-in), optional `durationMs` hard cap, and auto-halt
|
|
1210
|
+
on a hidden tab (visibilitychange). The state machine (`createVizLoop`) is framework-free with
|
|
1211
|
+
injected `requestAnimationFrame`/`cancelAnimationFrame`, unit-tested with a fake clock (10 tests).
|
|
1212
|
+
`usePausedViz` is the React wrapper. Animated views should mount through it instead of calling rAF
|
|
1213
|
+
directly. Enforces the portfolio "no autoplay, no compute bomb" rule at the shell level.
|
|
1214
|
+
- **`CaseSelector` v2**, shared source + case picker. Chips show `ID · name`; cases render in
|
|
1215
|
+
labelled category groups; an optional first-level `Synthetic | Real | Uploaded` source control
|
|
1216
|
+
filters the deck and shows a locked-knobs explanation on non-synthetic lanes; a "modified from CASE"
|
|
1217
|
+
divergence badge with reset; opt-in `?case=` deep-linking. Pure model (`caseModel.ts`) unit-tested
|
|
1218
|
+
(6 tests). Closes the inherited selector defects portfolio-wide (deep-review 1.6.1-1.6.4).
|
|
1219
|
+
- Establishes the shell's first test harness (`npm test` → `node --test` + `tsx`; 16 tests).
|
|
1220
|
+
|
|
1221
|
+
## [0.02.000] · 2026-07-03
|
|
1222
|
+
|
|
1223
|
+
### Added
|
|
1224
|
+
- Adopt the `X.XX.XXX` versioning scheme: a `VERSION` file as the single source of truth, this `CHANGELOG`, and the first git tag. Baseline documenting the current shipped state; later changes are versioned by nature (major/minor/patch).
|
|
1225
|
+
## [0.06.007] - 2026-09-10
|
|
1226
|
+
|
|
1227
|
+
### Fixed
|
|
1228
|
+
|
|
1229
|
+
- Architecture dialogs keep keyboard focus within the modal and return it to the opener on close. Tabs support arrow keys, Home and End with explicit tab-panel relationships.
|
|
1230
|
+
- Architecture diagrams offer a contained native-size reading view and a fit toggle in English and Spanish. Native-size viewing preserves authored text size on mobile while retaining the selected theme and language.
|
|
1231
|
+
- A real Chromium consumer checks keyboard navigation, Escape, focus restoration, native-size scrolling and diagram fit in both languages and themes at mobile and desktop widths (`npm run test:browser`).
|
|
1232
|
+
## [0.06.008] - 2026-09-10
|
|
1233
|
+
|
|
1234
|
+
### Fixed
|
|
1235
|
+
|
|
1236
|
+
- All configured page routes remain reachable on mobile through a compact second header row. Links scroll horizontally inside the header, retain their active-page semantics and remain visible when reached by keyboard focus.
|
|
1237
|
+
- Real-browser navigation tests exercise all six routes by click and keyboard at 320, 390 and 1440 px, in EN/ES and both themes. They verify viewport containment and a header below 100 px so the main instrument retains most of the viewport.
|