Repository navigation
Rail 17: warn when the attestation expires before a DCA window, and retry a vetoed window (#1010) - #1013
Open
eaitbrahim wants to merge 21 commits into
Open
Rail 17: warn when the attestation expires before a DCA window, and retry a vetoed window (#1010)#1013eaitbrahim wants to merge 21 commits into
eaitbrahim wants to merge 21 commits into
Conversation
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…t signals Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…r, one buy per window Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… expiry Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…7's expiry Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…d one Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…er's row filters Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
eaitbrahim
commented
Oct 27, 2026
On a placement day the 01:20 cycle has acted on yesterday's bar, so the rail-17 cadence warning now looks at the following bar (live wrapper passes the newest counted live BUY's bar day; with no information the helper checks both bars). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
eaitbrahim
commented
Oct 27, 2026
…rapper bar day Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… bar Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Contributor
Author
This branch has not been deployed
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 #1010
Problem
Rail 17's withdrawal attestation lasts 7 days. Some live DCA rules buy every 14 days. On 2026-10-23 the attestation (made 2026-10-10 19:25Z) had been expired for six days, and rail 17 vetoed all seven DCA signals for the 2026-10-22 bar. Nothing warned beforehand. A vetoed window was also lost until the next cadence multiple, which for a 14-day rule means a month between buys. Finally, the veto text said "exits and DCA-exempt paths are unaffected", which reads as if DCA is exempt. It is not.
Approach
attestations.dca_windows_after_expiry, holds all the arithmetic: the due day is the cadence bar plus one day, and a rule is warned when the expiry comes before due + 1 day. A never-raising wrapper,live_dca_windows_after_expiry, applies it to the live DCA rules. It stays silent unless the attestation is fresh (OK or EXPIRING) and says withdrawals are enabled (R15). Three surfaces call the wrapper and never restate the arithmetic:keel withdrawals attest --enabledprints aWARNING:line per rule.keel statusprints the same line under the rail-17 line. It does this in live modes only, and the line is also in--json.keel doctoralways emitsattest.dca_cadence, as OK or WARN and never FAIL (R11).Dca.detectstays pure and reads an optional per-cycleDcaWindowLedger. Only live cycles set it (R10), from two newRepositoryreads.filledorpendinglive BUY's bar day (created_at//86400 - 1) is at or after the window start (R4, R5).promoted_atmeans no retry).context["previous_window_missed_ts"]plus a WARNINGagent.dca_window_missed(R7). It is never back-filled.agent.dca_window_ledger_failedis logged (R14).WITHDRAWAL_ATTESTATION_TTL_SECis unchanged. No config, plist or DB file is touched. There is no CHANGELOG entry (R12);docs/rails/rail-17-withdrawal-attestation.mdgains a section on this instead.Considered and rejected
created_atfalls inside it. A live order is placed the day after its bar. With that rule, a buy for a window's last bar would land in the next window and suppress that window's buy, and a cadence-1 rule would never buy again. Bar-day attribution (R4) avoids both.attestations.survey(), so the web banner shows it. That would change the notification alert-once windows and the web banners.survey()is unchanged (R9); the web console can pick this up in a follow-up.Verification
Commands run on the final tree, c55a39d:
How each criterion is met (D4):
tests/test_dca_windows_after_expiry.pyreproduces the 2026-10-10/10-17/10-23 lapse with the exact warning line, and covers the R15 silent cases.tests/execution/test_withdrawal_attestation.py::test_attest_enabled_names_each_live_dca_rule_whose_next_buy_falls_after_expirytests/commands/test_status.py::test_status_lists_each_live_dca_rule_due_after_the_attestation_expires(and the JSON and paper tests)tests/commands/test_doctor.py::test_gather_findings_wires_the_dca_cadence_checktests/strategy/test_dca_window_retry.py(8 tests)tests/test_agent.py#1010section: retry on the next fresh bar, no double buy on a same-day rerun or a later bar, missed window reported but not back-filled, rule promoted mid-window, paper-era signal, ledger-read failure, and paper cycles staying cadence-only.tests/execution/test_guards.py::test_rail17_unknown_text_does_not_imply_dca_is_exemptagent.py(5 failed, 2 regression guards passed) and for Task 5 by revertingwithdrawals.py. Coverage gaps were closed with mutation-checked tests in c55a39d: the paper-cycle guard, the non-DCA kind filter, and skipping an unbuildable row.Expected red check: the
security / dependencies(pip-audit) check is red on main for certifi PYSEC-2026-4320. PR #1012 fixes it and is still open, so expect that one check red here as well. It is unrelated to this diff.Where to look first
keel/strategy/rules/dca.pyDca.detect(theledgerbranch): the window start, the satisfied check (counted >= window_start), the retry condition (a signal at a bar day in[ws, d)), and the previous-window-missed condition.keel/agent.py_dca_window_ledger: thesincelower bound (max(now_day - 2c - 1, floor(promoted_at))).promoted_atis read from the live rules only.tests/test_agent.py::test_two_cycles_in_one_utc_day_place_one_dca_order: this is a characterization test that pinned the same-day DCA double buy. Its own text said to rewrite it, not delete it, once a dedupe existed. D2's one buy per window is that dedupe, so it now asserts one order.keel/attestations.pylive_dca_windows_after_expiry: the freshness gate uses the module's ownAttestationmodel rather than restating it.keel dca plan's busiest-day figure. Rails 3 and 14 still bound it.Commits
The plan is in
docs/superpowers/plans/2026-10-27-rail17-ttl-dca-cadence.md(two earlier commits).🤖 Generated with Claude Code