Skip to content

fix(bot): make greenfield bootstrap actually trade (issue #17)#18

Open
jdkajewski wants to merge 2 commits into
jdkajewski/ts-rewrite-planfrom
dk-greenfield-bootstrap-fix
Open

fix(bot): make greenfield bootstrap actually trade (issue #17)#18
jdkajewski wants to merge 2 commits into
jdkajewski/ts-rewrite-planfrom
dk-greenfield-bootstrap-fix

Conversation

@jdkajewski

Copy link
Copy Markdown
Owner

Fixes the core greenfield-bootstrap blockers found while running the TS bot live on a fresh weekly reset — the bot sat at its starting credits with the sole trader parked, never trading. Now verified earning end-to-end on the live agent.

Root causes (two fixed in code, one config)

1. Empty coords → zero lanes (the hidden blocker). On a fresh reset the persistence waypoint table is empty, so the distance function D() has no coordinates → every candidate lane fails the MAXD distance gate → buildLanes() returns nothing → the ship parks forever. main.ts now eagerly fetches the home system's waypoints from the game API at boot and populates the coords map (idempotent — skipped once coords are present, so established runs are unaffected).

2. Unaffordable full lot → whole lane rejected. selectLane() rejected an entire lane when the full tradeVolume lot cost exceeded the working budget (estCost > availableForWork → continue). A capital-constrained bot therefore couldn't trade high-value goods at all. It now scales the lot down to the affordable unit count instead of rejecting.

3. Greenfield capital config (deploy/bot.greenfield.env.example): the default OPERATING_RESERVE (200k) + goods cushions computed a reserve larger than the ~175k starting capital, freezing all spending (no ship buys, no trades). Set low greenfield reserves, BOOTSTRAP_FLEET_MIN=1, and mining/contracts off (the extract path yields 0 ore — separate bug tracked in #17).

Also adds a one-line worker diagnostic when a ship can't claim a lane (markets/priced/lanes/budget) — this is what pinpointed the coords bug.

Live validation (fresh agent UPRISING, HQ X1-SQ96, 175k start)

🗺 eager home coords: loaded 83 X1-SQ96 waypoint coordinates
UPRISING-1 bought 17 LAB_INSTRUMENTS @ 3362 → sold 17 @ 5430 (+92,310)
UPRISING-1 bought 10 LAB_INSTRUMENTS @ 3394 → sold 10 @ 5350 (+53,500)
run total +54,716 over 2 lanes  |  credits 68k → 103k → 122k

Before: 0 trades, frozen. After: trades immediately and compounds.

Verification

276 bot tests pass, tsc --noEmit clean, eslint clean on changed files.

Not in scope (tracked in #17)

Mining extract yields 0 ore + mine-events 400; ships default to DRIFT not CRUISE at boot (mitigated once coords/markets are known). Re-enabling contracts/gate/expansion for the full greenfield→endgame lifecycle once mining is fixed.

jdkajewski and others added 2 commits June 21, 2026 11:15
A fresh-reset agent could never establish a trade loop — verified live on a
new reset, the bot sat at its starting credits with the sole trader parked.
Three compounding bugs, two fixed here in code:

1. Empty coords → no lanes. On greenfield the persistence waypoint table is
   empty, so the distance fn D() has no coordinates; every candidate lane fails
   the MAXD gate and buildLanes() returns nothing → the ship parks forever.
   main.ts now eagerly fetches the home system's waypoints from the game API at
   boot and populates the coords map (idempotent; skipped once coords exist).

2. Unaffordable full lot → lane rejected. selectLane() rejected a whole lane
   when the full tradeVolume lot exceeded the working budget, so a capital-
   constrained bot could not trade high-value goods at all. It now scales the
   lot down to the affordable unit count instead of rejecting outright.

3. (config) Greenfield capital settings in deploy/bot.greenfield.env.example:
   OPERATING_RESERVE/GOODS_CUSHION default reserve exceeded the ~175k starting
   capital and froze all spending; BOOTSTRAP_FLEET_MIN=1 to exit BOOTSTRAP with
   one trader; mining/contracts off (extract path yields 0 ore, separate bug).

Also adds a one-line worker diagnostic logged when a ship can't claim a lane
(markets/priced/lanes/budget), which is what pinpointed the coords bug.

Verified live on a fresh agent: home coords load (83 wps) → buildLanes finds
the lane → buys an affordable 17-unit lot → sells → credits 68k→122k over 2
lanes. 276 bot tests pass, tsc + eslint clean.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
FLEET_SCALE could not buy a 2nd trader on greenfield: it anchored on the
probe yard and issued the cargo-ship purchase there, but that yard sold only
probes -> POST /my/ships 400 "SHIP_LIGHT_SHUTTLE does not exist". The single
starter trader did all the trading and the flywheel could not scale.

Two root causes:
- getShipyards collapses each ship type to its cheapest yard, hiding that one
  yard sells BOTH probes and cargo (a cheaper probe elsewhere wins the key).
  pickAnchorYards now reads the full per-yard type cache (state.fleet.shipyards)
  so a combined yard is detected and preferred as the anchor.
- Cargo buys were hardcoded to anchorYard. They now target cargoYard, anchor a
  probe there when it differs from the probe yard, and dock before buying.

Verified live on UPRISING (X1-SQ96): anchor moved C40 -> A2 (sells probe+cargo),
400s stopped. 279 bot tests pass (3 new for pickAnchorYards), tsc clean.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant