fix(control)+test: terminal status on every control_apply exit; pin five failure paths - #287
Merged
Merged
Conversation
…ive failure paths Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements all five items of #276 (2026-07 repo-scan test-gap pass). One real code fix (item 1b); the rest are tests pinning previously untested failure/wiring paths.
Item 1 —
control_applyrollback double-failure + unreadable backup (code fix + tests)1(b) code fix (
rigforge.sh, control_apply): the rollback'scp "$backup" "$CONFIG_JSON"was unguarded — an unreadable backup ERR-trapped the oneshot out underset -Eeuo pipefailwith NO status written, so the receiver kept serving the stale previous outcome forever. Thecpis now explicitly guarded: on failure the applier writes a terminalfailedstatus with reasonrollback backup unreadable: <path>and returns 0.1(a) contract pin: the rollback re-apply's own success/failure is now distinguishable in the
rolled_backreason string —...; rolled back and livevs...; rollback re-apply also failed to restore liveness— so a dashboard can tell a self-healed rig from one still down.Tests extend the existing
ca_runharness: a call-counting_wait_miner_livestub (CA_ROLLBACK_OKdrives the 2nd call, defaulting toCA_APPLY_OKso all pre-existing cases are unchanged) plus aCA_BACKUP_UNREADABLEhook that swaps the backup file for a directory (robust even when the suite runs as root under kcov, wherechmod 000wouldn't bite).Item 2 — tune abort restarts the stopped miner (test)
Black-box tune with a fake xmrig that exits nonzero without a hashrate line on candidate 2 (single-knob prefetch sweep makes candidate 2 deterministic). Asserts the
Restarting the 'xmrig' servicelog line AND the recorded[systemctl] start xmrigshim call — pinning the_tune_bench_cleanupEXIT trap on the crash path, not just the happy path.Item 3 —
apply→_stamp_config_meta localwiring (test)After the existing black-box apply run, assert
.rigforge-config-meta.jsonexists with"source": "local". Previously every #254 test drove the helper directly, so deleting the call site inapplypassed the whole suite while fleet provenance silently froze.Item 4 — changes/ index keep-20 prune (test)
Loop
_control_statusthrough 22 distinct change_ids (the two oldest separated by real mtime gaps); assert exactly 20 files remain, both oldest are gone, and survivors 3 and 22 are present.Item 5 —
api_refreshpartial-failure atomicity (test)Stub
_api_rigforge_blockto emit a block whosehealthis a string (so only health.json's ownjq '.health + {...}'extraction fails); assert the previoushealth.jsoncontent still serves whilesummary.jsonandtune.jsonstill updated — pinning the per-fileprintf | jq && mvatomicity so a refactor to a single non-atomic write goes red.Verification
make test(lint + suite): 1371 passed, 0 failed after rebasing onto latest develop.failedstatus + its reason)._stamp_config_metacall in apply() neutralized → 2 failures.Closes #276
🤖 Generated with Claude Code