Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -158,10 +158,15 @@ jobs:
# which is what #260 hit. `corpus:fetch` pulls the snapshot pinned by
# scripts/corpus-pin.json and verifies its sha256.
#
# What is a gate here and what is not: the FETCH gates — a hash mismatch is a
# hard failure, or the pin is decorative. The census figures do NOT gate; they
# go to the run summary as a trend. Asserting them against the committed
# fixture is #260's job, and it needs the reachability this job provides.
# What gates here (#260): the FETCH — a hash mismatch is a hard failure, or
# the pin is decorative — and the VALUE census against the committed
# `corpus` block of test/fixtures/explain/values.json, which is the
# reachability this job was built to provide. The genre census still only
# reports: it has no committed fixture to be asserted against.
#
# The other half of #260 needs no corpus and is not here: the README figures
# are a generated projection of that same fixture, gated by
# `explain:value-census:readme:check` inside `lint:ci`.
corpus:
name: Corpus census
needs: [checks]
Expand Down Expand Up @@ -209,6 +214,11 @@ jobs:
bun run explain:value-census 2>&1
echo '```'
} >> "$GITHUB_STEP_SUMMARY"
# After the summary, so a drifted run still publishes its figures — the
# numbers are what tells you whether the drift is an intended emission
# change or a regression.
- name: Value census matches the committed fixture
run: bun run explain:value-census:check

chr-smoke:
name: CHR smoke (stable)
Expand Down
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,18 @@ documenting cross-cutting shifts that affect contributors and consumers.
and never on a PR; both now fall back to the pinned snapshot and announce the
source and hash they used. A new CI job gates the fetch and posts both
censuses to the run summary (#186).
- **The `explain` value census is drift-gated, not just re-derivable.** Its
figures live in three places — the census itself, the `corpus` block of
`test/fixtures/explain/values.json`, and prose in `commands/explain/README.md`
— and #256 shipped with the README still quoting pre-change numbers, caught by
review rather than CI. Each link now has a gate keyed to the data it needs:
`bun run explain:value-census:check` re-runs the census against the committed
fixture in the CI corpus job, while the README paragraph became a generated
projection of that fixture (`bun run explain:value-census:readme`) checked by
`bun run explain:value-census:readme:check` in `lint:ci` and in `bun test`,
needing no corpus at all. The generated prose reports the invariants as
counters rather than asserting they hold, so regenerating after a regression
states it instead of reading as reassurance (#260).

## 0.1.3 — 2026-07-06

Expand Down
28 changes: 19 additions & 9 deletions commands/explain/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -779,16 +779,26 @@ and its phase is named below.
on the seconds fallback rather than encoding a chain that depends on a failed
address attempt.

<!-- BEGIN GENERATED value-census — regenerate with `bun run explain:value-census:readme` -->
The corpus census is re-derivable with `bun run explain:value-census` and
covers 948 source scripts. Every one of the 13,168 emitted values in a
statement the strict argument lexer ALSO read has identical half-open byte
spans and decoded text (0 contradictions), while the prefix-safe scan retains
6,540 values across 569 statements whose strict REST reading abstains. Of
19,708 emitted occurrences, 5,636 are array members (529 keyed, 1,147 nested
inside another member) and 813 are arrays; the corpus contains no
source-literal `id` example. All spans were in bounds, every member named a
container that exists, and every member sat strictly inside it. The strict
lexer remains all-or-nothing; only non-authoritative hints use the wider view.
covers 948 source scripts. The figures below are generated from
`test/fixtures/explain/values.json` → `corpus` by
`bun run explain:value-census:readme` and gated against it by
`bun run explain:value-census:readme:check`; the fixture itself is gated
against a fresh corpus run by `bun run explain:value-census:check`. Of the
13,168 emitted values in a statement the strict argument lexer ALSO read, 0
disagree with it on half-open byte span or decoded text, while the
prefix-safe scan retains a further 6,540 values across 569 statements whose
strict REST reading abstains. Of 19,708 emitted occurrences, 5,636 are array
members (529 keyed, 1,147 nested inside another member) and 813 are arrays;
the corpus holds no source-literal `id` example. The three structural
counters — spans addressing bytes outside their own source, members naming a
container that does not exist, members escaping the container they name —
read 0, 0 and 0, and each must stay 0.
<!-- END GENERATED value-census -->

The strict lexer remains all-or-nothing; only non-authoritative hints use the
wider view.

### Offline comment placement (#245)

Expand Down
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
"lint": "bun run lint:biome && bun run lint:typecheck",
"lint:git:commit": "bun run lint",
"lint:git:push": "bun run lint:ci && bun run test && bun run build",
"lint:ci": "bun run lint && bun run docs:cli:check && bun run lint:markdownlint && bun run lint:cspell && bun run lint:secretlint",
"lint:ci": "bun run lint && bun run docs:cli:check && bun run explain:value-census:readme:check && bun run lint:markdownlint && bun run lint:cspell && bun run lint:secretlint",
"lint:cspell": "cspell lint . --gitignore",
"lint:cspell:all": "cspell lint . --no-gitignore",
"lint:markdownlint": "markdownlint-cli2 \"**/*.md\" \"!.scratch/**\"",
Expand Down Expand Up @@ -98,6 +98,9 @@
"explain:menus": "bun run scripts/gen-explain-menus.ts",
"explain:menus:check": "bun run scripts/gen-explain-menus.ts --check",
"explain:value-census": "bun run scripts/explain-value-census.ts",
"explain:value-census:check": "bun run scripts/explain-value-census.ts --check",
"explain:value-census:readme": "bun run scripts/explain-value-census.ts --readme",
"explain:value-census:readme:check": "bun run scripts/explain-value-census.ts --readme --check",
"security": "bun run lint:secretlint && bun run lint:markdownlint"
},
"type": "module",
Expand Down
Loading
Loading