fleetd #562 follow-up: extract loopHealthSource factory, pin its wiring (supersedes #579) #584

Closed
agent wants to merge 0 commits from worker/562-loop-health-wiring-test-99611c-5 into main
Member

fleetd #562 follow-up. This PR supersedes PR #579 (branch worker/562-surface-loop-health-7df5cc-4, fast-forward-merged onto this branch as the base commit) — #579's loopHealth field on fleet_list//healthz is good work and stays as-is; this adds the one thing the lead's "HOLD on PR #579" comment on issue #562 required before merge.

What was found

The lead mutated the production wiring in Fleetd.main: replacing poller::health with a constant () -> LoopWatchdog.State.RUNNING at the LoopHealthSource construction site compiled clean and left all 1771 existing tests green. The five tests #579 added all build their own LoopHealthSource with fixed lambdas — they prove the seam (LoopHealthSource reports what it's given), not what Fleetd.main actually gives it. That's a false negative: the daemon could always report the poller as RUNNING and the watchdog could never fire.

What this PR does

  1. Extracts Fleetd.loopHealthSource(StatusPoller poller, SessionReaper reaper) — a package-private factory in the same style as the existing sibling factories capacitySource(...) and healthCoverageSource(...). Fleetd.main now calls this factory instead of building the LoopHealthSource inline.
  2. Adds FleetdLoopHealthSourceWiringTest (package dev.ltms.fleet, follows FleetdHealthCoverageSourceWiringTest's pattern) with three separate assertions, each isolating one wired place:
    • the statusPoller half reports the real poller's health (not a hardcoded state)
    • the sessionReaper half reports the real reaper's health (not a hardcoded state)
    • reaper == null still reports STOPPED (the null check is kept — not deleted for simplicity)

Mutation proof (per the ticket's acceptance criteria)

Poller half — replaced poller::health with () -> LoopWatchdog.State.RUNNING:

[ERROR] dev.ltms.fleet.FleetdLoopHealthSourceWiringTest.statusPollerHalfReflectsThePollersRealHealth -- Time elapsed: 0.003 s <<< FAILURE!
org.opentest4j.AssertionFailedError: the statusPoller supplier must delegate to the real poller's health() — replacing poller::health with a constant () -> RUNNING at the Fleetd.loopHealthSource call site must fail this assertion ==> expected: <STOPPED> but was: <RUNNING>
[ERROR] Tests run: 3, Failures: 1, Errors: 0, Skipped: 0

Restored; shasum -a 256 fleetd/src/main/java/dev/ltms/fleet/Fleetd.java = d3c693e9e595228f5b41b185e94a49d86f1cb9ddd50ff9ddc6be2b73918659ea (matches pristine before and after).

Reaper half — replaced only the reaper.health() sub-expression (kept the reaper == null ternary branch intact) with () -> reaper == null ? LoopWatchdog.State.STOPPED : LoopWatchdog.State.RUNNING:

[ERROR] dev.ltms.fleet.FleetdLoopHealthSourceWiringTest.sessionReaperHalfReflectsTheReapersRealHealth -- Time elapsed: 0.182 s <<< FAILURE!
org.opentest4j.AssertionFailedError: the sessionReaper supplier must delegate to the real reaper's health() — replacing reaper.health() with a constant at the Fleetd.loopHealthSource call site must fail this assertion ==> expected: <STOPPED> but was: <RUNNING>
[ERROR] Tests run: 3, Failures: 1, Errors: 0, Skipped: 0

Only that one assertion failed — nullReaperStillReportsStopped stayed green under this surgical mutation, proving that third assertion is genuinely independent of the reaper-health assertion. Restored; sha256 matched pristine again.

Build

mvn -o clean install from fleetd/, full unpiped run: Tests run: 1774, Failures: 0, Errors: 0, Skipped: 0, BUILD SUCCESS. 1774 = the 1771 baseline on #579's branch + 3 new tests in this PR.

Scope

Exactly one extraction + one test class, nothing else touched. loopHealth's reported values and serialization are unchanged.

Caveat for review — CLAUDE.md/wiki sync check not run

I could not run the CLAUDE.md/wiki/7-Use-Cases.md sync check mentioned in this repo's CLAUDE.md — my worktree has wiki/ uninitialized (git submodule status shows a leading -), which is documented as unsatisfiable for a member. I am not proposing any CLAUDE.md edit myself; PR #579 already touched CLAUDE.md (the fleet_list intent→tool table row) and that change came in via merging #579's branch as this PR's base — the lead should verify that edit against the sync check when merging, since I have no way to run it.

fleetd #562 follow-up. This PR **supersedes PR #579** (branch `worker/562-surface-loop-health-7df5cc-4`, fast-forward-merged onto this branch as the base commit) — #579's `loopHealth` field on `fleet_list`/`/healthz` is good work and stays as-is; this adds the one thing the lead's "HOLD on PR #579" comment on issue #562 required before merge. ## What was found The lead mutated the production wiring in `Fleetd.main`: replacing `poller::health` with a constant `() -> LoopWatchdog.State.RUNNING` at the `LoopHealthSource` construction site compiled clean and left all 1771 existing tests green. The five tests #579 added all build their own `LoopHealthSource` with fixed lambdas — they prove the seam (`LoopHealthSource` reports what it's given), not what `Fleetd.main` actually gives it. That's a false negative: the daemon could always report the poller as `RUNNING` and the watchdog could never fire. ## What this PR does 1. **Extracts `Fleetd.loopHealthSource(StatusPoller poller, SessionReaper reaper)`** — a package-private factory in the same style as the existing sibling factories `capacitySource(...)` and `healthCoverageSource(...)`. `Fleetd.main` now calls this factory instead of building the `LoopHealthSource` inline. 2. **Adds `FleetdLoopHealthSourceWiringTest`** (package `dev.ltms.fleet`, follows `FleetdHealthCoverageSourceWiringTest`'s pattern) with three separate assertions, each isolating one wired place: - the `statusPoller` half reports the real poller's health (not a hardcoded state) - the `sessionReaper` half reports the real reaper's health (not a hardcoded state) - `reaper == null` still reports `STOPPED` (the null check is kept — not deleted for simplicity) ## Mutation proof (per the ticket's acceptance criteria) **Poller half** — replaced `poller::health` with `() -> LoopWatchdog.State.RUNNING`: ``` [ERROR] dev.ltms.fleet.FleetdLoopHealthSourceWiringTest.statusPollerHalfReflectsThePollersRealHealth -- Time elapsed: 0.003 s <<< FAILURE! org.opentest4j.AssertionFailedError: the statusPoller supplier must delegate to the real poller's health() — replacing poller::health with a constant () -> RUNNING at the Fleetd.loopHealthSource call site must fail this assertion ==> expected: <STOPPED> but was: <RUNNING> [ERROR] Tests run: 3, Failures: 1, Errors: 0, Skipped: 0 ``` Restored; `shasum -a 256 fleetd/src/main/java/dev/ltms/fleet/Fleetd.java` = `d3c693e9e595228f5b41b185e94a49d86f1cb9ddd50ff9ddc6be2b73918659ea` (matches pristine before and after). **Reaper half** — replaced only the `reaper.health()` sub-expression (kept the `reaper == null` ternary branch intact) with `() -> reaper == null ? LoopWatchdog.State.STOPPED : LoopWatchdog.State.RUNNING`: ``` [ERROR] dev.ltms.fleet.FleetdLoopHealthSourceWiringTest.sessionReaperHalfReflectsTheReapersRealHealth -- Time elapsed: 0.182 s <<< FAILURE! org.opentest4j.AssertionFailedError: the sessionReaper supplier must delegate to the real reaper's health() — replacing reaper.health() with a constant at the Fleetd.loopHealthSource call site must fail this assertion ==> expected: <STOPPED> but was: <RUNNING> [ERROR] Tests run: 3, Failures: 1, Errors: 0, Skipped: 0 ``` Only that one assertion failed — `nullReaperStillReportsStopped` stayed green under this surgical mutation, proving that third assertion is genuinely independent of the reaper-health assertion. Restored; sha256 matched pristine again. ## Build `mvn -o clean install` from `fleetd/`, full unpiped run: **`Tests run: 1774, Failures: 0, Errors: 0, Skipped: 0`**, `BUILD SUCCESS`. 1774 = the 1771 baseline on #579's branch + 3 new tests in this PR. ## Scope Exactly one extraction + one test class, nothing else touched. `loopHealth`'s reported values and serialization are unchanged. ## Caveat for review — CLAUDE.md/wiki sync check not run I could not run the `CLAUDE.md`/`wiki/7-Use-Cases.md` sync check mentioned in this repo's `CLAUDE.md` — my worktree has `wiki/` uninitialized (`git submodule status` shows a leading `-`), which is documented as unsatisfiable for a member. I am not proposing any `CLAUDE.md` edit myself; PR #579 already touched `CLAUDE.md` (the `fleet_list` intent→tool table row) and that change came in via merging #579's branch as this PR's base — the lead should verify that edit against the sync check when merging, since I have no way to run it.
agent added 2 commits 2026-09-12 15:16:57 +02:00
fleetd #562: surface loop health
CI / shell-tests (pull_request) Successful in 12s
CI / contract (pull_request) Successful in 1m31s
CI / build (pull_request) Successful in 2m11s
275ac0d251
fleetd #562 follow-up: extract loopHealthSource factory, pin its wiring
CI / shell-tests (pull_request) Successful in 6s
CI / contract (pull_request) Successful in 59s
CI / build (pull_request) Successful in 1m43s
1513d4f260
PR #579's inline `new FleetMcp.LoopHealthSource(poller::health, ...)` in
Fleetd.main had nothing a test could call directly. Measured: replacing
poller::health with a constant () -> RUNNING compiled clean and left all
1771 tests green (see issue #562 comment "HOLD on PR #579").

Extracts the inline construction to a package-private Fleetd.loopHealthSource
factory, the same style as the sibling capacitySource/healthCoverageSource
factories, and adds FleetdLoopHealthSourceWiringTest with three separate
assertions: the statusPoller half, the sessionReaper half, and the
reaper == null branch (still STOPPED).
Owner

Already in main — closing as merged.

Head 1513d4f26 is an ancestor of origin/main, brought in by 634d33b50
("Merge worker/562-loop-health-wiring-test-99611c-5"). The merge was done locally and pushed, so
Gitea never marked the PR merged.

$ git merge-base --is-ancestor 1513d4f26 origin/main && echo merged
merged
$ git rev-list --ancestry-path --reverse 1513d4f26..origin/main --merges | head -1
634d33b50

Note for #579: that branch came in through this same merge commit, because this branch was
built on top of it. So closing #579 as merged too is correct and is not a second landing.

Already in `main` — closing as merged. Head `1513d4f26` is an ancestor of `origin/main`, brought in by `634d33b50` ("Merge worker/562-loop-health-wiring-test-99611c-5"). The merge was done locally and pushed, so Gitea never marked the PR merged. ``` $ git merge-base --is-ancestor 1513d4f26 origin/main && echo merged merged $ git rev-list --ancestry-path --reverse 1513d4f26..origin/main --merges | head -1 634d33b50 ``` Note for #579: that branch came in through **this same merge commit**, because this branch was built on top of it. So closing #579 as merged too is correct and is not a second landing.
ltms closed this pull request 2026-09-12 16:42:37 +02:00
Some checks are pending
CI / shell-tests (pull_request) Successful in 6s
CI / contract (pull_request) Successful in 59s
CI / build (pull_request) Successful in 1m43s

Pull request closed

Sign in to join this conversation.