Issue 1952 (milestone L4 of design 47, ADR 0564 §4), approved by the operator on 2026-10-31 about 22:00.
Why: the watchman confirmed a module unhealthy only after two writes of its have in a row. A have that turns failed once and then stays the same is written once, so no finding was ever written; live, module.fail2ban.novox.unhealthy (the controller's) had no counterpart in the condition keeper's compare.
The change: a failed have starts a one-minute confirm signal and the warning is written if the have still says failed when it fires (ADR 0564 §4 names two statements in a row and no bound); the four-hour urgent signal starts beside it. A finding read back at start and replayed by a failed have is kept as it was: it is not confirmed again, a warning's urgent signal runs from its own Since, and an urgent finding stays urgent with no signal restarted.
Quick fix vs thorough fix: confirming by time is the thorough form here (no count of writes anywhere), in the one module that confirms.
Tests: WM3 rewritten (a steady failed have gets its finding after the bound; one that recovers within it gets none; the urgent signal after 4 h), a restart row, and two rows for a finding read back at start (warning and urgent), each failing on the old code. gofmt, go vet (with and without -tags integration) and go test pass. No new Test functions.
Issue 1952 (milestone L4 of design 47, ADR 0564 §4), approved by the operator on 2026-10-31 about 22:00.
**Why:** the watchman confirmed a module unhealthy only after two writes of its have in a row. A have that turns failed once and then stays the same is written once, so no finding was ever written; live, `module.fail2ban.novox.unhealthy` (the controller's) had no counterpart in the condition keeper's compare.
**The change:** a failed have starts a one-minute confirm signal and the warning is written if the have still says failed when it fires (ADR 0564 §4 names two statements in a row and no bound); the four-hour urgent signal starts beside it. A finding read back at start and replayed by a failed have is kept as it was: it is not confirmed again, a warning's urgent signal runs from its own Since, and an urgent finding stays urgent with no signal restarted.
**Quick fix vs thorough fix:** confirming by time is the thorough form here (no count of writes anywhere), in the one module that confirms.
**Tests:** WM3 rewritten (a steady failed have gets its finding after the bound; one that recovers within it gets none; the urgent signal after 4 h), a restart row, and two rows for a finding read back at start (warning and urgent), each failing on the old code. gofmt, go vet (with and without -tags integration) and go test pass. No new Test functions.
Reviewed-by: rev-l4@shanks at 8a658a4290c965cc09ecb2e5322020da27f62234
https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
A have that turned failed once and stayed unchanged was written once, so the old count of two writes never fired and the
finding was never written (fail2ban on novox). Confirm by time, with a signal, also at a restart.
Quick: raise the count to one write (loses the confirmation). Thorough, chosen: confirm by a time bound, as ADR 0564 s4's
signals are keys that expire, so no write count is needed.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
At a restart a standing finding is observed again by the replayed failed have: kept, not confirmed again, and its urgent
signal runs on from the finding's Since; an urgent one stays urgent with no signal restarted.
Quick: skip the confirm when a finding stands. Thorough, chosen: the same, plus urgency read from the finding itself.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
Deliverynovox/mesh-delivery@8a658a4290c9 — merged since 2026-10-31T21:34:08Z
Source — source.main moved to novox/mesh-delivery@91128d4f0a. Whether it reached the machines is mesh-delivery-view's, derived from source.main, the wants and the haves.
Transitions
2026-10-31 21:02 (new) → proposed (announced): novox/mesh-delivery#127's head announced
2026-10-31 21:03 proposed → ready (accepted): a verdict names this commit and the trunk's head as its trunk commit, the gate passed or warned, and the repository's own check did not fail; or the check gates no merge (check-gates-merge false)
2026-10-31 21:34 ready → merged (merged): on the trunk its modules follow: merged there
The commit's note under refs/notes/mesh-plan keeps every transition of this change up to its merge: git log --notes=mesh-plan.
<!-- mesh-delivery:view -->
**Delivery** `novox/mesh-delivery@8a658a4290c9` — **merged** since 2026-10-31T21:34:08Z
**Source** — source.main moved to novox/mesh-delivery@91128d4f0af6. Whether it reached the machines is `mesh-delivery-view`'s, derived from `source.main`, the wants and the haves.
**Transitions**
- 2026-10-31 21:02 (new) → proposed (announced): novox/mesh-delivery#127's head announced
- 2026-10-31 21:03 proposed → ready (accepted): a verdict names this commit and the trunk's head as its trunk commit, the gate passed or warned, and the repository's own check did not fail; or the check gates no merge (check-gates-merge false)
- 2026-10-31 21:34 ready → merged (merged): on the trunk its modules follow: merged there
The commit's note under `refs/notes/mesh-plan` keeps every transition of this change up to its merge: `git log --notes=mesh-plan`.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Issue 1952 (milestone L4 of design 47, ADR 0564 §4), approved by the operator on 2026-10-31 about 22:00.
Why: the watchman confirmed a module unhealthy only after two writes of its have in a row. A have that turns failed once and then stays the same is written once, so no finding was ever written; live,
module.fail2ban.novox.unhealthy(the controller's) had no counterpart in the condition keeper's compare.The change: a failed have starts a one-minute confirm signal and the warning is written if the have still says failed when it fires (ADR 0564 §4 names two statements in a row and no bound); the four-hour urgent signal starts beside it. A finding read back at start and replayed by a failed have is kept as it was: it is not confirmed again, a warning's urgent signal runs from its own Since, and an urgent finding stays urgent with no signal restarted.
Quick fix vs thorough fix: confirming by time is the thorough form here (no count of writes anywhere), in the one module that confirms.
Tests: WM3 rewritten (a steady failed have gets its finding after the bound; one that recovers within it gets none; the urgent signal after 4 h), a restart row, and two rows for a finding read back at start (warning and urgent), each failing on the old code. gofmt, go vet (with and without -tags integration) and go test pass. No new Test functions.
Reviewed-by: rev-l4@shanks at
8a658a4290https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
Delivery
novox/mesh-delivery@8a658a4290c9— merged since 2026-10-31T21:34:08ZSource — source.main moved to novox/mesh-delivery@91128d4f0a. Whether it reached the machines is
mesh-delivery-view's, derived fromsource.main, the wants and the haves.Transitions
The commit's note under
refs/notes/mesh-plankeeps every transition of this change up to its merge:git log --notes=mesh-plan.