Repository navigation
console: Holdings per rule row; DCA tranches read "no stop by design" (#960, #961) - #972
Merged
Merged
Conversation
) `status.bracket_verdict` is the one #641 judgement. `keel status`, Pulse's roll-call and missing-bracket count, and the Holdings bracket cell all read it. A non-paper tranche whose kind declares it never brackets (`Rule.places_bracket` False -- `Dca`) and that recorded no real stop is NEUTRAL "no stop by design". Zero is the `Dca.detect` stop sentinel, which every attributed live DCA tranche carries, so it is not a stop. Every other non-paper tranche without a bracket stays WARN, including the PAXG tranche (#811). Paper is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`HoldingsReport.groups` replaces `rules` and groups by `positions.rule_id`, not by kind. Every DCA rule is named `dca`, so the live book's DCA rules used to share one table across products. Each group is headed by its kind, product and rule id (`dca · BTC-USD · rule 6`): the id is the only field that tells two same-product DCA rules apart, and it is the handle `keel rules` takes. Unattributed tranches come last, one table per kind. Group keys are built only from an integer or an ordinal (`rule-6`, `unattributed-1`), so the element ids built from them (`h-hold-<key>`) are unique and safe. Each row carries its `group`, and the client filters on that key and prints the service's heading. The Holdings stop column reads `status.recorded_stop`. The DCA `stop=0` sentinel is absent there, not "$0.00", and on its own it no longer draws the column. This is the same reading the bracket verdict takes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
recorded_stop reads <= 0 as no stop. A negative stop on DCA is by design; on any other kind it stays BRACKET_MISSING. Neither side was pinned, so flipping > 0 to != 0 survived mutation. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…erdict names (F1) Applying recorded_stop everywhere changed paper: a paper DCA tranche with stop 0 showed a dash in the stop cell beside 'paper stop $0.00' in the bracket cell, and the stop column could vanish. status.shown_stop(initial_stop, mode) now makes that one decision (paper: raw, as on origin/main; otherwise recorded_stop); holdings.py and payload.py read it and neither compares the mode. recorded_stop's docstring now says what is true. Also notes in _kind_never_brackets that rule_kind is rule.name, which is always the kind (H2). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…se no longer equates unbracketed with no stop (H5) A page-wide guard drew an all-dash stop column in every DCA table whenever the PAXG turtle tranche (the only one with a stop) sat elsewhere on the page. Each group now carries its own stop_rows_present list (computed in the service from shown_stop), and holdingsSection reads it inside the group loop. The page-wide stop_rows_present and HoldingsReport.stop_row_ids had no other reader and are gone. The structural test pins the guard inside the loop, read from group., one guard serving both splices. Runbook and header comments follow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ayload groups (R2-F1) Two mutants survived round 2: dropping stop_row_ids from rule-attributed groups, and giving every payload group the first group's list. Either would strip the stop column from a real turtle table while the suite stayed green. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Paper DCA still shows 'paper stop $0.00' with a stop column, and a live DCA tranche that recorded a real stop reads NO bracket; the runbook and render.js prose said DCA never has a stop. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ence does (R3) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…name param The #961 safety argument (a non-DCA rule never carries rule_name dca) rested on behaviour no test locked. Pin both halves: describe()[params] carries no name for any registered kind, and add_rule_row refuses name in --params with no row. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-F1) The docstring said a name in --params was dropped from the stored row; it is refused (dropped-param refusal, or rsi_meanrev's constructor). Say what the code does and cite the pinning tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
Author
Gatekeeper: READY for the owner to merge (head c686c35)I ran 5 review/fix rounds with a fresh reviewer each round. Findings per round: 2, 2, 1, 1, 0. All of them are fixed, and none is open. Changes in the review loop
Safety
Evidence on c686c35
Filed outside this PR: #973 (keel positions measures DCA stop distance against the 0 sentinel), #974 ( 🤖 Generated with Claude Code |
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 #960
Closes #961
What changes
#961: one bracket verdict, read by three surfaces.
status.bracket_verdictis now the only Paper positions render an unactionable 'NO bracket' warning — the state paper can never leave #641 judgement. These all read it:keel status(_bracket_display);payload._bracket_field);pulse.build_pulse).Rule.places_bracket = False, a class attribute declared once, onDca;initial_stop = 0, which is theDca.detectstop=0sentinel. The live ledger's tranches 4–6 show this. A check ofinitial_stop is Nonealone would have left all of them warning.status.recorded_stoptreats a stop ≤ 0 as no stop.#960: Holdings draws one table per rule row.
HoldingsReport.groupsreplacesrules. It is keyed onpositions.rule_id, and each group's heading iskind · product · rule <id>(for exampledca · BTC-USD · rule 6).dca · unattributed,turtle_breakout · unattributed).rule-6,unattributed-1). That makes theh-hold-<key>element ids unique and free of whitespace, which settles the earlier held H8.group. The client filters onrow.group === group.keyand prints the service's heading.Rulings
keel rulestakes.places_bracketis a new class attribute;accumulatesis not reused.test_dca_is_the_one_kind_that_never_bracketsforces that to be a deliberate change.Verification
ruff check keel tests packages,ruff format --check .and baremypy: all clean.node --checkpasses on every static JS file and on sw.js.pytest: 8286 passed, 3 skipped.Dcawithout the flag, Pulse counting!= BRACKETED, the heading without the id, unattributed groups first, grouping by name, the client filtering byrule_name, the client heading taken from the key, the stop cell showing the sentinel, the stop column drawn on the sentinel, the no-stop cell set to warn, and the CLI wording.keel statuswas run against a scratch confirm-mode copy of the paper config and DB. The DCA lines read(no stop by design). The PAXG-style turtle tranche (with a stop) and the SOL turtle tranche (without one) read(NO bracket). In paper mode the output was the same as before.keel serveon port 8811 over that scratch copy.rule-21,rule-101,rule-102,rule-103,unattributed-1(dca),unattributed-2(turtle).<span class="warn">NO bracket</span>.unbracketed_count2 (warn), with 4 DCA tranches neutral.🤖 Generated with Claude Code