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`) |
|
||||
| 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` |
|
||||
| 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 |
|
||||
|
||||
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`
|
||||
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)
|
||||
|
||||
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