feat: add healthcheck ping wiring (lib/healthcheck.sh, opt-in) #348
No reviewers
Labels
No labels
Agent
Compat/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Abandoned
Status
Blocked
Status
Need More Info
No milestone
No assignees
2 participants
Notifications
Total time spent: 35 seconds
Due date
igor
35 seconds
No due date set.
Dependencies
No dependencies set
Reference
joshtronic/igor!348
Loading…
Reference in a new issue
No description provided.
Delete branch "agent/339-feat-healthcheck-ping-wiring-lib-healthcheck-sh"
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?
What this PR does
lib/healthcheck.sh, opt-in)hc_ping <which> [start|success|fail]-- best-effort curl,--max-time 10, always returns 0HEALTHCHECK_HEARTBEAT_URL-- plain ping at the top of every tick (dead-man's switch, check A)HEALTHCHECK_TASK_URL-- start ping once the tick clears the health/deploy gates, paired success/fail ping in the existingcleanup()EXIT trap so every exit path (including the cascade's many earlyexit 0s, and any crash) reports honestly (check B).env.example, both default empty -> clean no-op like the SMTP2GO/GSC gatesbin/test-healthcheck.sh(unset URL -> no curl call, URL set -> correct request built for base//start//fail, curl failure -> rc still 0)Both vars are new -- no existing var was renamed or reused. Neither
agent-settings.json,systemd/, nor.forgejo/workflows/were touched. Merges safe now; activation (standing up the healthchecks server + creating the two checks + dropping the URLs into.env) is the operator-side #297.Test plan
bash bin/check-sync.shpasses (outcome-sentinel sync check + everybin/test-*.sh, including the newtest-healthcheck.sh)bash -nonbin/tick.sh,lib/healthcheck.sh,bin/test-healthcheck.sh-- no syntax errors/security-reviewrun on the diff -- no findings (URL args are always trusted.env-sourced values or hardcoded literals, never attacker-influenced; output is fully discarded)Closes #339
lib/healthcheck.sh, opt-in)🤖 Review —
APPROVE(automated)CI for
73acc5ee: successOpt-in healthcheck ping wiring: a new
lib/healthcheck.sh(hc_ping), sourced and wired intobin/tick.sh(heartbeat + task start/success/fail), documented in.env.example, with unit tests. CI green. Approving.Verification against the checklist — all items hold up:
hc_ping <which> [start|success|fail]exists inlib/healthcheck.sh, usescurl -fsS --max-time 10 -o /dev/null, and alwaysreturn 0(both|| trueand the trailingreturn 0). ✅hc_ping heartbeat). ✅claude_health_blockedgate withHC_TASK_STARTED=1; paired success/fail lives incleanup()guarded onHC_TASK_STARTED. ✅.env.example, default empty, exported with:-defaults soset -uis safe. ✅/start//fail, state-omitted default, and curl-failure-still-rc0. ✅Correctness spot-checks:
cleanup()captureslocal rc=$?before anyhc_pingcall, so the ping's curl exit status can't clobber the real exit code. Ordering is right.HC_TASK_STARTEDguard correctly prevents false success/fail reports for ticks that bail at the health/deploy/cooldown gates (start never fired), while covering the cascade's earlyexit 0s and crashes via the EXIT trap. Sound design.curl() { CURL_URL="${*: -1}"; }correctly grabs the last arg (the URL);${*: -1}slicing is valid bash. Assertions match the real call shape.success→ base URL (healthchecks.io convention); consistent with the testtask (state omitted)case.Security: URLs are trusted
.env-sourced or unset; output discarded to/dev/null, stderr suppressed,--max-time 10bounds the network call. No injection surface. No CI/workflow files touched. Inert until #297 supplies real URLs.Scope: ~130 lines across 4 files, tightly focused on the one issue. No drive-by changes.
Nothing blocking. Clean, well-tested, no-op-by-default change.
Independent review by the harness on
claude-opus-4-8(effort: high). The human reviewer is requested once Igor has reviewed; a human still merges.CoS binding review: 🟢 GREEN — merge-ready.
Live-verified
hc_ping: no-op when the URL is unset (rc 0, no curl), survivesset -e, always returns 0 — a ping can never affect tick outcome. Correct healthchecks.io semantics (/start,/fail, base URL for success), 10s timeout, non-model (plain curl, runs even during a Claude cooldown).Checked the correctness-critical wiring (the false-alarm trap):
task startsits AFTER the health/deploy/cooldown early-exit gates and setsHC_TASK_STARTED.cleanup()(EXIT trap), guarded onHC_TASK_STARTEDand conditional onrc(0→success, else→fail).So every exit path reports honestly:
New env vars default empty (
set -usafe), documented, activation deferred to #297. 168 lines, CI green,test-healthcheck.shincluded. Merge-ready — inert until you set the URLs.New commits pushed, approval review dismissed automatically according to repository settings