docs(market): close Gap 1 — active seller row under forSale is live-confirmed
The one claim the Fix B promotion left open: no active listing existed during
that session, so only the expired path had been exercised.
Closed with a disposable card (75 ST, res 212188, wire id 100000178 — one of
three identical copies, not in the squad) listed through the real FIFA 17 client
at 150/200 for 1h, so expiry arrives naturally. No timestamp touched.
Wire: itemState=forSale, tradeState=active, 12 atoms, prices intact, expires
3562 -> 3556 over a 6s sample (live clock), /trade/status coherent, counts
{count:1, selling:1}, coins unchanged, zero inactive rows (Fix A intact).
The decisive evidence is client-side, not ours: a read-only /proc/<pid>/mem
decode of the live trade-pile auction record returned
itemState=5(forSale)
on the very field that read -1(<unrecognised>) under listFS. Direct A/B on the
only changed field, taken from the client's own memory.
Operator confirmed the row renders under LISTED ITEMS with correct prices, a
counting-down timer, normal art, and correctly non-actionable while active.
No code change required — the promoted implementation was already correct on the
active path. Claim boundary unchanged: this proves the client DECODES the token
and says nothing about the Flash action-gate term.
This commit is contained in:
@@ -653,7 +653,7 @@ row `1000000155` (res 158023, 93 RW).
|
|||||||
| `forSale` is FIFA 17-native, value 5 | **CONFIRMED** (12-row table at `0x180229cc0`) |
|
| `forSale` is FIFA 17-native, value 5 | **CONFIRMED** (12-row table at `0x180229cc0`) |
|
||||||
| An expired row carrying `forSale` is still ACTIONABLE, and Return to Club works | **LIVE-CONFIRMED** — operator returned the card; server verified below |
|
| An expired row carrying `forSale` is still ACTIONABLE, and Return to Club works | **LIVE-CONFIRMED** — operator returned the card; server verified below |
|
||||||
| The result is durable (a fresh session reconstructs it) | **CONFIRMED server-side**: `/tradePile` `total:0`, `/tradePile/counts` all zero, card present in `/club` (1965 → 1966 items, `itemState:"free"`), zero duplicate ids, listing `cancelled` in the store and projected as `closed` (4) on `/trade/status` |
|
| The result is durable (a fresh session reconstructs it) | **CONFIRMED server-side**: `/tradePile` `total:0`, `/tradePile/counts` all zero, card present in `/club` (1965 → 1966 items, `itemState:"free"`), zero duplicate ids, listing `cancelled` in the store and projected as `closed` (4) on `/trade/status` |
|
||||||
| An ACTIVE seller row carrying `forSale` renders correctly | **NOT YET OBSERVED** — no active listing existed during the session; `/transfermarket` has always emitted `forSale` on active rows, so this is expected-safe but unverified |
|
| An ACTIVE seller row carrying `forSale` renders correctly | **LIVE-CONFIRMED** (Gap 1, 2026-08-17) — see the closure section below; the client decoded `CARD_OFFERSTATE = 5` out of its own auction record |
|
||||||
| `CARD_OFFERSTATE` is the Flash action-gate term | **STILL UNPROVEN** — this change does not test it, and the result does not bear on it |
|
| `CARD_OFFERSTATE` is the Flash action-gate term | **STILL UNPROVEN** — this change does not test it, and the result does not bear on it |
|
||||||
|
|
||||||
What this rules out: `CARD_OFFERSTATE` is not a gate term that *requires* −1. An expired
|
What this rules out: `CARD_OFFERSTATE` is not a gate term that *requires* −1. An expired
|
||||||
@@ -689,6 +689,74 @@ revert and go to the AVM1 gate work — NOT to compensate with another field cha
|
|||||||
the Flash decision tree; `STATE`, `CARD_OFFERSTATE` and `RESERVEDPRICE`/`MAX_CREDITS`
|
the Flash decision tree; `STATE`, `CARD_OFFERSTATE` and `RESERVEDPRICE`/`MAX_CREDITS`
|
||||||
remain confounded.
|
remain confounded.
|
||||||
|
|
||||||
|
### Gap 1 CLOSED — an ACTIVE seller row under `forSale` (2026-08-17)
|
||||||
|
|
||||||
|
The one thing the Fix B promotion could not test, because no active listing existed
|
||||||
|
during that session. Closed with a deliberately disposable card: a **75 ST**, resourceId
|
||||||
|
`212188`, wire id `100000178` — one of **three identical owned copies**, not in the
|
||||||
|
11-man squad, `untradeable: false`, discardValue 600. Listed **through the real FIFA 17
|
||||||
|
client** at Start 150 / Buy Now 200 for the shortest offered duration (1h), so expiry
|
||||||
|
would arrive naturally. No timestamp was touched.
|
||||||
|
|
||||||
|
Listing creation was entirely Rust-owned:
|
||||||
|
`PUT …/item` (club → pile) → `route=market-list POST item_id=100000178 listed=true
|
||||||
|
trade_id=1000000178` → `POST …/auctionhouse 200`, then the client polling
|
||||||
|
`GET …/trade/status?tradeIds=1000000178` (`requested=1 returned=1`) for the row it draws.
|
||||||
|
|
||||||
|
Wire, active row `1000000178`
|
||||||
|
(`docs/evidence/market-lifecycle-2026-08-17/gap1-active-forsale.json`):
|
||||||
|
|
||||||
|
| Field | Value |
|
||||||
|
|---|---|
|
||||||
|
| `itemState` | **`forSale`** |
|
||||||
|
| `tradeState` | `active` |
|
||||||
|
| `startingBid` / `buyNowPrice` / `currentBid` | 150 / 200 / 0 |
|
||||||
|
| `bidState` | `none` |
|
||||||
|
| `expires` | **3562 → 3556** over a 6-second sample — a live clock, not a frozen scalar |
|
||||||
|
| atom count | **12**, exactly what `0x18013e410` reads |
|
||||||
|
| `itemData` | full card, 6-entry `attributeList` |
|
||||||
|
| `/tradePile/counts` | `count 1, selling 1, offered 0, sold 0` |
|
||||||
|
| coins | 29,843,976 unchanged |
|
||||||
|
| Fix A | 0 `inactive` rows |
|
||||||
|
|
||||||
|
`/trade/status` stayed coherent with `/tradePile` throughout, agreeing on tradeId,
|
||||||
|
`active`, `forSale` and a decreasing `expires`.
|
||||||
|
|
||||||
|
**The decisive observation** is not the wire — it is what the client made of it. A
|
||||||
|
read-only `/proc/<pid>/mem` decode of the live trade-pile auction record (slide proven by
|
||||||
|
FNV control MATCH first; `O_RDONLY` + `pread` only) returned:
|
||||||
|
|
||||||
|
```text
|
||||||
|
tradeId=1000000178 state=1(active) bid=0(none) buyNow=200 start=150 cur=0 expires=3457
|
||||||
|
item CARD_ID=212188 cardType=1 tradeable=1 itemState=5(forSale) pile=0 rating=75
|
||||||
|
```
|
||||||
|
|
||||||
|
`itemState = 5(forSale)`. The same field read `-1(<unrecognised>)` under `listFS`. This is
|
||||||
|
the direct A/B on the only changed field, taken from the client's own memory rather than
|
||||||
|
from our response — the strongest form of this evidence available without AVM1 work.
|
||||||
|
`pile = 0` again, confirming pile is still never set from the wire.
|
||||||
|
|
||||||
|
Operator UI acceptance: card under **LISTED ITEMS** (not the TRANSFER LIST section), Start
|
||||||
|
150 / Buy Now 200 correct, **Time Remaining visibly counting down**, normal card art, no
|
||||||
|
malformed row, no duplicate, no premature Expired, no crash, and correctly
|
||||||
|
**non-actionable while active**. The client's container populating with exactly this row
|
||||||
|
(`rows=1`) independently corroborates that the Transfer List screen bound and drew it.
|
||||||
|
|
||||||
|
**No code change was required** — the promoted implementation was already correct on the
|
||||||
|
active path, which is what the test was designed to find out.
|
||||||
|
|
||||||
|
Two process notes worth keeping. First, an early capture reported "countdown NO"; that was
|
||||||
|
a bug in the capture script (it re-read a hardcoded copy id rather than the row it had
|
||||||
|
resolved), not a server fault — the same run's `/trade/status` already showed a lower
|
||||||
|
`expires` than `/tradePile`. Verify the instrument before believing a negative. Second,
|
||||||
|
the client's auction-record containers read **0 rows** while the operator was on any other
|
||||||
|
screen; they populate only while the Transfer List is bound. An empty container is not
|
||||||
|
evidence of an empty pile.
|
||||||
|
|
||||||
|
**Claim boundary unchanged:** this proves the client *decodes* the token. It says nothing
|
||||||
|
about the Flash action-gate term.
|
||||||
|
|
||||||
|
|
||||||
### Proving the gate (not yet done)
|
### Proving the gate (not yet done)
|
||||||
|
|
||||||
Disassemble the AVM1 action buffer of `tradepile.isInActiveAuction` (and
|
Disassemble the AVM1 action buffer of `tradepile.isInActiveAuction` (and
|
||||||
|
|||||||
@@ -0,0 +1,173 @@
|
|||||||
|
{
|
||||||
|
"gap": 1,
|
||||||
|
"test": "ACTIVE seller row under itemState=forSale",
|
||||||
|
"date": "2026-08-17",
|
||||||
|
"disposable_card": {
|
||||||
|
"wire_item_id": 100000178,
|
||||||
|
"resourceId": 212188,
|
||||||
|
"rating": 75,
|
||||||
|
"preferredPosition": "ST",
|
||||||
|
"copies_owned": 3,
|
||||||
|
"discardValue": 600,
|
||||||
|
"in_active_squad": false,
|
||||||
|
"untradeable": false
|
||||||
|
},
|
||||||
|
"pre_state": {
|
||||||
|
"club_items": 1966,
|
||||||
|
"coins": 29843976,
|
||||||
|
"tradePile_rows": 0,
|
||||||
|
"tradePile_counts": {
|
||||||
|
"count": 0,
|
||||||
|
"maxAuctionsAllowed": 100,
|
||||||
|
"offered": 0,
|
||||||
|
"selling": 0,
|
||||||
|
"sold": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"listing_creation_route_log": "utas-host owner=RUST route=market-list POST item_id=100000178 listed=true trade_id=1000000178",
|
||||||
|
"client_flow_observed_rust_owned": [
|
||||||
|
"PUT /ut/game/fifa17/item (club -> trade pile move)",
|
||||||
|
"POST /ut/game/fifa17/auctionhouse (ISStart) -> 200",
|
||||||
|
"GET /ut/game/fifa17/tradePile (repeated)",
|
||||||
|
"GET /ut/game/fifa17/trade/status?tradeIds=1000000178 -> requested=1 returned=1 (repeated poll)",
|
||||||
|
"GET /ut/game/fifa17/tradePile/counts"
|
||||||
|
],
|
||||||
|
"wire_active_row": {
|
||||||
|
"tradeId": 1000000178,
|
||||||
|
"tradeState": "active",
|
||||||
|
"itemState": "forSale",
|
||||||
|
"startingBid": 150,
|
||||||
|
"buyNowPrice": 200,
|
||||||
|
"currentBid": 0,
|
||||||
|
"bidState": "none",
|
||||||
|
"sellerName": "CAGE",
|
||||||
|
"sellerEstablished": 1,
|
||||||
|
"watched": false,
|
||||||
|
"coinsProcessed": 0,
|
||||||
|
"atom_count": 12,
|
||||||
|
"itemData_attributeList_entries": 6
|
||||||
|
},
|
||||||
|
"countdown_sample": {
|
||||||
|
"expires": [
|
||||||
|
3562,
|
||||||
|
3556
|
||||||
|
],
|
||||||
|
"delta_secs": 6,
|
||||||
|
"live": true
|
||||||
|
},
|
||||||
|
"trade_status_coherent_while_running": true,
|
||||||
|
"trade_status_rows": [
|
||||||
|
{
|
||||||
|
"bidState": "none",
|
||||||
|
"buyNowPrice": 200,
|
||||||
|
"coinsProcessed": 0,
|
||||||
|
"currentBid": 0,
|
||||||
|
"expires": 3556,
|
||||||
|
"itemData": {
|
||||||
|
"assetId": 212188,
|
||||||
|
"attributeList": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"value": 90
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"value": 70
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 2,
|
||||||
|
"value": 64
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 3,
|
||||||
|
"value": 78
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 4,
|
||||||
|
"value": 24
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 5,
|
||||||
|
"value": 62
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"cardassetid": 212188,
|
||||||
|
"cardsubtypeid": 0,
|
||||||
|
"contract": 7,
|
||||||
|
"definitionId": 212188,
|
||||||
|
"discardValue": 600,
|
||||||
|
"fitness": 99,
|
||||||
|
"id": 100000178,
|
||||||
|
"itemState": "forSale",
|
||||||
|
"itemType": "player",
|
||||||
|
"leagueId": 19,
|
||||||
|
"nation": 21,
|
||||||
|
"owners": 1,
|
||||||
|
"playStyle": 250,
|
||||||
|
"preferredPosition": "ST",
|
||||||
|
"rareflag": 1,
|
||||||
|
"rating": 75,
|
||||||
|
"resourceId": 212188,
|
||||||
|
"teamid": 112172,
|
||||||
|
"untradeable": false
|
||||||
|
},
|
||||||
|
"sellerEstablished": 1,
|
||||||
|
"sellerName": "CAGE",
|
||||||
|
"startingBid": 150,
|
||||||
|
"tradeId": 1000000178,
|
||||||
|
"tradeState": "active",
|
||||||
|
"watched": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tradePile_counts_while_active": {
|
||||||
|
"count": 1,
|
||||||
|
"maxAuctionsAllowed": 100,
|
||||||
|
"offered": 0,
|
||||||
|
"selling": 1,
|
||||||
|
"sold": 0
|
||||||
|
},
|
||||||
|
"coins_unchanged": true,
|
||||||
|
"fix_a_inactive_rows": 0,
|
||||||
|
"CARD_OFFERSTATE_live_decode": {
|
||||||
|
"observed": true,
|
||||||
|
"method": "read-only /proc/<pid>/mem via fifa17-recon-derived auction_record_probe.py; slide proven by FNV control MATCH before any other read; O_RDONLY + pread only",
|
||||||
|
"client_pid": 29670,
|
||||||
|
"container": "model->vt[0x120] (trade pile), rows=1, +0x60 override=1",
|
||||||
|
"record": {
|
||||||
|
"tradeId": 1000000178,
|
||||||
|
"STATE_tradeState": "1(active)",
|
||||||
|
"YOURBID_bidState": "0(none)",
|
||||||
|
"MAX_CREDITS_buyNowPrice": 200,
|
||||||
|
"RESERVEDPRICE_startingBid": 150,
|
||||||
|
"currentBid": 0,
|
||||||
|
"expires": 3457,
|
||||||
|
"coinsProcessed": 0,
|
||||||
|
"IS_GLOW_flagB": 0,
|
||||||
|
"INBOX_flagA": 0,
|
||||||
|
"IS_WATCHED": 0
|
||||||
|
},
|
||||||
|
"item": {
|
||||||
|
"CARD_ID": 212188,
|
||||||
|
"CARD_TYPE": 1,
|
||||||
|
"tradeable": 1,
|
||||||
|
"rating": 75,
|
||||||
|
"CARD_OFFERSTATE_itemState": "5(forSale)",
|
||||||
|
"pile": 0
|
||||||
|
},
|
||||||
|
"ab_significance": "This is the direct A/B on the only changed field. Baseline `listFS` decoded to -1(<unrecognised>) in the client's own record; candidate `forSale` decodes to 5. Every other field in the record is unchanged in kind.",
|
||||||
|
"claim_boundary": "Proves the CLIENT DECODES the token correctly. Says nothing about the Flash action-gate term."
|
||||||
|
},
|
||||||
|
"ui_acceptance": {
|
||||||
|
"operator_report": "looks right",
|
||||||
|
"confirmed": [
|
||||||
|
"card renders under LISTED ITEMS (not the TRANSFER LIST section)",
|
||||||
|
"Start Price 150 and Buy Now 200 displayed correctly, Current Bid as expected",
|
||||||
|
"Time Remaining visibly counting down",
|
||||||
|
"card art renders normally; no malformed row, no duplicate, no premature Expired, no crash",
|
||||||
|
"row correctly non-actionable while active (established FIFA 17 behaviour, not a fault)"
|
||||||
|
],
|
||||||
|
"corroboration": "the client's trade-pile container populated with exactly this row (rows=1), so the Transfer List screen bound and drew it"
|
||||||
|
},
|
||||||
|
"verdict": "GAP 1 CLOSED \u2014 LIVE-CONFIRMED: an active seller auction with itemState=forSale renders correctly and is decoded by the client as CARD_OFFERSTATE=5",
|
||||||
|
"code_change_required": false
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user