Skip to main content

Entry

Struct Entry 

Source
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: String

The tool name as found on PATH (or supplied via --tools).

§stratum: String

The 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: String

The 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 closedexistence::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 --help heading (git-lfs: 36 nodes, 34 suspects, status suspicious, 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 eventNone 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, which Entry::validate_families rejects whenever families is 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

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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”.

Source

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.

Source

pub fn has_family(&self, family: &str) -> bool

True when this entry carries family among its labels.

Source

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.

Source

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_FAMILIES set (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_derived for 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.

Trait Implementations§

Source§

impl Clone for Entry

Source§

fn clone(&self) -> Entry

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Entry

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for Entry

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Serialize for Entry

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

§

impl Freeze for Entry

§

impl RefUnwindSafe for Entry

§

impl Send for Entry

§

impl Sync for Entry

§

impl Unpin for Entry

§

impl UnsafeUnpin for Entry

§

impl UnwindSafe for Entry

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.