just_dna_format.findings¶
just_dna_format.findings ¶
A warning that knows what it is and whether an author can clear it (RM131).
manifest.compilation.warnings already ships and already carries every finding a compile made. What
it could not do was answer the two questions a reader of 14 kB of prose actually has — what kind of
thing is this? and can I do anything about it? — even though the compiler computes the second at
the point each finding is built and spends it on severity alone (_BLAME_TIER/_BLAME_ROW, whose
own comment says "blame decides severity and nothing else").
The transport stays list[str], deliberately. CodedWarning is a str subclass, so every
.extend, every if w not in all_warnings de-duplication, every "; ".join and every consumer
already grepping a phrase keeps working untouched, and the published field keeps its exact type and
its exact text (@warning-text-is-api). What the subclass adds is a code the emission site names,
from which carried follows — and classify reads both back off a finished list.
Pydantic strips the subclass at a model boundary, which is a feature for serialization (the
manifest holds plain JSON strings) and a trap for anything that reads warnings back off a result
model and keeps building. So the rule is: classify before constructing the model, and hand the
classified list — not the model's warnings — to whatever compiles next.
A caller holding plain prose is not an error, and this is where that is decided rather than at
each result model: the public result types have accepted warnings=["..."] since 0.6 and Principle 3
keeps them accepting it, so classify withholds for such a caller and refuses only the part-classified
channel no legitimate caller can produce.
CodedWarning ¶
Bases: str
One warning sentence, plus the code its emission site named it with.
A str for every purpose but one: .code says which member of VALID_WARNING_CODES this is,
and .carried says whether the author can clear it. Equality, hashing, in and formatting are
the base class's, so a CodedWarning and the identical plain string are interchangeable everywhere
the compiler already de-duplicates on the message.
carried
property
¶
Whether no edit to the spec directory can clear this — a property of the code alone.
restated ¶
The same finding under a new sentence — for a caller that prefixes a table name.
Re-wrapping is the one operation that silently loses the code, because every other string
operation on a CodedWarning returns a plain str by construction. A caller that reformats a
message goes through here so the code travels with the text it belongs to.
Source code in schema/src/just_dna_format/findings.py
restate ¶
finding.restated(message), tolerating a plain str only by refusing it out loud.
A reformatting site is exactly where a code goes missing, so this refuses rather than inventing one: the caller is holding something that never named its kind, and bucketing it here would reproduce the silently-partial summary the whole item exists to avoid.
Source code in schema/src/just_dna_format/findings.py
classify ¶
(carried, warnings_summary) for a finished warning list — three cases, no flag.
carried is the subset of warnings no edit to the spec directory can remove, in the order the
findings appear, so a consumer subtracting it from warnings gets the actionable set and both
lists read in the same order as the channel they came from.
- Every member classified — the compiler's own channel — and the answer is the full one:
sum(summary.values()) == len(warnings), which is the claim this summary is complete. - No member classified — a caller holding plain prose, which the public result models have
accepted since 0.6 and must keep accepting (Principle 3) — and the answer is withheld:
([], {}). Nothing here can tell what those messages are, and the house rule is to withhold an unknown rather than report or negate it. An empty summary beside a non-empty channel reads as not classified, which is a different statement from complete and short. - Mixed — some coded, some not — is the one case that cannot arise from a legitimate caller, because every emission site in this repository names a code. So it raises, loudly, at the first compile that reaches the branch.
No catch-all key, in any of the three. A warnings_summary with a bucket for the unclassified
is the rejected repair wearing a different hat: it silently omits findings nobody classified while
looking complete, and the reader believes the digest. Withholding says less; it does not lie.
The residual gap the three cases leave — a module whose only warning lost its code, so the list is uniformly unclassified rather than mixed — is what the static registry guard over the emission sites covers, and it is why that guard is an equality rather than a floor.