pub struct Entry {
pub tool: String,
pub stratum: String,
pub verdict: Option<String>,
pub note: String,
pub k1: Option<bool>,
pub k2: Option<bool>,
pub k3: Option<bool>,
pub include_reason: Option<String>,
pub spot_audit_event: Option<String>,
pub families: Vec<String>,
pub families_derived: Option<bool>,
pub amendments: Vec<Amendment>,
}Expand description
One entry in a verdict file: a sampled tool, its drawn stratum, and —
once reviewed — a verdict plus an optional note. verdict: None is the
“pending” state; every command that touches the file treats absence of a
verdict as “not yet reviewed”, never as an implicit skip.
Fields§
§tool: StringThe tool name as found on PATH (or supplied via --tools).
stratum: StringThe parse-status label this tool had when it was drawn — recorded at
draw time, not recomputed later, so a tool whose parse changes
between sample and review (a grammar fix landing mid-session)
still reports against the stratum it was actually drawn from.
verdict: Option<String>"correct" / "incomplete" / "wrong" / "skip", or absent while
pending. Stored as a plain string (not an enum) so a hand-edited
verdict file with an unrecognized word fails loudly at the point of
use (parse_verdict_word) rather than silently at deserialization.
note: StringThe reviewer’s free-text note. Becomes an [xfail] reason for a
wrong/incomplete fixture (xtask::audit::cmd_fixtures).
k1: Option<bool>K1 pre-tag: the GCC-family single-dash-long-option parser defect
(short.is_some() && long.is_none() && value_name.is_some()).
Computed once, at sample time, by xtask::audit::k1_signature;
displayed and overridden here (k1=true/k1=false anywhere in a
verdict line or note, via extract_tag_override) exactly the same
way regardless of whether the reviewing tool is xtask audit review
or mandible --review. Some(true) when the tool’s tree contains at
least one matching flag, None when it contains none — never
Some(false), since there is no “confirmed not K1” state worth
asserting for a tool that never exhibited the shape at all.
k2: Option<bool>K2 pre-tag: the existence detector’s own tokenizer gap
(xtask::existence’s line_start_words only considered each line’s
first token, so a multi-column or comma-separated
applet/subcommand list reported every column after the first as
“fabricated” even though it’s right there in the raw text).
The gap itself is closed — existence::list_row_words now reads
a whole list row, and the 359 fleet-wide fabrications this tag
existed to explain away are gone (spec §K2). Existing entries keep
their recorded tag, since a verdict is a record of what the reviewer
was shown; freshly sampled tools of the same shape simply produce no
fabrication to tag. Retained so an old manifest still round-trips,
and so a regression in the list-row rule shows up as this tag coming
back rather than as silent noise.
Computed once, at sample time, by xtask::audit::k2_signature.
Some(true) when every subcommand-kind existence fabrication for
this tool is explained by the known tokenizer gap, Some(false)
when at least one is not (worth a real look), None when the tool
has no subcommand-kind fabrications to judge at all.
k3: Option<bool>K3 pre-tag: “subcommand help was never fetched, so this node is
a bare stub.” Two distinct causes produce it, both computed once at
sample time by xtask::audit::k3_signature from the same
single-pass snapshot K1/K2 use, and both should tag:
- the attestation gate refused to probe a subcommand because its
name came from a native/cobra artifact rather than a recognized
--helpheading (git-lfs: 36 nodes, 34 suspects, statussuspicious, every subcommand a cobra stub — and, unlike an ordinary un-recursed node that just hasn’t been fetched yet, this shape is structurally permanent: the gate refuses it live, in the TUI, exactly as it does here); - the tool’s subcommands simply carry no flags because their own
help was never fetched (
openssl: 151 subcommands, zero flags anywhere in the extracted tree, root included).
Without this, a reviewer re-derives the same “still empty, still not
this tool’s fault” verdict once per subcommand. Some(true) when the
tool’s snapshot shows at least one of the two shapes, None
otherwise — the same “no Some(false)” convention as K1, since
there is nothing to assert-not for a tool that shows neither shape.
include_reason: Option<String>Some(reason) when this entry was force-included in the sample
outside the normal stratified draw (see xtask::audit::cmd_sample’s
force_include parameter). None for an entry drawn by the
ordinary stratified sample.
spot_audit_event: Option<String>Some(event) when this entry was drawn by xtask audit spot-audit
(spec §13.1b’s sixth rule) to spot-check one specific mass-ok
promotion event named event — None for every other entry.
Why this cannot just reuse Self::include_reason/
[FORCED_INCLUSION_STRATUM]-style bucketing. That mechanism
answers why a tool bypassed the ordinary stratified draw, and
tallies every such tool under one hardcoded label regardless of
reason — correct for its own purpose, but a spot-audit needs the
opposite property: which promotion event a tool’s read is
evidence for, kept separate per event, since a promotion next
month must never blend into this month’s numbers. xtask::audit’s
effective_stratum reads this field first and reports
spot-audit:<event> as its own row — one stratum per promotion,
never a single catch-all. An entry may carry both this field and
include_reason (the latter documents the draw itself: which event,
how many of the promoted set were available, the seed) — this field
alone decides the reported stratum.
families: Vec<String>Defect-family labels for a wrong/incomplete verdict: which
shapes of defect this tool exhibits, drawn from the closed set in
DEFECT_FAMILIES. Empty for a correct/skip entry (there is no
defect to name), and — importantly — also empty for a
wrong/incomplete entry nobody could confidently classify. That
second case is Entry::is_unclassified, and it is deliberately
representable: an honest “we do not know which family this is” is
worth far more than a fabricated label, because the whole purpose of
these labels is to calibrate a detector against them.
Stored as plain strings rather than an enum for the same reason
Self::verdict is: a hand-edited manifest with an unrecognized
family fails loudly at the point of use
(Entry::validate_families) rather than silently at
deserialization, where the error would name a line number and not a
tool.
A family is a shape, never a tool. spec §1’s no-per-tool-logic
rule applies here exactly as it does to a parser: tcpdump is not a
family, bundled-short-flag is, and the tool name is data.
families_derived: Option<bool>Provenance of Self::families, and the reason that field is safe
to have in a tracked manifest at all.
A verdict is a human judgment: a reviewer read the tool’s real output. A family label derived by a machine reading that reviewer’s prose is a strictly weaker claim, and this project’s posture (spec §13.1b’s fifth rule: a name a reader could mistake for a stronger claim is itself a defect) is that a weaker claim must be labelled as one rather than left to be inferred.
Some(true)— derived by machine from the reviewer’s note plus the fixture evidence. Not a reviewer’s own classification.Some(false)— the reviewer classified it themselves.None— no provenance recorded, whichEntry::validate_familiesrejects wheneverfamiliesis non-empty. Absence must never silently read as “a human said so”: a writer that forgets this field would otherwise launder a machine reading into a human judgment, which is the single worst outcome this schema can produce.
amendments: Vec<Amendment>A history of corrections applied to this entry’s original verdict,
oldest first — appended to, never used to overwrite Self::verdict
or Self::note. Empty for the overwhelming majority of entries,
which is exactly why this is a Vec that serializes to nothing when
empty rather than a field every existing manifest would need
migrating to carry: an audit/<seed>.toml written before this field
existed deserializes with amendments: vec![], identical in every
observable way to a freshly reviewed entry that has never been
amended. See Self::effective_verdict/Self::effective_note for
what a caller should actually read, and amend for how an entry
gets one of these appended.
Implementations§
Source§impl Entry
impl Entry
Sourcepub fn effective_verdict(&self) -> Option<&str>
pub fn effective_verdict(&self) -> Option<&str>
The verdict every aggregate computation (accuracy tallies, the
wrong/incomplete listing, fixture generation) should read: the
new_verdict of the most recent Amendment if this entry has any,
else the original Self::verdict untouched. A verdict amendment
changes what the project believes about a tool without destroying
the record of what a reviewer originally wrote — see amend’s doc
comment for the full rationale.
Sourcepub fn effective_note(&self) -> &str
pub fn effective_note(&self) -> &str
The note that belongs to Self::effective_verdict: the most
recent amendment’s new_note if this entry has been amended, else
the original Self::note. Never a concatenation of both — an
amendment’s new_note is a complete, self-contained note for the
corrected verdict (enforced by amend), not a delta on top of the
original.
Sourcepub fn missing_required_note(&self) -> bool
pub fn missing_required_note(&self) -> bool
True when this entry’s note is obligatory but missing or blank — a
wrong/incomplete verdict with nothing recorded about what was
wrong. Reads the effective verdict/note, so an amendment that
corrects a bare-note defect heals this the same way a plain
re-review would. See verdict_requires_note.
Sourcepub fn needs_attention(&self) -> bool
pub fn needs_attention(&self) -> bool
True when a review session should still stop at this entry: no verdict yet, or a verdict whose obligatory note never got written.
Sourcepub fn is_judged_defect(&self) -> bool
pub fn is_judged_defect(&self) -> bool
True when this entry is a judged defect — wrong or incomplete
under Self::effective_verdict. The population a family label is
about, and the population a detector is expected to fire on once
the label says it belongs to that detector’s family.
Sourcepub fn is_judged_correct(&self) -> bool
pub fn is_judged_correct(&self) -> bool
True when this entry is a judged non-defect — correct under
Self::effective_verdict. The population a detector must stay
silent on: a fire here is a false alarm against a human who read
the tool’s real output and said the parse was right.
skip is neither this nor Self::is_judged_defect. A skipped
entry carries no judgment about the parse at all (spec §13.1c
excludes it from the accuracy ratio for the same reason), so it can
neither confirm nor refute a detector and is excluded from
calibration entirely rather than silently counted as “good”.
Sourcepub fn is_unclassified(&self) -> bool
pub fn is_unclassified(&self) -> bool
True when this entry is a judged defect that carries no family label — the honest “nobody could tell which family this is” state. Counted and printed rather than hidden, because an unclassified entry is a known hole in a detector’s calibration set, and a hole you can see is not the same kind of problem as a hole papered over with a guess.
Sourcepub fn has_family(&self, family: &str) -> bool
pub fn has_family(&self, family: &str) -> bool
True when this entry carries family among its labels.
Sourcepub fn is_display_only(&self) -> bool
pub fn is_display_only(&self) -> bool
True when this judged defect (wrong/incomplete) is entirely
a display/rendering issue — the extraction itself is right, and
what the reviewer actually judged wrong is how mandible --review’s
TUI draws it (width, wrapping, a truncated bracket). Spec §13.1c
already draws this boundary for the audit’s scope (“usage-section
formatting” is explicitly deferred); this is that same boundary
applied to the accuracy denominator: a finding this method returns
true for must be excluded from crate::audit’s accuracy
arithmetic (xtask::audit::accuracy_over) while remaining fully
visible everywhere else — Self::effective_note, xtask audit report’s stratum table and its own out-of-scope line, and every
fixture xtask audit fixtures writes.
Structural, not an assertion — this is the part of the task that
actually matters. The tempting shortcut is “any entry that
mentions display-only in families,” but that alone would let a
mixed defect — a genuine parse-shape family (bundled-short-flag,
unparsed-flag, …) with display-only tacked on beside it — escape
the denominator on the strength of one true-but-irrelevant label.
That is exactly the free-text-reason failure mode
xtask::detector::Ground::BelowMemberThreshold replaced this week:
an exclusion must be computed from a witness the author cannot
forge by writing a persuasive sentence, not claimed by assertion.
The witness here is cheaper than Ground’s (no arithmetic to
compute — a label set has no continuous “how much”), but the same
discipline applies in the one dimension available: display-only
must be this entry’s only family. A tool with a real parse
defect can never also claim this exclusion just by naming
display-only as a second label, because a second label is exactly
what this check refuses. Composed with what Self::validate_families
already enforces — display-only must come from the closed
DEFECT_FAMILIES set, must carry Self::families_derived
provenance, and can only appear on a judged defect in the first
place — an entry cannot reach true here by hand-editing a stray
word into the manifest.
Sourcepub fn validate_families(&self) -> Result<()>
pub fn validate_families(&self) -> Result<()>
Check this entry’s Self::families/Self::families_derived pair
for every way it could be a claim nobody can evaluate later:
- a family word outside the closed
DEFECT_FAMILIESset (a typo, or an ad-hoc family invented in a hand edit and therefore invisible to every reader that matches on the set); - the same family listed twice (harmless to a matcher, but it makes a per-family count wrong, and counts are what calibration reports);
- labels with no recorded provenance — see
Self::families_derivedfor why silence there is unacceptable; - labels on a verdict that names no defect (
correct/skip), which would put a tool into a detector’s expected-fires set on the strength of a verdict that says nothing is wrong with it.