The compiled stylesheet is three utilities behind, and the report page is missing two #164

Closed
opened 2026-09-10 08:52:38 +00:00 by tiagoagueda · 1 comment
Owner

Observation

The styles job rebuilds the stylesheet and fails on the diff:

+  .mt-5 {
+    margin-top: calc(var(--spacing) * 5);
+  }
+  .border-collapse {
+    border-collapse: collapse;
+  }
+    .lg\:grid-cols-2 {
+      grid-template-columns: repeat(2, minmax(0, 1fr));
+    }
::error::app.css is stale. Run 'npm run build:css' and commit the result.

What happened

All three come from the report templates added in #56 (b2afbfb5). The stylesheet was last
rebuilt in 078be627 (#125), and nothing between them rebuilt it. Reproduced locally by
building to a scratch file: exactly these three, nothing else.

  • mt-5 — report.html, the Show this period button, which relies on it to line up with
    the labelled controls beside it.
  • lg:grid-cols-2 — report.html, the two tallies (Where they were found, What kind of
    employer
    ), which are meant to sit side by side on a wide screen.
  • border-collapse — not a class anybody wrote. It is the declaration
    border-collapse: collapse; inside the inline <style> of report_print.html, which
    Tailwind's scanner reads as a candidate utility. It is harmless: the PDF carries its own
    stylesheet and never loads app.css.

So this is a visible defect, not only a red job. On any instance running 0.3.0 as it stands,
the report's button sits out of line and the two tallies stack on a wide screen, because those
classes do nothing. It is the failure #125's
test_the_spans_are_written_out_rather_than_assembled names — a class it never sees is a class
it never compiles, silently
— but the other way round: the class was seen, and the compiled file
was never regenerated.

Why it passed before pushing

The check exists only in CI. The local definition of done in CLAUDE.md is ruff, pytest, the
browser suite and the catalogue checks. npm run build:css is mentioned ("the compiled CSS is
committed") but is not on that list. No pre-commit hook or test compares the committed file with
a fresh build, and the #125 test checks three particular spans and nothing else.

What fixing it is

npm run build:css and commit. Then close the gap that let this through, which is the part
worth deciding:

  • CLAUDE.md — add the build to Before saying a change is done. Cheap, and relies on
    memory.
  • A pre-commit hook scoped with files: to templates, assets/ and static/js, which
    rebuilds and fails on a diff. It would have caught this, but it needs Node on every
    contributor's machine — the thing CI installs in a container precisely so nobody else has to.
  • A pytest that does the same when npx is available and skips otherwise. It catches this
    for anybody who runs the suite.

Probably the first, plus one of the other two.

Worth being careful about

border-collapse comes back on every build for as long as the print template's inline CSS
contains that phrase. That is the scanner behaving correctly rather than a bug, and worth knowing
so nobody "fixes" it by editing app.css by hand. If the noise matters, Tailwind v4 (3.3 is
installed) can exclude paths from the scan with @source not. The templates the stylesheet never
styles are exactly the PDF ones — documents/themes/* and report_print.html — and leaving them
out would also stop their CSS turning into utilities.

Classification

Bug. Blocks CI, and so the 0.3.0 release.

## Observation The `styles` job rebuilds the stylesheet and fails on the diff: ``` + .mt-5 { + margin-top: calc(var(--spacing) * 5); + } + .border-collapse { + border-collapse: collapse; + } + .lg\:grid-cols-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } ::error::app.css is stale. Run 'npm run build:css' and commit the result. ``` ## What happened All three come from the report templates added in #56 (`b2afbfb5`). The stylesheet was last rebuilt in `078be627` (#125), and nothing between them rebuilt it. Reproduced locally by building to a scratch file: exactly these three, nothing else. - **`mt-5`** — `report.html`, the *Show this period* button, which relies on it to line up with the labelled controls beside it. - **`lg:grid-cols-2`** — `report.html`, the two tallies (*Where they were found*, *What kind of employer*), which are meant to sit side by side on a wide screen. - **`border-collapse`** — not a class anybody wrote. It is the declaration `border-collapse: collapse;` inside the inline `<style>` of `report_print.html`, which Tailwind's scanner reads as a candidate utility. It is harmless: the PDF carries its own stylesheet and never loads `app.css`. **So this is a visible defect, not only a red job.** On any instance running 0.3.0 as it stands, the report's button sits out of line and the two tallies stack on a wide screen, because those classes do nothing. It is the failure #125's `test_the_spans_are_written_out_rather_than_assembled` names — *a class it never sees is a class it never compiles, silently* — but the other way round: the class was seen, and the compiled file was never regenerated. ## Why it passed before pushing The check exists only in CI. The local definition of done in `CLAUDE.md` is ruff, pytest, the browser suite and the catalogue checks. `npm run build:css` is mentioned ("the compiled CSS is committed") but is not on that list. No pre-commit hook or test compares the committed file with a fresh build, and the #125 test checks three particular spans and nothing else. ## What fixing it is `npm run build:css` and commit. Then close the gap that let this through, which is the part worth deciding: - **`CLAUDE.md`** — add the build to *Before saying a change is done*. Cheap, and relies on memory. - **A pre-commit hook** scoped with `files:` to templates, `assets/` and `static/js`, which rebuilds and fails on a diff. It would have caught this, but it needs Node on every contributor's machine — the thing CI installs in a container precisely so nobody else has to. - **A pytest** that does the same when `npx` is available and skips otherwise. It catches this for anybody who runs the suite. Probably the first, plus one of the other two. ## Worth being careful about **`border-collapse` comes back on every build** for as long as the print template's inline CSS contains that phrase. That is the scanner behaving correctly rather than a bug, and worth knowing so nobody "fixes" it by editing `app.css` by hand. If the noise matters, Tailwind v4 (3.3 is installed) can exclude paths from the scan with `@source not`. The templates the stylesheet never styles are exactly the PDF ones — `documents/themes/*` and `report_print.html` — and leaving them out would also stop their CSS turning into utilities. ## Classification Bug. Blocks CI, and so the 0.3.0 release.
tiagoagueda added this to the 0.3.0 milestone 2026-09-10 08:52:38 +00:00
Author
Owner

Done in 2acc2ee4. The styles job has passed on every run that reached it since, 271 to 276.

What was wrong

The report arrived without a stylesheet rebuild, so its Show this period button sat out of line and its two tallies stacked on a wide screen: mt-5 and lg:grid-cols-2 compiled to nothing. The rebuild puts both back.

The phantom third class led to the real problem: what compiled depended on more than the interface. There were three leaks.

  • Automatic detection scanned the whole repository. A word in a test's docstring, the wiki or the changelog could put a class in the stylesheet every page loads, and the template lint's own list of forbidden physical utilities was compiling them. @import "tailwindcss" source(none) and one @source "../../src/postulo" fix that.
  • The compiled file sat inside the scanned tree. Tailwind skips its output only when it is writing to it, so a build written anywhere else read the previous build as a source. That is why border-collapse appeared when I built to a scratch file. It is fixed with @source not "../../src/postulo/static/css".
  • The PDF templates' inline CSS was read as classes, border-collapse: collapse; among it. They never load this stylesheet, so they are out of the scan, as you suggested (@source not for documents/themes and report_print.html).

With the scan fixed, 24 utilities nothing used have gone, every physical one among them. Each was checked unused under src/postulo before it went. A build is now byte-identical wherever it is written.

Your three options for closing the gap

  • CLAUDE.md: done. npm run build:css is on the checklist, and CONTRIBUTING.md says the suite catches a stale stylesheet once npm ci has run.
  • A pytest: done. tests/test_stylesheet.py rebuilds into a temporary file and compares it with the committed one, using the CLI npm ci installs, never one fetched to run a test. It skips where node_modules is absent, which includes CI's test job; the styles job covers it there. Two more tests there hold the scan to the interface and keep physical utilities out of the compiled file.
  • A pre-commit hook: not done, for the reason you gave. It would need Node on every contributor's machine.

Worth knowing

#165 changed the stylesheet three times after this. Each rebuild went through the new comparison, and CI's styles job agreed with the result.

Done in `2acc2ee4`. The `styles` job has passed on every run that reached it since, 271 to 276. ## What was wrong The report arrived without a stylesheet rebuild, so its *Show this period* button sat out of line and its two tallies stacked on a wide screen: `mt-5` and `lg:grid-cols-2` compiled to nothing. The rebuild puts both back. **The phantom third class led to the real problem: what compiled depended on more than the interface.** There were three leaks. - **Automatic detection** scanned the whole repository. A word in a test's docstring, the wiki or the changelog could put a class in the stylesheet every page loads, and the template lint's own list of forbidden physical utilities was compiling them. `@import "tailwindcss" source(none)` and one `@source "../../src/postulo"` fix that. - **The compiled file sat inside the scanned tree.** Tailwind skips its output only when it is writing to it, so a build written anywhere else read the previous build as a source. That is why `border-collapse` appeared when I built to a scratch file. It is fixed with `@source not "../../src/postulo/static/css"`. - **The PDF templates' inline CSS was read as classes**, `border-collapse: collapse;` among it. They never load this stylesheet, so they are out of the scan, as you suggested (`@source not` for `documents/themes` and `report_print.html`). With the scan fixed, **24 utilities nothing used have gone**, every physical one among them. Each was checked unused under `src/postulo` before it went. A build is now byte-identical wherever it is written. ## Your three options for closing the gap - **`CLAUDE.md`**: done. `npm run build:css` is on the checklist, and `CONTRIBUTING.md` says the suite catches a stale stylesheet once `npm ci` has run. - **A pytest**: done. `tests/test_stylesheet.py` rebuilds into a temporary file and compares it with the committed one, using the CLI `npm ci` installs, never one fetched to run a test. It skips where `node_modules` is absent, which includes CI's test job; the `styles` job covers it there. Two more tests there hold the scan to the interface and keep physical utilities out of the compiled file. - **A pre-commit hook**: not done, for the reason you gave. It would need Node on every contributor's machine. ## Worth knowing #165 changed the stylesheet three times after this. Each rebuild went through the new comparison, and CI's `styles` job agreed with the result.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Postulo/postulo#164
No description provided.