# Mining Phase 2 — Configuration Composition and Scenario Workbench

Date: 2026-08-10
Repository: `staratlasmeta/sage-editor`
Branch: `claude/ses-mining-phase2-20260810`
Base: merged PR #207 (`6a7af4aeb9d9822384da22daf6ed7d9c31629d19`)

## Purpose

Phase 1 established the Mining lens as a source-grounded discovery and lineage surface. Phase 2 adds two bounded capabilities without creating another balance authority:

1. Select an active authored ship configuration and compare its composed Mining-throughput fields with the ship leaf's base fields.
2. Run a transparent scenario over explicit operator inputs for richness, selected-resource split, runtime multiplier, cargo occupancy/storage cost, and optional Food/Ammo balances.

The page remains read-only. It does not query accounts, submit transactions, or claim that a local scenario is a live-fleet prediction.

## Source and derived authority

### SES source authority

- Ship base stats: `SAGE Editor Suite/Ship Configurator/ships/*.json`
- Active configurations/components: `SAGE Editor Suite/Ship Configurator/ship_configurations-combatv5.json`
- Resource catalog: `SAGE Editor Suite/C4 Tools/data/resources.json`
- Body richness/locations: `SAGE Editor Suite/Map Editor/69regions-v10.json`
- Research metadata and XP thresholds: existing Phase 1 sources

### SES-derived values

`SAGE Editor Suite/Mining/scripts/mining-compose.mjs` composes only these Mining-relevant fields:

- `asteroid_mining_rate`
- `asteroid_mining_food_rate`
- `asteroid_mining_ammo_rate`
- `cargo_capacity`
- `ammo_capacity`
- `fuel_capacity`
- `loading_rate`
- `required_crew`

The helper mirrors the converter's selected-component and linear-stacking behavior. This duplication is not trusted by itself: `tools/c4-converter/tests/mining-configuration-parity.ts` drives the real `composeShipStats` over every generated active configuration and compares all eight fields with magnitude-aware numeric tolerance.

The 67 ship leaves do not author a `food_capacity` field. Phase 2 therefore does not display or infer one. Available Food remains an explicit optional scenario input.

### Programs runtime authority

The current runtime formula remains:

```text
fleet mining rate
× body resource richness
× (1 / selected resource count)
× runtime crew/rare-find modifiers
```

Tick duration/output is then constrained by Food, Ammo, cargo capacity, per-resource cargo storage cost, and settlement duration. Current `Fleet::mining_rate` has no resource-hardness divisor.

Live authority not available to this tool includes fleet quantity/state, current balances and occupancy, Character/crew modifiers, rare finds, eligibility, instruction timing, transaction results, XP awards, and settlement state.

## Generated artifact contract

The generator emits two deterministic artifacts:

1. `data/mining-data.json`
   - Readable source witnesses, summary, base ships, effect definitions, resources, research rows, formula boundary, and compact-encoding contract.
2. `data/mining-configurations.json`
   - Compact one-line machine payload containing the 2,928 active `v1`/`v2` configuration rows grouped by ship slug.

The split keeps the reviewable index near its Phase 1 size while avoiding a roughly 100,000-line generated diff. The compact configuration payload uses:

- `stats`: values aligned with `configurationContract.statFields`
- `effectGroups`: `[group-index, selected-count]` tuples aligned with `configurationContract.effectGroups`
- `sourceIndex`: the exact index in `shipConfigurations[ship slug]`

`npm run check:generated` regenerates both serializations in memory and fails if either committed artifact is missing or stale. `pretest` invokes this check automatically.

## Scenario math

Given composed mining rate `M`, richness `R`, selected-resource count `N`, runtime multiplier `X`, cargo capacity `C`, occupied cargo `O`, uniform selected-resource storage cost `S`, optional Food `F` with burn `Fb`, authored Food storage cost `Fs`, and optional Ammo `A` with burn `Ab`:

```text
total output rate       = M × R × X
per-resource rate       = total output rate / clamp(N, 1, 8)
free cargo              = max(0, C - O)
resource volume inflow  = total output rate × S
Food volume outflow     = Fb × Fs          (only when F is provided)
net cargo fill rate     = resource volume inflow - Food volume outflow
cargo runway            = free cargo / net cargo fill rate (unbounded when net ≤ 0)
Food runway             = F / Fb          (only when F is provided)
Ammo runway             = A / Ab          (only when A is provided)
limiting duration       = min(modeled runways)
settled total units     = total output rate × limiting duration
settled units/resource  = per-resource rate × limiting duration
```

A zero burn rate is non-limiting. Blank Food or Ammo excludes that balance-dependent runway, not as an infinite balance. Food cargo-volume outflow remains source-derivable when Food balance is blank. If no modeled bound is finite, settled units remain explicitly unbounded by the entered model.

Cargo occupancy must include carried consumables. One entered storage cost is applied uniformly across selected resources. Food's authored `cargo_types.json` storage cost is source-grounded in generated data, and Programs-aligned Food consumption frees that volume while Mining fills the hold. Blank Food excludes only the balance-dependent Food runway; its volume-outflow rate remains derivable from composed Food burn and authored storage cost.

## UI contract

- Ship selector includes only ships with at least one active configuration; zero-config manifest entries remain in generated provenance/summary data but cannot leave stale configuration results on screen
- Eight base-versus-composed stat cards with precise small-rate formatting
- One selected-effect card per unique component group
- C4 ID, source index, status, lock, tags, and research metadata
- Scenario input and result surfaces
- Direct links to Ship Config Lite, Ship Stats, SAGE Map Editor, Research Nodes, and Uber Export
- Existing component/resource tables remain one-row-per-unique-item and explicitly scrollable
- Desktop and 390px mobile layouts have no page-level horizontal overflow

## Validation

Validated on the exact working tree before commit:

- Mining freshness + structural/scenario tests: **16/16 passing**
- Converter TypeScript typecheck: passing
- Real Heat/Shockwave composition contract: passing
- Real converter configuration parity: **2,928/2,928 active configurations passing**
- Desktop browser probe: 8 stat cards, 6 selected effect-group cards for the exercised Tier Five fixture, 9 scenario outputs, 19 component rows, 95 resource rows, no console/page errors, no page overflow
- 390×844 browser probe: same functional counts, no console/page errors, no page overflow; wide component/resource tables remain inside their intended horizontal scroll shells

Diagnostic entity counts are reported rather than pinned as immutable balance invariants. Structural coverage and complete parity are asserted.

## Delivery boundary

No chain/config write, deployment, merge, or self-approval is part of this phase. Publication follows the normal Star Atlas branch and human-review lifecycle.
