Skip to content

Thirty fields published a zero for a comparison that never happened - #41

Merged
ChelseaKR merged 1 commit into
mainfrom
fix/no-published-domain-is-not-zero-outside-one
Sep 2, 2026
Merged

Thirty fields published a zero for a comparison that never happened#41
ChelseaKR merged 1 commit into
mainfrom
fix/no-published-domain-is-not-zero-outside-one

Conversation

@ChelseaKR

Copy link
Copy Markdown
Owner

The defect

FieldSpec.outside_domain answers False for every cell of a field the layer publishes
no coded-value domain for. field_coverage summed that answer for every field alike, so
thirty of the fifty-four measured fields published "outside_published_domain": 0,
with a distinct count of 0 and an empty value object beside it.

That zero is a measurement nobody took. It is indistinguishable in the artifact from
CAUSE, which does have a published domain and does hold every value in it, and it
says the file and the domain agree about a domain that does not exist. Both publishers
state which of their fields they constrain; FIRE_NAME, UNIT_ID, COUNTY,
SITEADDRESS and twenty-six others are free text.

It is live in the published artifacts today, on both pages.

The fact was already known one layer down.
tests/test_schema.py::test_free_text_fields_have_no_domain_to_be_outside_of asserts it
at the FieldSpec level. Nothing carried it into the counting and nothing tested what the
count published, so the artifact contradicted a test in the same suite.

The fix

  • The four out-of-domain measures are null together for a field with no published
    domain, the way present_tenths_pct is already null where there is no denominator.
    Zero keeps the narrow meaning it should always have had: the domain was published, it
    was read, and the file holds nothing outside it.
  • Every free-text row on both pages now says so: "The layer publishes no coded-value
    domain for this field, so no value here is counted as outside one."
    The paragraph under
    each field table names all three states a row can be in, so a row's silence means
    exactly one of them.
  • outside_published_domain_values is capped at twelve and never said so. No field reaches
    the cap today, which is why nothing has been misread yet; a truncated list that does not
    declare itself reads as the whole set. outside_published_domain_values_listed is
    published beside outside_published_domain_distinct.
  • docs/adr/0010, README.md and CHANGELOG.md record the decision and what changed.

Tests

Three new count-level tests in tests/test_measurements.py, two artifact tests over both
published payloads in tests/test_artifacts_and_pages.py, three page tests in
tests/test_pages_html.py including one asserting the overview carries neither note, so
the other two are not passing over every page. Every new test was run against the previous
code and fails there.

site/ and make site-check

site/ is committed, is what the Pages workflow uploads, and is rebuilt here from the
acquired files. tests/test_published_site_is_current.py compares the artifacts' shape, so
the new key would have failed the build until site/ was rebuilt. It compares pages only
outside <main>, so the thirty new page notes would have gone unnoticed.

make site-check closes that half: a rebuild from data/raw/ into build/site-current,
diffed against site/, never writing into site/, and refusing outright when the acquired
files are absent, because a check that could not run is not a check that passed. Per
ADR-0004 it was run against both inputs it exists to catch, a drifted page and a missing
source file, and fails on both. It cannot run in CI: data/raw/ is not in git and never
will be.

Gate

make verify is green locally end to end: lock-check, sync, lint, format, mypy --strict,
682 tests with the coverage floor, pip-audit, html-validate, axe in jsdom and in Chromium,
Reflow at 320px, npm audit on both trees, and the determinism check. make site-check is
green against the acquired FRAP and DINS files.

🤖 Generated with Claude Code

`FieldSpec.outside_domain` answers False for every cell of a field the layer
publishes no coded-value domain for, and `field_coverage` summed that answer for
every field alike. Thirty of the fifty-four measured fields are free text, so all
thirty published `outside_published_domain: 0`, in the same key where `CAUSE`
publishes a zero meaning "counted, none found". The zero said the file and the
domain agree, about a domain that does not exist.

The four out-of-domain measures are now null together for such a field, the way
`present_tenths_pct` is already null where there is no denominator. Zero keeps
the narrow meaning it should always have had.

tests/test_schema.py has always asserted, at the FieldSpec level, that a
free-text field has nothing to be outside of. Nothing carried that into the
counting and nothing tested what the count published, so the artifact
contradicted a test in the same suite. Both new count-level tests fail against
the previous code.

Both pages now say it on the row rather than leaving it silent, and the
paragraph under each field table names all three states a row can be in, so
silence means exactly one of them.

`outside_published_domain_values` is capped at twelve and never said so. No
field reaches the cap today, which is why nothing has been misread yet.
`outside_published_domain_values_listed` publishes how many of the distinct
values the object names.

`site/` is rebuilt from the acquired files. The artifact-shape check would have
failed until it was; the page notes change only inside `<main>`, which nothing
compares. `make site-check` closes that: a rebuild from data/raw/ into
build/site-current, diffed against site/, never writing into site/, refusing
outright when the acquired files are absent. Verified to fail on both inputs it
exists to catch. It cannot run in CI, because those files are not in git.

See ADR-0010.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ChelseaKR
ChelseaKR merged commit 18ed022 into main Sep 2, 2026
6 checks passed
@ChelseaKR
ChelseaKR deleted the fix/no-published-domain-is-not-zero-outside-one branch September 2, 2026 03:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant