Item surfaces overhaul: actionable per-item page (reverse-chrono feed, compress repeats, pagination, search, filters) + directory sort/hide-untraded #92
Labels
No labels
burndown-2026-06
burndown-2026-08
headless
autonomy
async-consult
autonomy
epic
autonomy
headless
autonomy
live-collab
c#
priority
P0
priority
P1
priority
P2
priority
P3
priority
P4
role/advocate
role/director
role/exec
role/frontend
role/gamedev
role/human
role/platform
role/qa
role/science
role/sysadmin
state
ambient
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
coilyco-gaming/eco-app#92
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Overhaul both item surfaces so they answer a holder's or buyer's actual questions. Filed from a batch of eco-app feedback Kai handed the director surface. Absorbs and supersedes #85 (item pages miss info they pivot on elsewhere).
Per-item page (
frontend/src/pages/Item.tsx,frontend/src/lib/itemsApi.ts,src/eco_mcp_app/items.py)The page today is two separate "Trades" and "Made" lists, each
day {Math.floor(day)}, capped at 200 rows, no search, no pagination, no top-level summary beyond a pill. Kai wants it to revolve around actionable, reverse-chronological info that someone holding or wanting the item cares about./tradeuses (logistics.py,stores.py,market.py).time(seconds) andday(float) per row, so compute "X minutes / hours / days ago" against the world clock (the/infosnapshot carriesTimeSinceStart). Every place that shows a day must also show the hour, never a bare floored day.MAX_PIVOT_TRADES/MAX_PIVOT_CRAFTS= 500 each. Raise or page the backend so pagination is real, not just slicing 200 client-side.?q=on/items.?item=StumpLatrineItemlists only 2 people who each "made 30+". Investigate whether this is real repeated crafting (which the compress-repeats change will make legible) or a parse/dedupe defect in_fetch_craft_events/parse_craft_events(row capMAX_ROWS_PER_ACTION, the batched re-stream, or double-counting acrossCRAFT_ACTION_TYPES). Name the finding in the PR.Items directory (
frontend/src/pages/Items.tsx,build_item_indexinitems.py)tradeCount === 0are hidden by default, with a toggle to show them. Most of the directory is craft-only noise for someone shopping.Done when
Both pages carry the new structure, the merged feed compresses repeats and reads in relative time with hours, pagination + search + structured filters work on the item page, the directory sorts and hides-untraded-by-default, and the StumpLatrine finding is stated.
ward exectest + lint gates green. Updatedocs/FEATURES.mdfor the reshaped item surfaces.🔒 Reserved by
ward agent --driver claude— containerengineer-claude-eco-app-92on hostKAI-DESKTOP-TOWERis carrying this issue (reserved 2026-07-07T06:12:57Z). Concurrentward agentruns are blocked until it finishes or the reservation goes stale (2h0m0s TTL);--forceoverrides.Do not comment on or edit this issue to steer the run while it is reserved. The engineer seeded the body once at launch and never re-reads it, so a comment or edit reaches only human readers, never the running engineer. A correction goes to a new issue, dispatched fresh — that is the only channel that reaches a run in flight. Where the forge supports it, ward locks this conversation to make that a road-block rather than a convention (ward#494).
run seed context — what this run is carrying (ward#609)
coilyco-gaming/eco-app#92· branchissue-92· driverclaude· workflowdirect-mainengineer-claude-eco-app-92· wardv0.419.0· dispatched2026-07-07T06:12:57ZIssue body as seeded:
… (truncated to 2000 chars; full body is on this issue)
Static container doctrine and seed boilerplate are identical every run and omitted here (they ride ward v0.419.0).
— Claude (she/her), via
ward agentWARD-OUTCOME: done - actionable per-item page (summary + merged compressed reverse-chrono feed with search/actor/type filters + pagination) and directory sort chips + hide-untraded-by-default landed on main.
Honest retrospective:
The shape of this one was friendlier than expected because the hard parts already existed. The supply/demand "who buys it, where's it cheapest" summary is just
fetch_logistics(item=...)folded into the pivot — the logistics spine/tradeuses was right there, so I reused it rather than re-deriving offers. The feed compression (collapse runs of identical actor/verb/station rows into one counted row) fell out cleanly as a pure function, which made it pleasant to unit-test.What fought back: the world clock. The issue says age events against
/info'sTimeSinceStart, but mid-run I merged main and discovered #93 had just landed a whole two-calendars problem — the exporter CSVs count days as Time/86400 while the /info world clock counts 3600s/day. #93 also shipped exactly the helper item surfaces were meant to consume (formatRelative), so I switched the feed onto it. That merge conflict informat.tswas the only real friction, and main moved twice under me (concurrent containers), so I re-merged twice.StumpLatrine finding: real, not a bug. I queried the live deploy —
?item=StumpLatrineItemis two genuine bulk-craft rows (Count 40 + 32 at a Workbench), one row per bulk craft.craftCount(events) vscraftQuantity(units) diverging is the correct, now-legible behavior; no parse/dedupe defect in_fetch_craft_events.Confidence: high on the logic (491 backend + 98 frontend tests green, lint/build clean, and I smoke-tested the real payload shape end-to-end). One rough edge worth a follow-up: supply/demand totals are a floor when a market has more stores than the top-N offers shown (flagged with a
cappedbool), and the exporter-vs-world-clock day reconciliation #93 flagged is still a site-wide follow-up, not closed here.