Found while implementing #718, out of scope there.
The defect
keel/commands/notifications.py has an opt-in registry, _ATTESTATION_FINDINGS, naming the doctor findings that should be delivered as webhook events. attest.cash_posture is registered in it.
But notify_after_cycle never calls cash_posture_findings, so that finding is not among the ones it evaluates. The registration is real; the delivery path is not. An operator who wired a webhook expecting to be told about a cash-posture problem will never be told.
Why this one matters
attest.cash_posture is not a routine warning. It is the finding that fires when:
- the account is attested MARGIN-ENABLED — a sell can fill as a short, and rail 22 vetoes live entries;
- the posture attestation has expired, same veto;
- the posture was attested with no due date at all, which rail 22 refuses rather than treating as never expiring.
All three are states where the agent has stopped being able to enter positions. That is precisely the condition a webhook exists to surface, because the symptom otherwise is silence — an agent that looks healthy and simply never trades again.
What to check when fixing
Whether the omission is the only one. The registry and the call site are two lists that must agree and there is nothing making them agree; a test that asserts every name in _ATTESTATION_FINDINGS is actually produced by something notify_after_cycle evaluates would close the class, not just this instance.
That shape of pin has already paid for itself twice in this repo (test_this_module_pins_every_route_the_server_serves, and test_every_mapped_collection_is_either_checked_or_named).
Found while implementing #718, out of scope there.
The defect
keel/commands/notifications.pyhas an opt-in registry,_ATTESTATION_FINDINGS, naming the doctor findings that should be delivered as webhook events.attest.cash_postureis registered in it.But
notify_after_cyclenever callscash_posture_findings, so that finding is not among the ones it evaluates. The registration is real; the delivery path is not. An operator who wired a webhook expecting to be told about a cash-posture problem will never be told.Why this one matters
attest.cash_postureis not a routine warning. It is the finding that fires when:All three are states where the agent has stopped being able to enter positions. That is precisely the condition a webhook exists to surface, because the symptom otherwise is silence — an agent that looks healthy and simply never trades again.
What to check when fixing
Whether the omission is the only one. The registry and the call site are two lists that must agree and there is nothing making them agree; a test that asserts every name in
_ATTESTATION_FINDINGSis actually produced by somethingnotify_after_cycleevaluates would close the class, not just this instance.That shape of pin has already paid for itself twice in this repo (
test_this_module_pins_every_route_the_server_serves, andtest_every_mapped_collection_is_either_checked_or_named).