reset-readiness: greenfield deploy profile + markets write-through fix (#8)#12
Merged
Merged
Conversation
#8) Make packages/bot production-ready for a fresh greenfield weekly reset. Issue #8 — markets write-through: - persistence.putMarkets() converted the bot's Record<wp,Market> straight to the wire, but PUT /markets (BulkPutBody) wants Array<{waypoint,data}> → 400, and the call is fire-and-forget so it was silently dropped (no snapshot ever persisted). Convert Record→array before send. The GET side mismatched too (api returns Array<{waypoint,data,updatedAt}>, bot typed it as Record) so getMarkets()/getMarket() now reduce the array back into the Record the cache expects. Added a contract test that validates the body shape exactly as BulkPutBody would (and guards the old Record body as a regression). docker-compose: - Dropped SYSTEM: ${SYSTEM:-X1-PP30} from the bot environment: block so a fresh reset auto-detects home via resolveHome() instead of pinning the old system. (environment: overrides env_file:, so a pin there clobbers a per-profile value.) - Layered ./deploy/bot.greenfield.env as a second env_file: entry and documented the --env-file requirement for live runs. Greenfield deploy profile: - New deploy/bot.greenfield.env.example: a complete, reset-agnostic LIVE earner profile (no hardcoded system/waypoint/ship symbols). Enables the self- provisioning earner stack (FLEET_SCALE, CONTRACTS, GATE_SUPPLY, MINE_FEED/ EXPAND, GALAXY_CRAWL + AUTO_EXPAND); battle-tested floors mirrored from the legacy overnight_experiment profile with reset-specific pins stripped; issue-#2 scan-optimization levers left at default OFF; runbook header with the exact compose invocation. NEGOTIATOR default: - shared/config.ts NEGOTIATOR default was a reset-specific ship 'SPACEJAM-DK-2-15' — a greenfield footgun. Defaulted to '' and guarded the new-contract negotiate call on a non-empty NEGOTIATOR so an empty value cleanly skips auto-negotiation (the bot still accepts offered/pending contracts). Pin to the command ship post-register for sustained negotiation. Verification: @st/shared build clean, @st/bot tsc --noEmit clean, eslint clean on changed files, 269 bot tests pass (incl. 4 new markets contract tests), 18 api tests pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Makes
packages/botproduction-ready to run LIVE at the next greenfield weekly reset — deployment polish, not new earners. A readiness pass confirmed all earner subsystems are wired and home/expansion auto-detect; this PR removes the remaining reset-specific footguns and ships a reset-agnostic launch profile.1. Fix issue #8 — markets write-through
persistence.putMarkets()sent the bot'sRecord<wp, Market>straight to the wire, butPUT /markets(BulkPutBody) expectsArray<{ waypoint, data }>→ 400, and the call is fire-and-forget so it was silently dropped (no market snapshot ever persisted → crawler/market history lost on restart).putMarketsnow convertsRecord → Array<{waypoint, data}>before send.Array<{waypoint, data, updatedAt}>, the bot typed it as aRecord) —getMarkets()/getMarket()now reduce the array back into theRecordthe cache expects.persistence.markets.test.ts, 4 cases) validates the outgoing body exactly asBulkPutBodywould, guards the old Record body as a regression, and round-trips GET so the bot↔api shapes can't drift again.2. docker-compose — auto-detect home
SYSTEM: ${SYSTEM:-X1-PP30}from the botenvironment:block so a fresh reset auto-detects home viaresolveHome()instead of pinning the previous reset's system. (environment:overridesenv_file:, so a pin there would clobber a per-profile value.)./deploy/bot.greenfield.envas a secondenv_file:entry and documented the--env-filerequirement for live runs.3. Greenfield deploy profile
New
deploy/bot.greenfield.env.example— a complete, reset-agnostic LIVE earner profile with no hardcoded system/waypoint/ship symbols:DRY_RUN=0, token=PASTE_AT_RESET,API_BASE_URL=http://api:3000,SYSTEMunset (auto-detect).FLEET_SCALE,CONTRACTS,GATE_SUPPLY,MINE_FEED+MINE_EXPAND,GALAXY_CRAWL+AUTO_EXPAND— all of which auto-discover shipyards/tenders/outposts so no ship pins are needed.INPUT_FEED=0(matches the battle-tested legacy profile).overnight_experimentprofile (MIN_NET=1200,GATE_CREDIT_FLOOR=900000,FLEET_SCALE_FLOOR=30000, …) with reset-specific pins stripped and greenfield-safe values chosen.SCAN_*/COVERAGE_*/SCAN_BUDGET_*/FLEET_COVERAGE_*) left at default OFF — not needed to earn; enable + measure post-reset against the credits-per-request metric.docker compose --env-file deploy/bot.greenfield.env up --build.The legacy
deploy/bot.env.exampleis untouched.4. NEGOTIATOR default — honest gap signal ⚠
shared/config.tsdefaultedNEGOTIATORto a reset-specific ship'SPACEJAM-DK-2-15'— a greenfield footgun (CONTRACTS=1would dock/negotiate against a ship that doesn't exist on a fresh reset). Changed the default to''and guarded the new-contract negotiate call on a non-empty NEGOTIATOR so an empty value cleanly skips auto-negotiation.Gap: with
NEGOTIATORempty the bot still accepts offered/pending contracts but cannot negotiate NEW ones — the profile can't know the agent's command ship pre-reset. The runbook instructs settingNEGOTIATOR=<AGENT>-1post-register for sustained contract income. A future enhancement could auto-pick the command ship; flagged for review.Calibration assumption
The live
.mjshistory (live-metrics.json) is issue-#2 scan/lane data and not relevant to greenfield earner floors, which come from the battle-tested legacyovernight_experimentprofile. Referenced in the env header as a comment for later scan-lever tuning.Verification
@st/sharedbuild clean,@st/bot tsc --noEmitclean, eslint clean on changed files.prisma generatecodegen step).Scope boundary: does NOT touch the parked issue-#2 optimization PRs (#9, #10).