fix(engine): close #731 and #732 — pin two ON CONFLICT windows, and deliver the finding nobody could receive - #745
Merged
Conversation
…eliver the finding nobody could receive Both were found while implementing #718 and left alone to keep that PR to its scope. Both sit under rail 22. #731: TWO UPSERT CLAUSES WERE CORRECT AND UNTESTED `broker_subscriptions` and `venue_cash_postures` both carry `attest_due_ts` in an `INSERT ... ON CONFLICT DO UPDATE SET`, both set it, and deleting either line left the whole suite green -- the same hole #718 closed for the asset and instrument tables and left open here. `venue_cash_postures.attest_due_ts` is RAIL 22's INPUT. A re-attestation that carried the old window forward would keep an expired posture reading as current, and the rail would stop vetoing when it should: the failure direction that costs money rather than opportunity. On `broker_subscriptions` the column is NOT NULL, so the same slip is even less visible -- the window can never read as absent, only as stale. Mutating every column of both clauses found TWO MORE the issue did not name. `attested_posture` is the column rail 22 actually reads: an operator who moves off margin and re-attests, whose re-attestation silently kept `MARGIN_ENABLED`, would go on being vetoed by a record saying the opposite of what they stated. And the refutation columns had the same hole the method's own docstring already states for `credential_fingerprint` -- "a writer that could not clear it would let a stale fingerprint outlive the record it described" -- so a posture the venue refuted and the operator then fixed would read as refuted forever. Every column in both clauses is now pinned. #732: A REGISTERED FINDING THAT NOTHING COULD DELIVER `attest.cash_posture` was in `_ATTESTATION_FINDINGS`, the opt-in registry of findings a webhook receives, and `notify_after_cycle` never called `cash_posture_findings`. The registration was real; the delivery path was not. That finding fires when the account is attested MARGIN-ENABLED, when the posture attestation has expired, or when it was attested with no due date at all -- three states in which rail 22 has stopped letting the agent enter positions. The symptom otherwise is SILENCE: an agent that looks healthy and simply never trades again. It is exactly what a webhook is for. AND THE `break` WAS THE SAME BUG ONE LAYER DOWN `events_from_state` emitted one attestation event per CYCLE, with a comment saying "the finding list carries one rail-17 verdict" -- true when the registry held rail 17 alone. With rail 22 in it, that break makes a cash-posture problem invisible whenever a withdrawals problem also exists. One event per finding NAME now. THE PIN CLOSES THE CLASS, NOT THE INSTANCE A test comparing the registry against a list of gatherer names would be a third list to drift. Instead it drives the REAL `notify_after_cycle` against a book where every registered finding is unhealthy at once, and asserts each one ARRIVES -- so a registration with no gatherer fails here rather than in production quiet. One behaviour change worth naming: a deployment that has never attested a cash posture now notifies. `cash_posture_findings(None)` is a FAIL -- "cash posture never attested" -- and rail 22 vetoes on it, so the agent cannot enter and until now had no way to say so. That is the standing case #732 is really about, and it is why an existing test's `sent == 1` became `sent == 2`: the default double carries no posture, which was never a fixture detail. Nine mutants killed: both windows dropped, a neighbour dropped from each clause, `refuted_ts`, `refuted_reason`, `credential_fingerprint`, `state` and `attested_posture` dropped from the posture clause, the cash-posture gatherer removed, the break restored, and a healthy posture notifying anyway. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KZZxmspQXe5qJ9FAsG13s6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #731. Closes #732.
Both were found while implementing #718 and left alone to keep that PR to its scope. Both sit under rail 22.
#731 — two upsert clauses, correct and untested
broker_subscriptionsandvenue_cash_posturesboth carryattest_due_tsin anINSERT … ON CONFLICT DO UPDATE SET, both set it, and deleting either line left the whole suite green — the same hole #718 closed for the asset and instrument tables and left open here.venue_cash_postures.attest_due_tsis rail 22's input. A re-attestation carrying the old window forward would keep an expired posture reading as current, and the rail would stop vetoing when it should — the failure direction that costs money rather than opportunity.Mutating every column of both clauses found two more the issue didn't name:
attested_postureis the column rail 22 actually reads. An operator who moves off margin and re-attests, whose re-attestation silently keptMARGIN_ENABLED, would go on being vetoed by a record saying the opposite of what they stated.credential_fingerprint— "a writer that could not clear it would let a stale fingerprint outlive the record it described" — so a posture the venue refuted and the operator then fixed would read as refuted forever.Every column in both clauses is now pinned.
#732 — a registered finding nothing could deliver
attest.cash_posturewas in_ATTESTATION_FINDINGS, andnotify_after_cyclenever calledcash_posture_findings. The registration was real; the delivery path was not.It fires when the account is attested margin-enabled, when the posture attestation has expired, or when it was attested with no due date at all — three states where rail 22 has stopped letting the agent enter positions. The symptom otherwise is silence: an agent that looks healthy and never trades again.
The
breakwas the same bug one layer down.events_from_stateemitted one attestation event per cycle, commented "the finding list carries one rail-17 verdict" — true when the registry held rail 17 alone. With rail 22 in it, that break makes a cash-posture problem invisible whenever a withdrawals problem also exists. One event per finding name now.The pin closes the class. A test comparing the registry against a list of gatherer names would be a third list to drift. Instead it drives the real
notify_after_cycleagainst a book where every registered finding is unhealthy at once and asserts each one arrives — so a registration with no gatherer fails there rather than in production quiet.One behaviour change worth naming
A deployment that has never attested a cash posture now notifies.
cash_posture_findings(None)is aFAIL— "cash posture never attested" — and rail 22 vetoes on it, so the agent cannot enter and until now had no way to say so. That's the standing case #732 is really about, and it's why an existing test'ssent == 1becamesent == 2: the default double carries no posture, which was never a fixture detail.Gates
E501is pre-existing indocs/experiments/)refuted_ts,refuted_reason,credential_fingerprint,stateandattested_posturedropped from the posture clause · the cash-posture gatherer removed · the break restored · a healthy posture notifying anyway🤖 Generated with Claude Code
https://claude.ai/code/session_01KZZxmspQXe5qJ9FAsG13s6