commit 2fbb20c6e37801c12660ca117e5ddd94a10930a0
parent d5fe1b33053b59173e1739546a17e94194ee252b
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date: Tue, 29 Sep 2026 22:54:52 -0400
plans: slice CF after the review — `--chart-other` and its numbers in the record (the sweep sentence withdrawn), the Review table, the CF row lists tokens.css and FACTS, Found and left and Decisions updated; FACTS; the homepage changelog
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Diffstat:
3 files changed, 75 insertions(+), 38 deletions(-)
diff --git a/homepage/CHANGELOG.md b/homepage/CHANGELOG.md
@@ -1,7 +1,7 @@
# Homepage Changelog
## [Unreleased]
-- **The growth chart draws its smallest instances together as Other.** Two or more instances that each hold under 5% of the chart's total are one band, **Other**, on top of the stack, in the chart's neutral grey (`--chart-axis`, at least 3:1 on both grounds); an instance at exactly 5% keeps its band, and a single one under 5% is not grouped. The other instances keep their bands and their colours. The legend lists them and Other; the caption says what Other is and the chart's description names the instances in it; every month's hover title and the Numbers by year table still name every instance. At this release's numbers Hasanalyzer, Rekietalyzer and Jasolyzer are Other. The instance cards and `/stats` are unchanged. The e2e fixture's fifth site transcribes 4 a day rather than 5, so two of its six sites are grouped.
+- **The growth chart draws its smallest instances together as Other.** Two or more instances that each hold under 5% of the chart's total are one band, **Other**, on top of the stack, in a near-neutral grey of its own (`--chart-other`: 7.36:1 on the Light ground, 3.22:1 on the Dark one, and apart from every instance colour for colour-blind readers); an instance at exactly 5% keeps its band, and a single one under 5% is not grouped. The other instances keep their bands and their colours. The legend lists them and Other; the caption says what Other is and the chart's description names the instances in it; every month's hover title and the Numbers by year table still name every instance. At this release's numbers Hasanalyzer, Rekietalyzer and Jasolyzer are Other. The instance cards and `/stats` are unchanged. The e2e fixture's fifth site transcribes 4 a day rather than 5, so two of its six sites are grouped.
- **An unlisted site is not on the homepage.** A site whose settings turn off **List on the Archilyzer homepage and hub** (`listed: false`) has no Official Instances card, chart series, `/stats` entry or recent item, is not in `channel-sites.json` or `stats/`, and the channels only it carries count in none of the numbers, the headline totals included. The summary's version is 6. The e2e fixture has a seventh, unlisted site that no page names.
- **`/#instances` goes straight to Official Instances.** The section carries `id="instances"`, clear of the sticky header, and every archive's header now links there (`INSTANCES_URL` in `common/lib/project.ts`). With no sites the link lands on the top of the page.
diff --git a/plans/FACTS.md b/plans/FACTS.md
@@ -6801,7 +6801,8 @@ S4, as shipped"; `release-10.md` "Slice L2 / L1, as shipped". Every anchor below
lowest free slot — never two sites in one colour, and any six wear the six validated slots. The growth
chart, its legend and `/stats` (`SiteGrid`, `homepageChartData`, the By-site leaderboard) wear
it (release 14 slice CF: the growth chart draws two or more sites each under 5 % of its total as
- ONE Other band on top, in `--chart-axis`; `homepage/app/lib/growthGaps.ts` `growthLayers` /
+ ONE Other band on top, in its own `--chart-other` (tokens.css, Light `#3e545c`, Dark `#62625c`;
+ not in `REQUIRED_TOKENS`); `homepage/app/lib/growthGaps.ts` `growthLayers` /
`layerColors`, which run `siteChartColors` over EVERY site, so a kept site keeps its slot); the
accents themselves fail the dataviz validator as a chart palette (no five with Brass and Blue
pass). `useHubSites` lists the official
diff --git a/plans/release-14.md b/plans/release-14.md
@@ -22,7 +22,7 @@ slice HP added to it on the operator's ruling of the same day. Rules:
| Lows, chart gap, T1, H1 (H3 folded in), H2 | `r14/two-grounds-headers` | The final review's Lows; the charts' surface gap; two grounds and each site in its own accent; the export and hub headers carry the social row and the toggle as one group, with an Archilyzer link to the homepage's `#instances` in place of the sites dropdown and the hub link; Changelog to the footer; after its review, the narrow header keeps the name and shows only the marked links (every header) | `common/components/{ThemeProvider,ThemeScript,ThemeToggle,SocialScroll}.tsx` + `themeConfig.ts` (and the deleted `ThemeMenu`, `ThemeRadios`), `common/components/charts/{ChartView,CrossSiteChart,surfaceGap}`, `common/styles/tokens.css`, `common/lib/{brand,accent,siteColor,paths,project,socialSvg,siteSchema,settingsSchema}.ts` + tests, `scripts/next-build-trace.test.mjs`, `export/app/components/{Header,MobileMenu,Footer}.tsx` (and the deleted `SiblingSwitcher`), `export/app/{layout.tsx,globals.css,changelog/page.tsx,lib/brand.ts}`, `export/e2e{,-hub}/**` (the theme, header and branding specs), `export/playwright.config.ts`, `editor/app/{layout.tsx,globals.css,sites/components/SiteForm.tsx}`, `editor/e2e/theme.spec.ts`, `homepage/app/{page.tsx,layout.tsx,globals.css,lib/*,changelog/page.tsx,components/{Header,ArchiveGrowthChart,ArchiveCards}.tsx}`, `homepage/e2e/**`, `homepage/content/docs/operate.md`, `SETTINGS.md`, `SITE.md` |
| HS | `r14/hidden-sites` | Hidden sites: `site.json` `listed` (absent = listed). An unlisted site builds and deploys as before, and is left off the homepage (cards, chart, `/stats`), the hub (members, federated search, `corpus.json`, `llms.txt`), every other site's footer and the published id lists (`channel-sites.json`, the pooled `stats/`); the channels only it exposes count in no public total. One checkbox in the site form | `common/lib/{siteSchema,site,homepageSummary}.ts` + tests, `common/controller/{poolSummary,buildStats}.ts` + tests, `common/bin/{compose-homepage,compose-hub}.ts` + `compose-hub.test.ts`, `editor/app/sites/{actions.ts,components/SiteForm.tsx}`, `editor/e2e/{helpers.ts,sites-crud.spec.ts}`, `homepage/e2e/{fixture-summary.ts,unlisted-site.spec.ts}`, `SITE.md`, `plans/FACTS.md` (Naming hazards) |
| S1 | per the plan | per the plan | per the plan |
-| CF | `r14/chart-fold` | The homepage's growth chart folds two or more sites each under 5 % of its total into one Other band on top, in the chart's neutral grey; the kept sites keep their colours; the legend shows them and Other, the hover titles and the table every site | `homepage/app/lib/growthGaps.ts` + test, `homepage/app/components/ArchiveGrowthChart.tsx`, `homepage/e2e/{fixture-summary.ts,growth-chart.spec.ts,instance-colours.spec.ts,marketing.spec.ts}`, `homepage/CHANGELOG.md` |
+| CF | `r14/chart-fold` | The homepage's growth chart folds two or more sites each under 5 % of its total into one Other band on top, in its own near-neutral grey (`--chart-other`); the kept sites keep their colours; the legend shows them and Other, the hover titles and the table every site | `homepage/app/lib/growthGaps.ts` + test, `homepage/app/components/ArchiveGrowthChart.tsx`, `common/styles/tokens.css` (`--chart-other`), `homepage/e2e/{fixture-summary.ts,growth-chart.spec.ts,instance-colours.spec.ts,marketing.spec.ts}`, `homepage/CHANGELOG.md`, `plans/FACTS.md` |
**Order:** HP → `r14/two-grounds-headers` → HS (`r14/hidden-sites`) and S1 (`r14/first-search`),
siblings; CF (`r14/chart-fold`) off `main` after HS. The shared files are the three changelogs' `[Unreleased]` sections and this record.
@@ -1238,12 +1238,17 @@ implementer. Scratch files `cf-*` in the job's `tmp`. The rulings (2026-09-29, n
folded.
5. The instance cards and `/stats` are unchanged; the surface gap draws correctly with Other on
top.
+6. (The review, ruled by the parent.) Other wears a dedicated `--chart-other` token in both chart
+ blocks of `tokens.css`: Light `#3e545c`, Dark `#62625c` (the near-neutral).
| sha | what |
|---|---|
| `8351d24f` | `homepage:` the fold in `lib/growthGaps.ts` (`foldedSites`, `growthLayers`, `ownLayers`, `layerColors`; `growthStack` stacks layers); the chart draws the layers, its legend, label and caption; the unit tests; the e2e fixture's fifth site at 4 a day |
| `6e0b652d` | `homepage:` e2e: `growth-chart.spec.ts` (the fold, the grey), `instance-colours.spec.ts`, `marketing.spec.ts` adjusted |
-| _this_ | `plans:` this record, the slices table, Order and Rollout; FACTS; the homepage changelog |
+| `e95a8058` | `plans:` this record, the slices table, Order and Rollout; FACTS; the homepage changelog |
+| `17832633` | `common, homepage:` `--chart-other` in both chart blocks with its numbers; `OTHER_COLOR` points at it; the chart's header comment; `growth-chart.spec.ts` resolves `OTHER_COLOR` and pins each base's value (review M1) |
+| `c42d2bbc` | `homepage:` `instance-colours.spec.ts` reads each site line's stroke on `/stats/`, the Vermilion site's the rust (review L2) |
+| _this_ | `plans:` the review's fixes in this record (the grey, the Review table, the screenshots, Found and left, Decisions); the CF row's files; FACTS; the homepage changelog |
**What shipped.**
- **The rule** (`homepage/app/lib/growthGaps.ts`, pure, beside `growthStack`):
@@ -1261,30 +1266,33 @@ implementer. Scratch files `cf-*` in the job's `tmp`. The rulings (2026-09-29, n
- `layerColors(layers, sites)`: `siteChartColors` over EVERY site, and a kept site takes its own
entry, so a fold never repaints one (with no accents, the kept list alone would move a site
after a folded one to a lower slot; the unit test proves it); Other is `OTHER_COLOR`.
-- **The grey is `--chart-axis`**, the chart tokens' neutral (Light `#55646e`, Dark `#8a8170`). **No
- token was added.** Contrast: 5.63:1 on the Light ground and 6.11:1 on its chart surface; 5.13:1
- on the Dark ground and 4.88:1 on its chart surface. Against each chart slot it can touch (the
- dataviz skill's validator's measures, OKLab ΔE × 100, normal / the worse of protan and deutan):
+- **The grey is its own token, `--chart-other`** (`common/styles/tokens.css`, beside `--chart-axis`
+ in both chart blocks, each with its numbers in a comment as `--chart-6` has; review M1): Light
+ `#3e545c` (OKLCH L 0.43, C 0.03), Dark `#62625c` (L 0.49, C 0.01). Contrast: 7.36:1 on the Light
+ ground and 7.99:1 on its chart surface; 3.22:1 on the Dark ground and 3.06:1 on its chart surface
+ (the Dark slots are 3.37–6.46:1 on the ground: Other is the dimmest mark there). Against each
+ chart slot it can sit on (the dataviz skill's validator's measures, OKLab ΔE × 100, normal / the
+ worse of protan and deutan):
| Slot | Light | Dark |
|---|---|---|
- | blue (`--chart-1`) | 17.6 / 17.6 | 21.3 / 19.8 |
- | green (`--chart-2`) | 13.6 / 9.8 | 12.3 / 4.1 |
- | violet (`--chart-3`) | 16.1 / 14.3 | 18.5 / 17.1 |
- | amber (`--chart-4`) | 17.5 / 14.9 | 11.0 / 10.3 |
- | magenta (`--chart-5`) | 20.2 / 4.5 | 16.9 / 4.2 |
- | rust (`--chart-6`) | 14.4 / 11.7 | 14.6 / 11.4 |
-
- - Other touches only the kept site beneath it (the highest with a height that month). In
- today's data that is Bonnellyzer, blue, in every month Other has data: both floors pass on
- both grounds.
+ | blue (`--chart-1`) | 21.9 / 21.4 | 17.8 / 17.9 |
+ | green (`--chart-2`) | 17.4 / 15.2 | 19.2 / 15.7 |
+ | violet (`--chart-3`) | 16.2 / 13.4 | 23.4 / 21.5 |
+ | amber (`--chart-4`) | 22.1 / 18.2 | 20.3 / 18.1 |
+ | magenta (`--chart-5`) | 24.5 / 9.1 | 19.5 / 7.3 |
+ | rust (`--chart-6`) | 14.1 / 10.5 | 13.5 / 9.3 |
+
+ - Every CVD pair clears the floor (6) on both bases, and the target (8) on Light. Dark's magenta
+ (7.3) is in the 6–8 floor band, legal with the legend, the table and Other's place on top.
+ Rust is the one pair under the normal-vision 15, on both bases.
- A grey is under the validator's chroma floor by definition (it is the de-emphasis role, not a
- categorical slot). No grey inside the chart's lightness band and at ≥ 3:1 on both the ground and
- the chart surface clears both floors (normal 15, CVD 6) against every slot, on either ground
- (swept over neutral, slate-tinted and warm-tinted greys): on Light the best worst normal pair
- is 14.0; on Dark a slate grey reaches 15.6 but falls to CVD 5.5 against magenta. The token was
- kept, as ruled; where a pair is under a floor, the gap, Other's place on top, the legend and
- the table carry it.
+ categorical slot).
+ - Other touches only the kept site beneath it (the highest with a height that month). In
+ today's data that is Bonnellyzer, blue, in every month Other has data.
+ - The first build used `--chart-axis` (Light `#55646e`, Dark `#8a8170`: magenta at CVD 4.5 /
+ 4.2, and on Dark green at 4.1, under the floor). The review's sweep found in-band greys that
+ clear CVD 8 against every slot; the parent ruled the token above.
- **The chart** (`ArchiveGrowthChart.tsx`):
- the legend is the layers: the kept sites' titles, then "Other";
- the areas and the gaps are keyed by layer;
@@ -1309,7 +1317,8 @@ implementer. Scratch files `cf-*` in the job's `tmp`. The rulings (2026-09-29, n
| 300 px | 119 | 7 | 0 |
On the fixture, gaps are drawn under Other, and no band is covered at any height (unit test).
-- **Unchanged:** the instance cards, `/stats`, `siteChartColors`, `tokens.css`, the hub.
+- **Unchanged:** the instance cards, `/stats`, `siteChartColors`, the hub; in `tokens.css` only
+ `--chart-other` is added.
- **With today's data** (the primary's `homepage-summary.json` of 2026-09-28, 75,821 transcripts
on the chart): Jeralyzer 42.03 %, Anilyzer 38.40 %, Bonnellyzer 9.18 % keep their bands;
Hasanalyzer 4.33 %, Rekietalyzer 3.79 % and Jasolyzer 2.26 % are Other.
@@ -1353,7 +1362,14 @@ unlisted site stays out of the chart (it is out of the summary). Every changed e
the four slots and `var(--chart-axis)` last; the label names "Fixture Five and Fixture Six";
the caption says what Other is; every month's title names every site with data that month and
no title says "Other"; the table's header is Year, the six titles, Total;
- - Other is `--chart-axis` on both grounds, at least 3:1 on the ground, and no kept site's colour.
+ - Other is `OTHER_COLOR` on both grounds, rendered `rgb(62, 84, 92)` on Light and `rgb(98, 98, 92)`
+ on Dark (so each base declares its own), not the axis colour, at least 3:1 on the ground, and no
+ kept site's colour (review M1).
+- `instance-colours.spec.ts`, new (review L2): on `/stats/`, on both bases, the six site lines'
+ rendered strokes are the six sites' chart colours in the summary's order; the Vermilion site's is
+ the rust (`--chart-6`) and within 25° of Vermilion's hue. The card test's own site-5 check is the
+ card's hue against its chart colour; the tautology it replaced (`chart[5]` against
+ `var(--chart-6)` twice) is gone.
**They bite** (each change made by hand, the unit tests run, the change reverted):
- `<=` for `<` in the rule: the edge test fails.
@@ -1370,7 +1386,8 @@ unlisted site stays out of the chart (it is out of the summary). Every changed e
- **Build**, capped at 5 GB with no swap, from a clean `.next`, with the primary's summary copied
into the worktree's `homepage/public` for the screenshots (the worktree's own put back after):
`pnpm --filter homepage exec next build` **ok**, 39 s, max RSS 779,504 KB. `main`'s chart,
- built the same way for the "before" shots: 80 s, 754,160 KB.
+ built the same way for the "before" shots: 80 s, 754,160 KB. After the review (`17832633`, for
+ the retaken shots): 20 s, 809,752 KB.
- **Homepage e2e, full** (97 at `main` after HS; 2 new):
| Run | Passed | Failed | Time |
@@ -1390,18 +1407,23 @@ unlisted site stays out of the chart (it is out of the summary). Every changed e
**Screenshots** (`~/reports/release-14/shots/chart3/`, 2×, the static server on 3331, today's
summary):
-- `after-{390,1280}-{light,dark}.png`: the chart; `…-2019-2026.png`: the plot from 2019 on, where
- Other lies;
+- `after-{390,1280}-{light,dark}.png`: the chart with `--chart-other` (retaken after the review;
+ the operator judges the Dark one); `…-2019-2026.png`: the plot from 2019 on, where Other lies;
+- `after-axis-…`: the same from the first build, Other in `--chart-axis`, for comparison;
- `before-…`: the same from `main`'s chart and the same summary (six bands);
- `after-1280-{light,dark}-table.png`: "Numbers by year" open, a column per site.
**Found and left:**
-- **Other and the value scale's labels are one colour** (`--chart-axis`). The labels sit at the
- plot's left edge, above their gridlines; today the stack there is near zero, so none sits on
- Other. A stack whose left edge reached a gridline would hide that label on Other (on another
- band it shows, at that band's contrast).
-- **The weak pairs above** (green, magenta, and on Dark amber) matter only when that site is the
- top kept one under Other; today it is blue.
+- **The pairs short of the validator's targets** are Dark's magenta (CVD 7.3, the 6–8 floor band)
+ and rust on both bases (normal 14.1 / 13.5). They matter only when that site is the top kept one under Other; today it
+ is blue.
+- **`/stats`' channel breakdown has an "Other (N)" of its own**, in `--muted-foreground`
+ (`common/lib/homepageChart.ts` `OTHER_COLOR`), not `--chart-other`. `/stats` is unchanged, as
+ ruled.
+- **`--chart-other` is not in `REQUIRED_TOKENS`** (`common/components/themeConfig.ts`, the list
+ `themeTokens.test.ts` checks every base declares): that file is outside this slice.
+ `growth-chart.spec.ts` pins each base's rendered value instead (a Dark block without it would
+ paint the Light value from `:root`).
- **The fold is the homepage chart's only.** `/stats`, the hub and the sites' charts draw every
site, as ruled.
@@ -1409,7 +1431,6 @@ summary):
| What I assumed | The alternative |
|---|---|
-| Other is `--chart-axis`, the axis labels' grey; no token added | a `--chart-other` token of its own |
| The caption gains one sentence saying what Other is, only when something folds | the caption unchanged |
| The image's label names the folded sites | name only how many |
| The legend reads "Other", with no count or names | "Other (3)" |
@@ -1417,11 +1438,26 @@ summary):
| When every site is under 5 % (21 or more sites), every site folds: one Other band | keep the largest, or fold nothing |
| A site with nothing in the plotted range is under 5 % and folds with another | leave it out of the chart |
+#### Review (verdict SHIP AFTER FIXES; `$T/cf-review.md`)
+
+| Finding | Fix |
+|---|---|
+| M1: the axis grey was under the CVD floor against magenta on both bases (4.5 / 4.2) and against green on Dark (4.1); the record's sweep sentence overstated the case against a better grey | `17832633`: `--chart-other` in both chart blocks (Light `#3e545c`, Dark `#62625c`, as ruled), `OTHER_COLOR` points at it, the chart's comment and the spec follow; the sweep sentence is withdrawn and the token's measured numbers stated ("What shipped"); the labels' shared colour is gone from Found and left; the four `after-*` shots retaken, the first build's kept as `after-axis-*` |
+| L1: the CF row omitted `plans/FACTS.md` | _this_ commit: the row lists it, and `common/styles/tokens.css` |
+| L2: `instance-colours.spec.ts` checked the sixth site's colour against itself | `c42d2bbc`: a rendered check of every site line's stroke on `/stats/`, the sixth the rust |
+| L3: "Found and left" left rust out of the weak pairs | moot with M1; the line names Dark's magenta and rust |
+| L4: the merge of `main` (`721ed0eb`, S1 merged) conflicts in this record only | the merge commit (below): S1's row, then CF's; S1's section, then CF's; both sets of live checks |
+| L5: the changelog's "at this release's numbers" will drift | left, as a release note |
+
+The caption and the image-label sentences are kept (the review: acceptable additions).
+
+**Gates after the review and the merge of `main`:** POSTGATES
+
## Rollout
Release 14 is slice HP (merged, `bfa1ff3c`), `r14/two-grounds-headers`, slice HS
-(`r14/hidden-sites`) and slice CF (`r14/chart-fold`), each after the parent's merge. Every command below is typed **from the
-primary checkout's root**. There is no `archilyzer` on PATH, so it is `pnpm archilyzer …`. The
+(`r14/hidden-sites`) and slice CF (`r14/chart-fold`), each after the parent's merge. Every command
+below is typed **from the primary checkout's root**. There is no `archilyzer` on PATH, so it is `pnpm archilyzer …`. The
command forms are the ones verified in `plans/stats-cache-key.md`'s rollout.
**Preconditions.**