fair_price: in-game evidence never attaches, and the item is silently rewritten before lookup #268

Open
opened 2026-08-13 19:47:25 +00:00 by coilyco-ops · 0 comments
Member

🤖 Filed by Claude Code on Kai's behalf.

fair_price exists to "compare an Eco item's in-game market evidence with an advisory real-world commodity benchmark". At 5e05296 the real-world half works and the in-game half never fires — including for items with active, readable markets on the same server.

04a1ae2fix(fair_price): declare the benchmark substitution and the missing evidence — implemented substitution disclosure for the real-world axis only. The in-game axis has a second, undisclosed rewrite.

Defect 1 — "no in-game market" is false

All five valid calls returned inGameMedian: null, inGameCurrency: null, inGameTrend: null, inGameVerdict: null. Against eco.coilysiren.me:3001 (admin reachable, 528 detailed ledger rows):

fair_price(item=Wheat)  → inGameStatus: "no_in_game_market_for_Wheat"
get_market(item=Wheat)  → WheatItem, medianPrice 0.10, totalVolume 638, totalTrades 2

Wheat is the clean case: the requested name and the ledger name agree, so no mapping question arises. The market exists and the tool says it does not.

fair_price(item=Iron)   → inGameStatus: "no_in_game_market_for_IronIngot"
get_market(item=Iron)   → 13 markets, incl. IronBarItem median 0.90,
                          IronOreItem 0.10, CrushedIronOreItem 0.56

Defect 2 — undisclosed item rewrite

The in-game lookup substitutes a different item than the caller asked for, with no disclosure:

requested looked up in-game substituted substitutionReason
Iron IronIngot false null
Copper CopperIngot false null
Wheat Wheat false null

The narrative for a call that asked about Iron reads "In-cycle fair price for IronIngot trending down". The disclosure machinery already exists and fires correctly on the real-world axis — fair_price(item=CopperIngot) returns substituted: true with a well-written reason. It simply is not wired to the in-game axis.

Note that neither IronIngot nor CopperIngot appears in the ledger at all; the traded forms are IronBarItem and CopperWiringItem. So the rewrite is also mapping to names the market never uses, which is a plausible root cause for defect 1.

Working correctly, do not regress

The real-world benchmark axis is sound: correct series ids (PCOPPUSDM, PWHEAMTUSDM, DCOILWTICO, PIORECRUSDM), sane units and frequencies, correct trend arithmetic, working cache (cached: true on repeat), and clear unknown_item errors.

Lower-severity, same tool

  • server has no observable effect — no field echoes which server was used, and a cross-server call returns an identically shaped payload.
  • cycle_id has no observable effect and is not echoed; the narrative still reads "calibration not yet recorded for this cycle".
  • The unknown_item suggestion list names 5 items (Board, Copper, Iron, Oil, Wheat); the schema documents 9, and CopperIngot/Lumber resolve fine despite not being suggested.

Acceptance criteria

  • fair_price(item=Wheat) against a server with a Wheat market returns a non-null inGameMedian, inGameCurrency and inGameVerdict.
  • The in-game item mapping resolves to names that appear in the ledger, or reports honestly that no mapping exists.
  • Any in-game item rewrite sets substituted and substitutionReason, matching the real-world axis behaviour.
  • server and cycle_id are either honoured and echoed in the payload, or removed from the schema.
  • Regression test: an item with known market evidence must not return no_in_game_market_for_*.

Refs 04a1ae2.

> 🤖 Filed by Claude Code on Kai's behalf. `fair_price` exists to "compare an Eco item's in-game market evidence with an advisory real-world commodity benchmark". At `5e05296` the real-world half works and the in-game half never fires — including for items with active, readable markets on the same server. `04a1ae2` — `fix(fair_price): declare the benchmark substitution and the missing evidence` — implemented substitution disclosure for the real-world axis only. The in-game axis has a second, undisclosed rewrite. ## Defect 1 — "no in-game market" is false All five valid calls returned `inGameMedian: null`, `inGameCurrency: null`, `inGameTrend: null`, `inGameVerdict: null`. Against `eco.coilysiren.me:3001` (admin reachable, 528 detailed ledger rows): ``` fair_price(item=Wheat) → inGameStatus: "no_in_game_market_for_Wheat" get_market(item=Wheat) → WheatItem, medianPrice 0.10, totalVolume 638, totalTrades 2 ``` Wheat is the clean case: the requested name and the ledger name agree, so no mapping question arises. The market exists and the tool says it does not. ``` fair_price(item=Iron) → inGameStatus: "no_in_game_market_for_IronIngot" get_market(item=Iron) → 13 markets, incl. IronBarItem median 0.90, IronOreItem 0.10, CrushedIronOreItem 0.56 ``` ## Defect 2 — undisclosed item rewrite The in-game lookup substitutes a different item than the caller asked for, with no disclosure: | requested | looked up in-game | `substituted` | `substitutionReason` | |---|---|---|---| | `Iron` | `IronIngot` | `false` | `null` | | `Copper` | `CopperIngot` | `false` | `null` | | `Wheat` | `Wheat` | `false` | `null` | The narrative for a call that asked about `Iron` reads "In-cycle fair price for **IronIngot** trending down". The disclosure machinery already exists and fires correctly on the real-world axis — `fair_price(item=CopperIngot)` returns `substituted: true` with a well-written reason. It simply is not wired to the in-game axis. Note that neither `IronIngot` nor `CopperIngot` appears in the ledger at all; the traded forms are `IronBarItem` and `CopperWiringItem`. So the rewrite is also mapping to names the market never uses, which is a plausible root cause for defect 1. ## Working correctly, do not regress The real-world benchmark axis is sound: correct series ids (`PCOPPUSDM`, `PWHEAMTUSDM`, `DCOILWTICO`, `PIORECRUSDM`), sane units and frequencies, correct trend arithmetic, working cache (`cached: true` on repeat), and clear `unknown_item` errors. ## Lower-severity, same tool - `server` has no observable effect — no field echoes which server was used, and a cross-server call returns an identically shaped payload. - `cycle_id` has no observable effect and is not echoed; the narrative still reads "calibration not yet recorded for this cycle". - The `unknown_item` suggestion list names 5 items (`Board, Copper, Iron, Oil, Wheat`); the schema documents 9, and `CopperIngot`/`Lumber` resolve fine despite not being suggested. ## Acceptance criteria - [ ] `fair_price(item=Wheat)` against a server with a Wheat market returns a non-null `inGameMedian`, `inGameCurrency` and `inGameVerdict`. - [ ] The in-game item mapping resolves to names that appear in the ledger, or reports honestly that no mapping exists. - [ ] Any in-game item rewrite sets `substituted` and `substitutionReason`, matching the real-world axis behaviour. - [ ] `server` and `cycle_id` are either honoured and echoed in the payload, or removed from the schema. - [ ] Regression test: an item with known market evidence must not return `no_in_game_market_for_*`. Refs `04a1ae2`.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-gaming/eco-app#268
No description provided.