Stale-loop nudge: warn after 3 consecutive identical fetch failures#72
Conversation
…#99) A local, privacy-neutral failure-loop detector for `aisbom scan`. The 2026-07-11 cli_error investigation found the fleet error rate dominated by one cron machine failing identically every day; its operator's own logs are the only channel we can reach. - New aisbom/loop_state.py: persists ~/.aisbom/loop_state.json with the failure shape (error_type / http_status bucket / target_type — never a URL or repo id), a consecutive-run counter, and a timestamp. Atomic writes, never raises, silent no-op on unwritable dirs. Local-only UX state: maintained even under AISBOM_NO_TELEMETRY, cleared when a scan of the same target class succeeds. - cli.py: both failure paths (caught fetch failures + unexpected crashes) feed the detector; from the 3rd identical failure a stderr panel prints status-aware remediation (HF_TOKEN hint on 401/403, upgrade hint only when the background version check already knows a newer release). cli_error events gain consecutive_failures (bucketed 1-9 / 10+). - Sharded-model dedupe: N identical per-file fetch errors now print one line with a "+N-1 more files" count instead of N near-identical lines. - Docs: README "Local state (no network)" privacy subsection + auth loop-nudge note; action/README_ACTION.md troubleshooting reworked to cover no_pr_context / fork PRs / missing pull-requests:write.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fc54f9576f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| payload = _scan_error_payload(err.get('exception'), target) | ||
| payload["consecutive_failures"] = loop_state.bucket_count(loop_count) |
There was a problem hiding this comment.
Keep per-error telemetry counters aligned with failure shapes
When one scan contains mixed fetch failures (for example, one shard returns 401 while another times out), the state counter is calculated only from the first failure but is attached to every cli_error. Thus, after three consecutive 401 runs, a timeout emitted in the same run is reported with consecutive_failures="3" even if that timeout has never repeated, corrupting the documented per-failure-shape telemetry dimension. Compute a count for each emitted fingerprint, or only attach the recorded count to the matching failure.
Useful? React with 👍 / 👎.
Implements aisbom-ops #99 (CLI stale-loop nudge).
What
aisbom/loop_state.py— persists~/.aisbom/loop_state.jsonwith the failure shape of the last failing scan (error_type/http_statusbucket /target_type— never a URL, repo id, or path), a consecutive-run counter, and a timestamp. Atomic writes, never raises, silent no-op when~/.aisbomis unwritable. Local-only UX state: maintained even underAISBOM_NO_TELEMETRY, cleared when a scan of the same target class succeeds.cli_errortelemetry gainsconsecutive_failures, bucketed1–9/10+.✖line with(+11 more files with the same error)instead of 12 near-identical lines. Telemetry emission stays per-file (feat(remote): authenticated HuggingFace scans (HF-only bearer token) #58 semantics unchanged).consecutive_failuresin thecli_errordescription, loop-nudge note under Authentication.action/README_ACTION.md: troubleshooting reworked into "Why isn't the Action posting comments on my PRs?" covering the three log-distinguished causes (no_pr_contexttrigger, fork-PR read-only token, missingpull-requests: write).Why
The 2026-07-11 cli_error investigation traced the fleet error rate to one machine on CLI 0.10.0 running ~daily automated scans of a gated HF repo with no token (133 of 212 errors in 25 days). The operator of an anonymous cron machine has exactly one reachable channel: their own logs.
Verification
hf://google/gemma-3-27b-it(gated, no token): runs 1–2 normal errors only; run 3 prints the nudge; state file carries only buckets + count; exit codes unchanged; founder-verified including token-present wording and counter persistence🤖 Generated with Claude Code