Skip to content

Fix: read orders from the list that isn't stale after a partial fill - #11

Merged
piekstra merged 1 commit into
mainfrom
fix/stale-quantity-property-scoped-orders
Jul 29, 2026
Merged

Fix: read orders from the list that isn't stale after a partial fill#11
piekstra merged 1 commit into
mainfrom
fix/stale-quantity-property-scoped-orders

Conversation

@piekstra

@piekstra piekstra commented Jul 29, 2026

Copy link
Copy Markdown
Owner

The bug

After a partial fill, GET /public/v1/orders?propertyId=X keeps reporting the order's original quantity. Raw-verified on the live API — same orderId, after 1 of 3 tokens filled:

endpoint quantity
GET /orders?propertyId=X 3 ← the original size
GET /orders?all=true 2
GET /orders/{id} (authoritative) 2

Two of three agree on the remainder, so this is upstream, not our parsing — checked through the raw passthrough before concluding anything, per the LOF-8/9 lesson where two filed "API bugs" turned out to be ours.

Why it matters

The quote primitives were the only readers of that endpoint, so they sized and covered against a position that no longer exists:

  • recenter defaults size to the resting quantity, so it would re-post the original 3 rather than the remaining 2 — quietly re-growing a position a fill had just reduced, and spending capital to do it.
  • Cover for an untouched side is computed from the same number, overstating the reservation.

It also explains a concrete inconsistency seen live: account coverage reported this order as $124.50 (2 × $45.00) while quote recenter planned against x3. Two commands disagreeing about the same live order is exactly what destroys trust in a tool that spends money.

The fix

fetch_state now reads all=true and filters by property client-side — the same path account coverage and rewards eligibility already use, which is why those two were right.

Notes

Found while deploying real capital after a bid partially filled. Worth filing upstream separately; the CLI shouldn't wait on that.

Unit tests construct State directly so they're unaffected — all 92 pass, fmt and clippy -D warnings clean. Live re-verification is pending an unattended keychain prompt on this machine; the raw-API table above is what establishes the behaviour.

Figures in this description are illustrative, not account data.

Raw-verified against the live API (2026-07-29), same orderId after 1 of 3
tokens filled:

  GET /orders?propertyId=X  -> quantity 3   (the ORIGINAL size, stale)
  GET /orders?all=true      -> quantity 2   (what remains)
  GET /orders/{id}          -> quantity 2   (authoritative, agrees)

The property-scoped list keeps reporting the original quantity, so the quote
primitives — its only readers — sized and covered against a position that no
longer existed: a recenter would re-post the original 3 rather than the
remaining 2, quietly re-growing a position a fill had just reduced.

Two of three endpoints agree on the remainder, so this is upstream rather than
our parsing — confirmed through the raw passthrough before concluding anything,
per the LOF-8/9 lesson.

fetch_state now uses `all=true` filtered client-side, matching what `account
coverage` and `rewards eligibility` already do — which is why those two
disagreed with `quote recenter` about the same live order.

Claude-Session: https://claude.ai/code/session_01J7bz8aijn2Uwv1yF5rUenW
@piekstra
piekstra requested a review from piekstra-dev July 29, 2026 17:51

@piekstra-dev piekstra-dev left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated PR Review

Reviewed commit: 3ed610054eab
Profile: reviewer - Posting as: piekstra-dev

Summary

Severity Findings
blocking 0
major 0
minor 0
nits 0

0 PR discussion threads considered. 0 summarized; 0 resolved.


Completed in 32s | $0.41 | claude-sonnet-5 | cr 0.10.268
Field Value
Model claude-sonnet-5
Reviewers unavailable
Engine claude_cli · claude-sonnet-5
Reviewed by cr · piekstra-dev
Duration 32s wall · 29s compute
Cost $0.41
Tokens 12 in / 1.8k out

Per-workstream usage

Workstream Model In Out Cache read Cache create Cost Duration
orchestrator-selection claude-sonnet-5 6 1.5k 22.3k 35.4k $0.24 20s
orchestrator-rollup claude-sonnet-5 6 377 47.8k 24.9k $0.17 9s

@piekstra
piekstra merged commit 5fc30f7 into main Jul 29, 2026
2 checks passed
@piekstra
piekstra deleted the fix/stale-quantity-property-scoped-orders branch July 29, 2026 17:53
piekstra added a commit that referenced this pull request Jul 29, 2026
Ships the mutating quote family and the stale-quantity fix:

- `lofty quote recenter`  — move a resting quote safely (#9)
- `lofty quote provision` — post a fresh two-sided quote, refusing to leave you
  one-sided (#10)
- `lofty quote pull`      — stand down, `--keep-above` protecting recovery asks (#10)
- fix: read orders from the list that isn't stale after a partial fill (#11)

All three are a DRY RUN unless `--execute`, and share one implementation of the
rails: never cross the market, never exceed cover, never go under minContracts,
stay in the reward band, and touch only the sides given a price.

Exercised against a live account before release — a there-and-back recenter
restored the exact starting state, and every rail was confirmed refusing a real
attempt.

Claude-Session: https://claude.ai/code/session_01J7bz8aijn2Uwv1yF5rUenW
piekstra added a commit that referenced this pull request Jul 30, 2026
Raw-verified against the live API (2026-07-29), same orderId after 1 of 3
tokens filled:

  GET /orders?propertyId=X  -> quantity 3   (the ORIGINAL size, stale)
  GET /orders?all=true      -> quantity 2   (what remains)
  GET /orders/{id}          -> quantity 2   (authoritative, agrees)

The property-scoped list keeps reporting the original quantity, so the quote
primitives — its only readers — sized and covered against a position that no
longer existed: a recenter would re-post the original 3 rather than the
remaining 2, quietly re-growing a position a fill had just reduced.

Two of three endpoints agree on the remainder, so this is upstream rather than
our parsing — confirmed through the raw passthrough before concluding anything,
per the LOF-8/9 lesson.

fetch_state now uses `all=true` filtered client-side, matching what `account
coverage` and `rewards eligibility` already do — which is why those two
disagreed with `quote recenter` about the same live order.
piekstra added a commit that referenced this pull request Jul 30, 2026
Ships the mutating quote family and the stale-quantity fix:

- `lofty quote recenter`  — move a resting quote safely (#9)
- `lofty quote provision` — post a fresh two-sided quote, refusing to leave you
  one-sided (#10)
- `lofty quote pull`      — stand down, `--keep-above` protecting recovery asks (#10)
- fix: read orders from the list that isn't stale after a partial fill (#11)

All three are a DRY RUN unless `--execute`, and share one implementation of the
rails: never cross the market, never exceed cover, never go under minContracts,
stay in the reward band, and touch only the sides given a price.

Exercised against a live account before release — a there-and-back recenter
restored the exact starting state, and every rail was confirmed refusing a real
attempt.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants