Files
OpenFUT/docs/evidence/sold-ab-2026-08-18/A_highest.json
T
funman300 aa5fb2cc40 test(market): make the sold A/B one-field attributable, add classified differential
The brief's gate: if the harness varies bidState AND coinsProcessed together, the
client's reaction is attributable to neither. The env knobs were already orthogonal
(--variant and --coins-processed are independent, cp defaults to 0), but
sold-wire-check.py was flipping BOTH for variant B as a convenience, which is exactly
the contaminated A/B the brief forbids. Fixed: the primary pair now holds
coinsProcessed at 0 and asserts the differing-field set is exactly ['bidState'].

New scripts/sold-ab-differential.py is the pre-live gate. It settles ONE synthetic
sale, then re-reads every seller-facing surface under each variant by restarting only
the host (same Core, same DBs, same sale), and diffs with explicit classification --
MISSING / EXTRA / TYPE_MISMATCH / VALUE_MISMATCH -- rather than a boolean "equal?".
Two orthogonal pairs:

  PRIMARY     bidState highest vs buyNow, coinsProcessed held at 0
  ORTHOGONAL  coinsProcessed 0 vs 1,      bidState held at highest

Result, 36/36: the ONLY finding on /tradePile is
VALUE_MISMATCH auctionInfo[0].bidState A='highest' B='buyNow'; /trade/status differs
in exactly the same one path; counts are byte-identical. The orthogonal pair's only
finding is auctionInfo[0].coinsProcessed. C_cp0's sha256 equals A_highest's, so the
capture is reproducible rather than merely consistent.

Counts states the live run has to interpret, measured not guessed:
  S1  0 active + 1 sold -> count 0, selling 0, sold 1
  S2  1 active + 1 sold -> count 1 (active mode) vs 2 (membership mode)
That divergence IS the open question for the client; production is unchanged.

scripts/sold-client-ports.py switches ONLY the two client Blaze port lines, and is
built so restoration cannot depend on memory: it records the production values to a
sidecar on the client BEFORE the first edit and restore reads that sidecar, refusing
if it is absent. It rewrites only known keys (a missing key is an error, never a
silent append), re-reads and verifies afterwards, and REFUSES to edit while a FIFA
client is running because the hook reads the file at connect time.

Phase 0 evidence under docs/evidence/sold-ab-2026-08-18/ with a sha256 per surface,
one file per variant so A can never overwrite B.

Live client A/B NOT run: a production FIFA session is currently live on 10.10.0.105
(pid 32188), and live-session mutual exclusion applies. The client config was NOT
touched -- the switcher's guard refused, as designed.

Production untouched: prod-host pid 3631953, coins 29,843,976, /tradePile 0,
counts.sold 0, club 1966; nothing under /home/alex/openfut-promotion/state/ opened.
2026-08-18 02:22:12 +00:00

114 lines
3.1 KiB
JSON

{
"env": {
"OPENFUT_FIFA17_SOLD_COINS_PROCESSED": "0",
"OPENFUT_FIFA17_SOLD_EXPERIMENT": "highest"
},
"surfaces": {
"counts": {
"body": {
"count": 0,
"maxAuctionsAllowed": 100,
"offered": 0,
"selling": 0,
"sold": 1
},
"sha256": "766b1fcc4ca47442e6f570c81583840b6ae8df9cbeae52473b3c100ca881e206",
"status": 200
},
"tradePile": {
"body": {
"auctionInfo": [
{
"bidState": "highest",
"buyNowPrice": 150,
"coinsProcessed": 0,
"currentBid": 150,
"expires": 0,
"itemData": {
"assetId": 212188,
"id": 100000178,
"itemState": "forSale",
"preferredPosition": "ST",
"rating": 75,
"resourceId": 212188,
"untradeable": false
},
"sellerEstablished": 1,
"sellerName": "CAGE",
"startingBid": 150,
"tradeId": 900500150,
"tradeState": "closed",
"watched": false
}
],
"credits": 1143,
"duplicateItemIdList": [],
"total": 1
},
"sha256": "caecc67a615ddd0f209b36c7c8ea6a04e0002552d9a42b8eeca20df84feedf3c",
"status": 200
},
"trade_status_filtered": {
"body": {
"auctionInfo": [
{
"bidState": "highest",
"buyNowPrice": 150,
"coinsProcessed": 0,
"currentBid": 150,
"expires": 0,
"itemData": {
"assetId": 212188,
"id": 100000178,
"itemState": "forSale",
"preferredPosition": "ST",
"rating": 75,
"resourceId": 212188,
"untradeable": false
},
"sellerEstablished": 1,
"sellerName": "CAGE",
"startingBid": 150,
"tradeId": 900500150,
"tradeState": "closed",
"watched": false
}
],
"credits": 1143
},
"sha256": "0107bf70809cce10fa5fa0f7f4e196f7ffdd6def1b9f63407eeffc7e66f35855",
"status": 200
},
"trade_status_unfiltered": {
"body": {
"auctionInfo": [
{
"bidState": "highest",
"buyNowPrice": 150,
"coinsProcessed": 0,
"currentBid": 150,
"expires": 0,
"itemData": {
"assetId": 212188,
"id": 100000178,
"itemState": "forSale",
"preferredPosition": "ST",
"rating": 75,
"resourceId": 212188,
"untradeable": false
},
"sellerEstablished": 1,
"sellerName": "CAGE",
"startingBid": 150,
"tradeId": 900500150,
"tradeState": "closed",
"watched": false
}
],
"credits": 1143
},
"sha256": "0107bf70809cce10fa5fa0f7f4e196f7ffdd6def1b9f63407eeffc7e66f35855",
"status": 200
}
}
}