Skip to content

fix: the round-2 audit blockers — my own blocker fix was a no-op - #386

Merged
kengio merged 3 commits into
mainfrom
fix-audit-round2
Aug 4, 2026
Merged

fix: the round-2 audit blockers — my own blocker fix was a no-op#386
kengio merged 3 commits into
mainfrom
fix-audit-round2

Conversation

@kengio

@kengio kengio commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Second full-epic audit returned DO-NOT-TAG. It found that the fix for the first audit's blocker 1 could never fire, and that the fix for blocker 2 had traded a false positive for a false negative. Both verified against the release machine's real plists before acting.

The no-op, and why three layers of verification agreed it was fine

skill_mode_plists_are_current had to tell skill-mode from command-mode. It keyed that on the absence of ONEBRAIN_SCHEDULED — which is the very property whose absence defines a stale plist.

Measured on the release machine:

stale skill-mode (daily):   StandardOutPath=1  ONEBRAIN_SCHEDULED=0
command-mode (reindex):     StandardOutPath=1  ONEBRAIN_SCHEDULED=0

Byte-identical in exactly the two fields the classifier read. So every stale skill-mode plist was classified as command-mode and skipped, and the stale branch was unreachable by construction. The audit reproduced the false reassurance verbatim by copying the real plists into a fixture and running the shipped binary.

Three things agreed it was correct and all three were blind for the same reason:

  • the test hand-injected Some(false) into the consumer (scheduler_log_dir_verdict) and never fed a plist body to the classifier
  • the sabotage inherited that blind spot — it broke the consumer's branch, not the classifier's logic
  • my own reading followed the branch I had written correctly and never questioned the predicate

Fix: classify by ProgramArguments containing skill + run — emitted only by the skill-mode renderer, and independent of both the redirect and the marker. The probe is split into a pure classify_plists_in(dir) so tests drive real plist bodies, including the mixed case where a current plist must not mask a stale one. Restoring the old marker-based classifier now fails that test.

That split is the v3.4.22 lesson applied again: a check that reads $HOME cannot be tested without lying about the machine it runs on.

Blocker 2's fix overcorrected

Entries whose window had not elapsed were suppressed from the accusation — correct — but still counted into observed, so the verdict returned:

✓ scheduled output   all producing output — 3 observable, 0 without a record to check

…over an entry that had produced nothing. A monthly job with a fire window three days past, inside the mechanism's lifetime, silently vouched for. The first fix removed a false accusation and installed a false reassurance one branch over.

They are now named as too soon to judge rather than folded into a green claim. ab885e8's own commit message set the standard this violated: "Reporting green while unable to distinguish 'new' from 'all dead' is the check overstating its reach."

Windows had no CLI-owned job log at all, and the failure erased its own evidence

write_job_log did env::var("HOME").map(PathBuf::from).ok()?. HOME is normally unset on Windows, so:

  1. the ? short-circuited — default_log_dir's LOCALAPPDATA branch was unreachable from this caller
  2. the None it returned is the same value that means "log written fine", so build_tail added no [job log unavailable: …] note

Two failures hiding each other. Uses dirs::home_dir() now and returns a real reason when it cannot resolve. CI would not have caught this either — nothing asserts a job log exists on Windows, and the tests touching this path pin HOME, which masks it.

CHANGELOG bullet corrected

It said the warning "names only the entries it is fatal for". After the blocker fix the stale path deliberately says ALL entries will fail — which is true while the plists are pre-v3.4.23. Bullet rewritten to describe both states.

Guards

sabotage result
restore the marker-based classifier (the exact shipped no-op) RED
fold suppressed entries back into "all producing output" RED

Gates — bare, real exit codes, on a disk with room

The previous audit's cargo test and coverage runs died on No space left on device — the host was at 100% from five cargo worktrees left by this epic. 41 GB reclaimed; those gates were UNKNOWN, not failing.

cargo fmt --check                                        exit=0
cargo clippy --workspace --all-targets -- -D warnings    exit=0
cargo test --workspace                                   exit=0  (48 suites, 0 failed, 0 ENOSPC)
bash scripts/coverage.sh --ci-gate                       exit=0  (TOTAL 94.54%)

The audit will be re-armed against this tree. Two consecutive audits have each found real blockers inside the previous audit's fixes, so a third pass is not ceremony.

kengio added 2 commits August 4, 2026 13:38
The re-audit found the guard I added for blocker 1 could never fire. It
classified command-mode-vs-skill-mode by the ABSENCE of ONEBRAIN_SCHEDULED —
which is the very property whose absence defines staleness. A stale skill-mode
plist (redirect, no marker) is byte-identical to a command-mode one in exactly
those two fields, so it was classified as command mode and skipped, and the
stale branch was unreachable. On the release machine the shipped binary emitted
the false reassurance verbatim, against the real plists.

The test could not catch it: it hand-injected Some(false) into the CONSUMER and
never fed a plist body to the CLASSIFIER. The sabotage inherited the same blind
spot. Now classified by ProgramArguments containing skill+run, which no
command-mode plist emits and which is independent of both the redirect and the
marker; and the probe is split into a pure classify_plists_in(dir) so tests
drive real plist bodies, including the mixed case where one current plist must
not mask a stale one. Restoring the old classifier now fails that test.

Blocker 2's fix had traded a false positive for a false negative: entries whose
window had not elapsed were suppressed from the accusation but still counted
into 'all producing output', so doctor asserted health for entries that had
produced nothing. The same overstatement, one branch over. They are now named
as too-soon-to-judge rather than folded into a green claim.

Also: write_job_log short-circuited on env::var("HOME"), unset on Windows, so
the LOCALAPPDATA branch was unreachable and Windows silently had no CLI-owned
job log — and the None it returned is the same value that means 'written fine',
so the record carried no [job log unavailable] note either. Two failures hiding
each other. Uses dirs::home_dir() and reports a real reason now.

The CHANGELOG bullet describing the log-dir warning was written before the
blocker fix changed that message and no longer matched it.
@kengio kengio added this to the v3.4.23 milestone Aug 4, 2026
Its only caller is the cfg(macos) resolver, so on Linux and Windows the
function has no caller in the non-test build and clippy -D warnings rejects it.
Local clippy on macOS structurally cannot see this — the caller exists there.
CI's Linux leg caught it.

Kept ungated with a conditional allow rather than cfg'd to macOS: the logic is
pure string matching over a plist body, so it stays testable on every platform,
which is the whole reason it was split out of the $HOME resolver.

The profile documents a cross-check for exactly this class
(cargo clippy --target <other>) and I did not run it before pushing. It would
not have helped here anyway — onebrain-cli cannot cross-compile locally because
ring needs Windows headers, and the Linux std is not installed — so CI is the
only available verifier for this file. Saying so rather than implying I proved
it.
@kengio
kengio merged commit 2511676 into main Aug 4, 2026
21 checks passed
@kengio
kengio deleted the fix-audit-round2 branch August 4, 2026 09:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant