ward doctor: host-side Ollama-reachability probe for goose/opencode dispatch #499

Closed
opened 2026-07-02 02:45:38 +00:00 by coilysiren · 6 comments
Owner

Found

During ward#487 (retro, ward#492 burndown session): #487 landed the pre-launch Ollama-reachability gate in both bootstrap paths (entrypoint.sh + the Go LaunchGate), so an unreachable local endpoint now aborts at container launch instead of hanging. What is still missing is the earlier, cheaper signal: a host-side ward doctor probe that surfaces the down endpoint before any dispatch is attempted.

Deliverable

  • A doctor check mirroring the launch gate's reachability probe, keyed off the same local-harness endpoint config, so ward doctor fails legibly when goose/opencode dispatch would abort.

Cross-refs

  • ward#487 - the launch-side gate this mirrors.

Filed by Claude Code (Fable) during the ward#492 burndown session.

## Found During ward#487 (retro, ward#492 burndown session): #487 landed the pre-launch Ollama-reachability gate in both bootstrap paths (entrypoint.sh + the Go `LaunchGate`), so an unreachable local endpoint now aborts at container launch instead of hanging. What is still missing is the earlier, cheaper signal: a host-side `ward doctor` probe that surfaces the down endpoint before any dispatch is attempted. ## Deliverable * A doctor check mirroring the launch gate's reachability probe, keyed off the same local-harness endpoint config, so `ward doctor` fails legibly when goose/opencode dispatch would abort. ## Cross-refs * ward#487 - the launch-side gate this mirrors. Filed by Claude Code (Fable) during the ward#492 burndown session.
Member

🔒 Reserved by ward agent --driver claude — container engineer-claude-ward-499 on host KAI-DESKTOP-TOWER is carrying this issue (reserved 2026-07-03T17:34:21Z). Concurrent ward agent runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); --force overrides.

Do not comment on or edit this issue to steer the run while it is reserved. The engineer seeded the body once at launch and never re-reads it, so a comment or edit reaches only human readers, never the running engineer. A correction goes to a new issue, dispatched fresh — that is the only channel that reaches a run in flight. Where the forge supports it, ward locks this conversation to make that a road-block rather than a convention (ward#494).

— Claude (she/her), via ward agent

<!-- ward-agent-reservation --> 🔒 Reserved by `ward agent --driver claude` — container `engineer-claude-ward-499` on host `KAI-DESKTOP-TOWER` is carrying this issue (reserved 2026-07-03T17:34:21Z). Concurrent `ward agent` runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); `--force` overrides. **Do not comment on or edit this issue to steer the run while it is reserved.** The engineer seeded the body once at launch and never re-reads it, so a comment or edit reaches only human readers, never the running engineer. A correction goes to a **new issue, dispatched fresh** — that is the only channel that reaches a run in flight. Where the forge supports it, ward locks this conversation to make that a road-block rather than a convention (ward#494). <!-- ward-agent-signature --> — Claude (she/her), via `ward agent`
Author
Owner

WARD-OUTCOME: done - ward doctor now probes the operator-configured local-harness Ollama endpoint host-side, mirroring the ward#487 launch gate.

Smooth run, one real fork in the road. The launch-gate half already existed (ollamaprobe.PreLaunch), so the shape was clear: extract a single-dial ReachOnce next to the windowed launch probe and render it in doctor. The thing that fought back was the ward#425 ratchet - my first cut put "goose"/"opencode"/"ollama" string literals straight into cmd/ward/doctor.go, and the TestNoPerAgentLiteralsInCore guard rightly rejected it. That pushed the target-resolution, probe, and all the result text down into internal/agents/ollamaprobe, with core just rendering generic rows - which is honestly the better design anyway, so a good nudge.

The one judgement call worth flagging: I made an unconfigured endpoint (WARD_OLLAMA_URL / WARD_GOOSE_OLLAMA_HOST_B64 both unset) a SKIP, not a FAIL, so a plain adopter ward doctor in a repo that never touches goose/opencode stays green and the baked fleet default is left to the in-container gate. The cost is that an operator who relies on the localhost default without setting the env gets no host-side probe - the SKIP row names exactly how to opt in. Confident in that trade for CI-safety, but it's the spot a reviewer might want to revisit.

Verified all four paths against the built binary (SKIP / PASS on a live listener / FAIL on a dead port for both harnesses / --skip ollama), plus unit + pre-commit. Rough edge: the code-comments 2-line cap meant trimming a lot of the rationale out of comments and into docs/doctor.md - fine, but worth knowing the prose lives there now. No follow-ups I'd file.

WARD-OUTCOME: done - `ward doctor` now probes the operator-configured local-harness Ollama endpoint host-side, mirroring the ward#487 launch gate. Smooth run, one real fork in the road. The launch-gate half already existed (`ollamaprobe.PreLaunch`), so the shape was clear: extract a single-dial `ReachOnce` next to the windowed launch probe and render it in doctor. The thing that fought back was the ward#425 ratchet - my first cut put "goose"/"opencode"/"ollama" string literals straight into `cmd/ward/doctor.go`, and the `TestNoPerAgentLiteralsInCore` guard rightly rejected it. That pushed the target-resolution, probe, and all the result text down into `internal/agents/ollamaprobe`, with core just rendering generic rows - which is honestly the better design anyway, so a good nudge. The one judgement call worth flagging: I made an unconfigured endpoint (`WARD_OLLAMA_URL` / `WARD_GOOSE_OLLAMA_HOST_B64` both unset) a **SKIP**, not a FAIL, so a plain adopter `ward doctor` in a repo that never touches goose/opencode stays green and the baked fleet default is left to the in-container gate. The cost is that an operator who relies on the localhost default without setting the env gets no host-side probe - the SKIP row names exactly how to opt in. Confident in that trade for CI-safety, but it's the spot a reviewer might want to revisit. Verified all four paths against the built binary (SKIP / PASS on a live listener / FAIL on a dead port for both harnesses / `--skip ollama`), plus unit + pre-commit. Rough edge: the code-comments 2-line cap meant trimming a lot of the rationale out of comments and into docs/doctor.md - fine, but worth knowing the prose lives there now. No follow-ups I'd file.
Member

🔒 Reserved by ward agent --driver claude — container engineer-claude-ward-499 on host KAI-DESKTOP-TOWER is carrying this issue (reserved 2026-07-04T08:27:11Z). Concurrent ward agent runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); --force overrides.

Do not comment on or edit this issue to steer the run while it is reserved. The engineer seeded the body once at launch and never re-reads it, so a comment or edit reaches only human readers, never the running engineer. A correction goes to a new issue, dispatched fresh — that is the only channel that reaches a run in flight. Where the forge supports it, ward locks this conversation to make that a road-block rather than a convention (ward#494).

— Claude (she/her), via ward agent

<!-- ward-agent-reservation --> 🔒 Reserved by `ward agent --driver claude` — container `engineer-claude-ward-499` on host `KAI-DESKTOP-TOWER` is carrying this issue (reserved 2026-07-04T08:27:11Z). Concurrent `ward agent` runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); `--force` overrides. **Do not comment on or edit this issue to steer the run while it is reserved.** The engineer seeded the body once at launch and never re-reads it, so a comment or edit reaches only human readers, never the running engineer. A correction goes to a **new issue, dispatched fresh** — that is the only channel that reaches a run in flight. Where the forge supports it, ward locks this conversation to make that a road-block rather than a convention (ward#494). <!-- ward-agent-signature --> — Claude (she/her), via `ward agent`
Member

🔒 Reserved by ward agent --driver claude — container engineer-claude-ward-499 on host KAI-DESKTOP-TOWER is carrying this issue (reserved 2026-07-04T08:27:11Z). Concurrent ward agent runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); --force overrides.

Do not comment on or edit this issue to steer the run while it is reserved. The engineer seeded the body once at launch and never re-reads it, so a comment or edit reaches only human readers, never the running engineer. A correction goes to a new issue, dispatched fresh — that is the only channel that reaches a run in flight. Where the forge supports it, ward locks this conversation to make that a road-block rather than a convention (ward#494).

— Claude (she/her), via ward agent

<!-- ward-agent-reservation --> 🔒 Reserved by `ward agent --driver claude` — container `engineer-claude-ward-499` on host `KAI-DESKTOP-TOWER` is carrying this issue (reserved 2026-07-04T08:27:11Z). Concurrent `ward agent` runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); `--force` overrides. **Do not comment on or edit this issue to steer the run while it is reserved.** The engineer seeded the body once at launch and never re-reads it, so a comment or edit reaches only human readers, never the running engineer. A correction goes to a **new issue, dispatched fresh** — that is the only channel that reaches a run in flight. Where the forge supports it, ward locks this conversation to make that a road-block rather than a convention (ward#494). <!-- ward-agent-signature --> — Claude (she/her), via `ward agent`
Member

🔒 Reserved by ward agent --driver claude — container engineer-claude-ward-499 on host KAI-DESKTOP-TOWER is carrying this issue (reserved 2026-07-04T08:27:11Z). Concurrent ward agent runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); --force overrides.

Do not comment on or edit this issue to steer the run while it is reserved. The engineer seeded the body once at launch and never re-reads it, so a comment or edit reaches only human readers, never the running engineer. A correction goes to a new issue, dispatched fresh — that is the only channel that reaches a run in flight. Where the forge supports it, ward locks this conversation to make that a road-block rather than a convention (ward#494).

— Claude (she/her), via ward agent

<!-- ward-agent-reservation --> 🔒 Reserved by `ward agent --driver claude` — container `engineer-claude-ward-499` on host `KAI-DESKTOP-TOWER` is carrying this issue (reserved 2026-07-04T08:27:11Z). Concurrent `ward agent` runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); `--force` overrides. **Do not comment on or edit this issue to steer the run while it is reserved.** The engineer seeded the body once at launch and never re-reads it, so a comment or edit reaches only human readers, never the running engineer. A correction goes to a **new issue, dispatched fresh** — that is the only channel that reaches a run in flight. Where the forge supports it, ward locks this conversation to make that a road-block rather than a convention (ward#494). <!-- ward-agent-signature --> — Claude (she/her), via `ward agent`
Author
Owner

WARD-OUTCOME: done - #499 already landed on main (commit 840dd9f, closes #499, issue closed 2026-07-03); this run verified the doctor ollama probe end-to-end rather than re-implementing it.

Honest note: I picked this up as a re-dispatch and found the feature already done and pushed by an earlier run - internal/agents/ollamaprobe (ReachOnce + DoctorProbe) wired into cmd/ward/doctor.go, tests included, closes #499 on main, and my branch sitting 0/0 with origin. So rather than churn a duplicate commit, I treated this as a verification pass.

What I actually did: built clean, ran the ollamaprobe + doctor unit tests (green), then exercised the live binary across all four paths - SKIP with no endpoint env, FAIL on a dead port (and confirmed it propagates to doctor's top-level non-zero exit), PASS against a live listener, and --skip ollama. All behaved as designed. The prior run's SKIP-not-FAIL call for an unconfigured endpoint reads right to me: it keeps a plain adopter's ward doctor green while still surfacing a truly-down configured backend, with the in-container launch gate as the backstop.

Confidence is high - the mirror of the launch gate is faithful and the messages name the exact env + bypass. Nothing surprised me except the re-dispatch itself. No follow-ups worth filing.

WARD-OUTCOME: done - #499 already landed on main (commit 840dd9f, `closes #499`, issue closed 2026-07-03); this run verified the doctor ollama probe end-to-end rather than re-implementing it. Honest note: I picked this up as a re-dispatch and found the feature already done and pushed by an earlier run - `internal/agents/ollamaprobe` (`ReachOnce` + `DoctorProbe`) wired into `cmd/ward/doctor.go`, tests included, `closes #499` on `main`, and my branch sitting 0/0 with origin. So rather than churn a duplicate commit, I treated this as a verification pass. What I actually did: built clean, ran the ollamaprobe + doctor unit tests (green), then exercised the live binary across all four paths - SKIP with no endpoint env, FAIL on a dead port (and confirmed it propagates to doctor's top-level non-zero exit), PASS against a live listener, and `--skip ollama`. All behaved as designed. The prior run's SKIP-not-FAIL call for an unconfigured endpoint reads right to me: it keeps a plain adopter's `ward doctor` green while still surfacing a truly-down configured backend, with the in-container launch gate as the backstop. Confidence is high - the mirror of the launch gate is faithful and the messages name the exact env + bypass. Nothing surprised me except the re-dispatch itself. No follow-ups worth filing.
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
coilyco-flight-deck/ward#499
No description provided.