Audit pipeline: evidence-strength classifications unstable across measurement windows #11
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Why: During Phase 7 acceptance testing, the pipeline (
bin/offload-scan->bin/boundary-classify) produced a candidate with two DIFFERENT evidence-strength classifications depending only on the measurement window. This directly undermines the plugin's core value proposition — confidently recommending a candidate as "measured" when a different window shows it as "thin" is exactly the "plausible-looking wrong recommendation" failure mode that design/rubric.md warns is worse than missing a candidate.Symptom: Candidate
anxious/agent-wip/release-policy-derivation:measurement_strength: "measured", cost3.9M weighted tokens = 12% of audited spend— issue body presented confidently with no caveatshare_of_audited_spend: 0.0,offload_value: 0,measurement_strength: "thin"— classifier reason text explicitly says "evidence is thin ... must be stated as such in the issue body"Impact: A human reviewing only the full-window body sees "measured" + confident 12% with no hint that a shorter window shows nothing. Window-sensitivity is not surfaced, violating the audit's transparency contract. Found during Phase 7 (S4 scenario) acceptance testing by adversarial triage review.
Secondary: Per-invocation weighted-token figure for
anxious:agent-wipis ~989k (for a skill whose actual job is ~10 MCP calls). Suggests whole-session attribution may be bleeding into skill-level cost figures rather than isolating actual mechanical/release-related turns — investigate whetheroffload-scan's invocation-reconstruction or attribution logic is over-attributing session-wide activity.Acceptance:
bin/boundary-classify— re-run classification across 2+ windows on failing candidate and confirm consistencyoffload-scan— verify skill-level cost figures isolate only relevant turns, not session-wide bleedLinks: Phase 7 acceptance testing (S4 scenario); design/rubric.md failure-mode warning
Fixed by commit
dcec9caonmain— the instability is now caught mechanically before filing, rather than by a human running a second review.What was built.
bin/stability-classify, a hard gate in the same register as FR-4.2's overrule-case gate. It runs afterbin/boundary-classifyand beforebin/filing-plan. For every candidate whose verdict isfile, it matches the candidate against the most recent prior snapshot that recorded it (FR-5.2 identity: issue > signature hash > slug) and downgrades it to a boundary question — never filed — if either:measurement_strengthdiffers between the two windows (measured/thin/unmeasured), orshare_of_audited_spendlands on opposite sides of the 2% filing threshold.Movement within a label is explicitly not instability (12% → 8% stays filed; that is a trend, and
audit-snapshot diffalready reports it). No prior window meansstability: uncheckedand the candidate files normally — an absence of history is not evidence of instability, and doing otherwise would contradict FR-2.4.Proof on the real data from this issue. Both Phase 7 windows are kept verbatim as fixtures. Running the gate on the 7-day classification with the 30-day snapshot in the store:
It is symmetric: classifying the 30-day window against the 7-day snapshot downgrades it too. Both windows cannot be right — which is the point.
Self-reporting. A downgrade produces a
stability_findingsentry that is a finding against this repo, not the target's: the target did not change, the auditor described it two ways. It carries an<!-- ia-stability: <candidate_id> -->marker so a re-run comments instead of duplicating, mirroring FR-6.3.Acceptance checklist from this issue:
anxious:agent-wipshowing ~989k weighted tokens per invocation, suggestingbin/offload-scanmay be attributing session-wide activity to a skill rather than isolating its own turns. That is a separate defect in the dynamic pass and is filed separately (see below); it does not block this gate, which works on whatever numbers the scan produces.Documented as: spec FR-4.5, rubric §5b ("The evidence-stability gate"), shipped verbatim in
references/boundary-rubric.md. Wired intoskills/offload-audit/SKILL.mdas step 4b.bin/ia_store.pyfactors store access and identity resolution out ofbin/audit-snapshotso both scripts hash signatures identically — a divergence there would make the gate match nothing and fail open.Tests:
tests/stability.test.sh, six cases including (f), the real two-windowanxiousevidence. Full suite 178 assertions, exit 0.