You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Repository.get_orders() exists (keel/data/repository.py:302). Nothing in the console calls it. No web payload reads the orders table at all; the only two modules that touch it are doctor (partial-fill findings) and research (the pooled review).
So there is no surface anywhere that answers "what did keel actually buy and sell, and at what price."
What the console shows instead, and why neither is this
view
shows
Status → Open positions
what is held right now — 2 BTC dca tranches on the live book
Activity
cycles and events parsed from the log file (commands/activity.py → resolve_log_path / read_log_window)
Activity is a cycle viewer, not a transaction record. It reads the log, so a cycle that did not log, or a rotated log, shows nothing. Neither view ever reads orders.
Why this is more than a missing convenience
keel's pitch is auditability, and orders is the audit trail. Per row it holds:
confirmation — autonomous or a human's approval. "Did I approve this, or did keel place it on its own?" is the single most important question about an order on a deployment with autonomy: ON, and it is answerable nowhere in the UI
raw_response — the venue's own JSON, including the real order id
rule_id — which rule caused it
Reading any of that currently means opening SQLite by hand. On the live book that is 4 rows; on the paper book, 14.
This is the same shape as #639, #640, #641 and #642: keel knows, and does not say.
Scope
A payload over get_orders() and one console view. Specifically:
confirmation is displayed prominently, not as a trailing column. autonomous on a live BUY is the row an operator most needs to find.
fee shown as paid, not as a percentage the layer computes. A derived rate here would be the presentation layer doing arithmetic it must not do (test_console_thinness.py); if a rate is wanted, a service computes it.
Newest first. get_orders returns oldest-first by id; the view wants the opposite, and reversing in the service — not in the renderer — keeps the thinness pin honest.
Scoped like Activity is, so the view does not grow unbounded on a long-running book.
raw_response must not be rendered raw. It is venue JSON of unbounded size and it is the one field that could carry something unexpected into the page. Surface the venue order id if anything.
Constraints
keel/web/*.py is scanned by tests/commands/test_console_thinness.py — no compute in the presentation layer, Decimal arithmetic is display-only, no broker construction. The service does the work; the payload places values.
The view is read-only and must add no route reachable from tests/web/test_server.py's disjointness pin, and no keel/capabilities.py row.
Money renders through the existing money() helper — strings, presentation-ready, no float.
A console view lists orders from get_orders(), newest first, scoped.
confirmation, expected_fill, actual_fill and fee are all visible on a row.
raw_response is never rendered wholesale.
The thinness pin and the disjointness pin both stay green; no capabilities row is added.
Mutation-verified pins, per this repo's habit.
Notes
Found by reading the live console and asking where the transactions were. Related: #626 (spread is the unmeasured cost term these rows would evidence), #641 (the same two renderers kept in step), #639/#640/#642 (the same silence).
Repository.get_orders()exists (keel/data/repository.py:302). Nothing in the console calls it. No web payload reads theorderstable at all; the only two modules that touch it aredoctor(partial-fill findings) andresearch(the pooled review).So there is no surface anywhere that answers "what did keel actually buy and sell, and at what price."
What the console shows instead, and why neither is this
dcatranches on the live bookcommands/activity.py→resolve_log_path/read_log_window)Activity is a cycle viewer, not a transaction record. It reads the log, so a cycle that did not log, or a rotated log, shows nothing. Neither view ever reads
orders.Why this is more than a missing convenience
keel's pitch is auditability, and
ordersis the audit trail. Per row it holds:side,product_id,qty,status,order_type,limit_priceexpected_fillvsactual_fill— what the engine sized against vs what the venue gavefee— the number the whole cost argument rests on. The three live fills are the only direct evidence thattaker_pct: 0.012is right (measured 1.1838% effective), and keel stores nothing that measures spread, and at this deployment's clip size spread IS the cost #626 is filed because spread is the term nothing recordsconfirmation—autonomousor a human's approval. "Did I approve this, or did keel place it on its own?" is the single most important question about an order on a deployment withautonomy: ON, and it is answerable nowhere in the UIraw_response— the venue's own JSON, including the real order idrule_id— which rule caused itReading any of that currently means opening SQLite by hand. On the live book that is 4 rows; on the paper book, 14.
This is the same shape as #639, #640, #641 and #642: keel knows, and does not say.
Scope
A payload over
get_orders()and one console view. Specifically:confirmationis displayed prominently, not as a trailing column.autonomouson a live BUY is the row an operator most needs to find.expected_fillvsactual_fillside by side, with the divergence visible. That difference is realised slippage — the quantity keel stores nothing that measures spread, and at this deployment's clip size spread IS the cost #626 wants and the reason_record_observed_fill_quantityexists.feeshown as paid, not as a percentage the layer computes. A derived rate here would be the presentation layer doing arithmetic it must not do (test_console_thinness.py); if a rate is wanted, a service computes it.get_ordersreturns oldest-first byid; the view wants the opposite, and reversing in the service — not in the renderer — keeps the thinness pin honest.raw_responsemust not be rendered raw. It is venue JSON of unbounded size and it is the one field that could carry something unexpected into the page. Surface the venue order id if anything.Constraints
keel/web/*.pyis scanned bytests/commands/test_console_thinness.py— no compute in the presentation layer,Decimalarithmetic is display-only, no broker construction. The service does the work; the payload places values.tests/web/test_server.py's disjointness pin, and nokeel/capabilities.pyrow.money()helper — strings, presentation-ready, no float.keel orders-style terminal listing and the web view should not disagree, the waystatus.pyandpayload.pyare kept in step for the bracket column (Paper positions render an unactionable 'NO bracket' warning — the state paper can never leave #641).Acceptance
get_orders(), newest first, scoped.confirmation,expected_fill,actual_fillandfeeare all visible on a row.raw_responseis never rendered wholesale.Notes
Found by reading the live console and asking where the transactions were. Related: #626 (spread is the unmeasured cost term these rows would evidence), #641 (the same two renderers kept in step), #639/#640/#642 (the same silence).