Bounded Market Autonomy
Scope
The first autonomous Market policy exists only to reopen demonstrably blocked native-mineral production. It evaluates a mineral when the room's protected native target is effectively full and the visible deposit has regenerated meaningful supply. Idle inventory, attractive prices, or elapsed time alone do not authorize a sale.
The supported decision graph is deliberately fixed:
- sell one eligible raw mineral;
- compress it through an already-compatible owned Factory and sell the output;
- for two eligible reagents of an enabled Lab recipe, compare their best independent paths with producing and selling that one compound.
The current enabled pairs are U/O to UO and L/H to LH. Compression uses the corresponding enabled base commodities. There is no recursive recipe solver, prerequisite manufacturing, arbitrary chemistry search, persistent order placement, buying, or speculative holding policy.
Eligibility And Safety
Default configuration lives in src/config/marketAutonomy.ts:
- evaluation cadence: 25 ticks;
- maximum batch: 1,000 raw units;
- maximum autonomous execution window without material progress: 500 ticks;
- effectively full threshold: 95% of the native mineral target;
- strategic reserve: 10,000 units per raw mineral;
- meaningful regenerated deposit: 1,000 units;
- required processing premium: 10%.
The evaluator subtracts active Factory, Lab, and boost commitments before it declares inventory liquidatable. Economy mode must be normal, optional spending must be open, the economy status must be stable or surplus, and CPU emergency must be absent. Active operator Factory, Lab, Market, or committed boost work blocks new autonomous execution. A boost-provisioning slot is a committed higher-priority blocker for liquidation in that provider room: an already-active liquidation plan yields, and the liquidation owner cancels only its own subordinate Factory, Lab, or Market directives. Explicit operator directives are never displaced and continue to block conflicting boost preparation explainably. Existing managers repeat their own safety checks during production, hauling, Terminal staging, and sale.
Operator authority defaults to autonomous and is persistent:
debug.marketAutonomy()
debug.marketAutonomy("manual")
debug.marketAutonomy("autonomous")
Manual mode continues to refresh the recommendation but does not create work. Changing authority does not cancel an already-started bounded order; use the existing Factory, Lab, or Market cancellation command when deliberate operator intervention is required.
Valuation
Only current Market buy orders with a Terminal room, positive remaining amount, and enough aggregate volume to cover the whole candidate output are executable quotes. The evaluator walks those orders from highest to lowest price and uses their weighted gross credit value. It does not inspect advertised sell orders.
Factory input/output quantities come from COMMODITIES. Lab output and reagent
batching use LAB_REACTION_AMOUNT. Candidate values are compared over the exact
same raw quantities:
normalizedCredits: executable gross credits for the bounded raw basis;creditsPerRawInput: gross credits divided by all raw input units;grossAdvantageCredits: processed value minus its simpler baseline;grossAdvantageRatio: that advantage divided by the baseline value.
Compression or compound production is accepted only when the advantage ratio meets the configured premium. A missing raw/independent executable baseline cannot authorize processing. Energy is intentionally not assigned a credit price; Factory/Lab and Terminal energy use the existing hard economy and reserve gates.
Execution And Memory
The policy stores one current evaluation and one optional plan under
Memory.marketPolicy.surplusLiquidation. An independent two-resource winner is
executed as no more than two sequential actions. Each action delegates to the
existing order APIs:
- Factory or Lab manager produces the selected bounded output, when required.
- Existing protected-service hauling evacuates/stages it.
- MarketManager sells against buy orders at or above the evaluated floor.
Every autonomous plan persists a material-progress tick. The clock advances only when work moves toward completion: sell inventory actually increases in the Terminal, a Market deal succeeds, a liquidation-owned Lab reaction produces output, a liquidation-owned Factory cycle produces output, or an action completes. Quote refreshes, repeated blockers, manager runs, and equivalent reason updates do not count.
After 500 ticks without material progress, the liquidation owner cancels any
active subordinate directive whose initiatedBy and liquidationPlanId
provenance match the plan. The plan becomes stale and waits for the normal
25-tick evaluation cadence. Committed boost preparation similarly makes it
preempted. Neither state resumes the old plan: current inventory, capability,
and executable order depth must produce a new plan. The evaluated price floor
is not lowered because time elapsed; retaining inventory remains safe.
The state is current-state only. It contains no order history, counterparty
history, rejected quotes, or tick-by-tick prices. Use debug.marketAutonomy()
for the eligibility explanation, evaluated prices, normalized candidates,
winner, premium decision, safety gates, plan state, and last material-progress
tick/age. Factory, Lab, and Market inspection also shows directive provenance
and the progress clock when the directive belongs to liquidation.
CPU And Telemetry
Evaluation is no more frequent than every 25 ticks; active-plan progression is
constant and bounded. CPU is visible at
Memory.stats.cpu.profile.rooms.<roomName>.marketAutonomy. Numeric Market
metrics are documented in docs/STATS.md. Evaluation quotes and normalized
recommendations are distinct from the latest realized autonomous sale.