Never invent a required field, a format rule, a threshold, or a citation.
Every check enforces something a published document actually says, and carries a citation to it. A conformance checker that cites an invented requirement is worse than no checker at all, because conformance is precisely the claim it is making. If you cannot find the requirement in a published source, the check does not get written. Register it as unimplemented with an honest reason instead. That is what ten of the current checks are.
uv sync --locked
make verifymake verify runs lint, formatting, strict type checking, the test suite
against its coverage floor, and the security scanners. It must exit 0 before
anything is pushed. CI runs the same gate.
-
Find the requirement. Fetch the source yourself. Read the operative sentence. Do not work from memory or from a summary.
-
Record the source in
src/power_content_check/citations.pyif it is not already there, with its URL, its publisher, its effective date if it has one, and the date you retrieved it. Add it todocs/sources.mdtoo, with a note on what it yielded. -
Take the next identifier. Identifiers are permanent. Never renumber, never reuse.
tests/test_registry.pypins the full set and the full title map, so adding a check means appending to both. -
Choose a basis honestly.
REGULATION_TEXTwhen the regulation enumerates the element in words.TEMPLATE_FORMATwhen the element is part of the format the California Energy Commission issues rather than a sentence of regulatory text.
If it is neither, you do not have a check yet.
-
Quote the source, do not paraphrase it. The
quotefield is transcribed from the document. Trim at a sentence boundary if it is long. Never reword. -
Decide what happens when you cannot tell. A check that cannot measure something returns
NOT_EVALUATED. It never returnsCONFORMSas a default. -
Write the finding as a statement about the document. Not about the supplier. "The words 'Energy Commission' do not appear in the label text" is the right register. Anything that reads as an accusation is not.
-
Test both directions, and test that prose cannot satisfy a check that is about a row of a table. There are existing examples in
tests/test_checks.py::TestNarrowMatching.
This is a first-class outcome, not a failure. Use _registered_only and write
a specific reason. "Not implemented yet" is not a reason. "Whether any customer
is served by a mixture of portfolios is a fact about the supplier's service,
not about the document" is.
- Ranking suppliers, scoring them against each other, or producing a leaderboard.
- Any output that reads as a compliance determination. Only the California Energy Commission can make one.
- Editorial content about anyone's energy sources.
- Copy implying endorsement by, affiliation with, or approval from the Energy Commission or any utility.
- Copy implying users, adopters, downloads, or production scale.
- Bulk fetching of published labels.
- Committing a published label into the repository. Test fixtures are synthetic.
- Em dashes and en dashes.
- Format and lint with ruff. Type check with mypy in strict mode.
- Coverage floor is 96 percent and the complexity ceiling is 10. Both are
configured in
pyproject.toml. The floor moves only when what it excludes has been argued with; raising it is a deliberate diff, not housekeeping. - Comments explain why, not what.
pypdf is the only runtime dependency and extraction is the safety-critical surface, so its upgrades get their own commit and are never folded into work that touches checks.
- Bump the floor in
pyproject.tomland relock. One dependency, one commit, a message that names the version. - Run
make verify. The gate covers the fail-closed properties, but note what it cannot cover:geometry.pyreads pypdf's layout machinery from below its public surface precisely because the surface folds lines (see ADR 0008), so a version bump can take column reconstruction away. That failure mode is safe - PCL016 goes back to not evaluated - but it is also silent, which is why a test asserts positioned text still yields on a real PDF. If that test fails, stop: either pin the previous version or fix forward, never delete the test. - Record the bump in the changelog under Changed, even though it is only a floor move. Consumers of the lockfile are entitled to know it moved.
Describe the change by what it does. Keep the changelog's Unreleased section current in the same commit as the change it describes.