codex: mining-f2p — executable GE purchase loop, structured copper/tin below-15 fallback, a2 target restrict (bounce-fix 5)
Governor bounce 5 (2026-08-28) repaired finding by finding: 1. Tool purchase is now executable end to end: new a10 ge_open before any ge_buy; a12 wait-ge-fill is BOUNDED (one 3-6 min fill window) and on no-fill/partial-fill TIMEOUT cancels the resting offer -> a13 collects/refunds -> fail closed via recover (3 loops -> failed); a resting offer is never re-placed indefinitely. Actions renumbered a11..a17. 2. min_level 1 copper/tin below-15 path now has STRUCTURED fallback rows (mine_sites se-varrock-copper / se-varrock-tin, level 1, 17.5 xp, safe East Varrock) added to mining_modes.fast-xp.sites; level-1 and level-14 selections are pinned in a new mining_selections block and recomputed by a new select_fast_site() validator gate (+ 3 committed selftest fixtures). 3. a2 no longer advertises silver/coal/gold/mithril banked targets: it restricts banked-income to the declared rows (iron @ se-varrock-bank, adamantite @ al-kharid-south-adamantite); superheat-coal technique is marked informational-only. New ge_open/ge_offers_done/ge_collect validator gate (+ 1 fixture). Modeled below-15 rate 6,300 XP/hr (was the unbacked '~8,800' prose) recomputed from the bronze cadence midpoint. Validator: 2 entries, 0 errors, 1 pre-existing WARN; --selftest 17 PASS; git diff --check clean.
This commit is contained in:
parent
765505ed0f
commit
64b5e4890e
@ -3,7 +3,7 @@ title: Mining (F2P)
|
|||||||
domain: training
|
domain: training
|
||||||
tags: [mining, gathering, f2p, skill-training]
|
tags: [mining, gathering, f2p, skill-training]
|
||||||
status: verified
|
status: verified
|
||||||
version: 5 # 5: bounce-fix 4 2026-08-28 — structured mine_sites/pickaxe_tiers/pickaxe_examples/mining_modes data model (validated exactly by the validator: no phrase-search); per-site respawn/depletion modeling (adamantite = respawn-bound + world-hop policy, runite NOT selectable — Wilderness PK risk); success-model rolls_per_ore; executable tool prep (check/withdraw/buy/wait/collect/equip via Wield); hop_world action; sub-29 fast-xp stays fast-xp at a safe drop site; modeled rates recomputed (28,000 xp/hr fast-xp drop; 70,080 gp/hr adamantite w/ hop; 49,900 iron banked)
|
version: 6 # 6: bounce-fix 5 2026-08-28 — executable GE purchase loop (new a10 ge_open action; bounded fill/no-fill timeout -> cancel/refund/collect -> fail closed, never re-place a resting offer); structured copper/tin below-15 fallback sites (mine_sites se-varrock-copper / se-varrock-tin, level 1, 17.5 xp, safe) pinned in mining_selections (levels 1 & 14) with validator fixtures; a2 restricted to the DECLARED banked-income target rows (iron @ se-varrock-bank, adamantite @ al-kharid-south-adamantite only — silver/coal/gold/mithril no longer advertised)
|
||||||
updated: "2026-08-28" # ISO dates must stay quoted — YAML 1.1 parses bare dates to datetime.date
|
updated: "2026-08-28" # ISO dates must stay quoted — YAML 1.1 parses bare dates to datetime.date
|
||||||
|
|
||||||
summary: >
|
summary: >
|
||||||
@ -11,10 +11,13 @@ summary: >
|
|||||||
validated against the structured mine_sites table; the entry never
|
validated against the structured mine_sites table; the entry never
|
||||||
silently picks "the highest available rock":
|
silently picks "the highest available rock":
|
||||||
- fast-xp: powermining for XP. Iron (level 15, 35 xp) from level 15
|
- fast-xp: powermining for XP. Iron (level 15, 35 xp) from level 15
|
||||||
onward, copper/tin (17.5 xp) below 15; every full inventory is DROPPED
|
onward; copper/tin (17.5 xp) below 15 run on STRUCTURED fallback
|
||||||
(drop route explicit — drop_run). Sub-combat-29 accounts run fast-xp at
|
mine_sites rows (se-varrock-copper / se-varrock-tin, East Varrock,
|
||||||
the safe South-east Varrock drop site; combat 29+ may use the Al Kharid
|
level 1, safe — selection pinned in mining_selections at levels 1 and
|
||||||
3-rock powermine. Mode NEVER switches to banking.
|
14). Every full inventory is DROPPED (drop route explicit — drop_run).
|
||||||
|
Sub-combat-29 accounts run fast-xp at the safe South-east Varrock drop
|
||||||
|
site; combat 29+ may use the Al Kharid 3-rock powermine. Mode NEVER
|
||||||
|
switches to banking.
|
||||||
- banked-income: ONE deterministic target mine_sites row chosen and
|
- banked-income: ONE deterministic target mine_sites row chosen and
|
||||||
validated at session start (Mining level >= ore level; the row's
|
validated at session start (Mining level >= ore level; the row's
|
||||||
access/safety gates; inventory policy = bank) and every load is BANKED
|
access/safety gates; inventory policy = bank) and every load is BANKED
|
||||||
@ -37,6 +40,7 @@ accounts:
|
|||||||
- "Pickaxe: two SEPARATE gates per tier (pickaxe_tiers table): MINING level decides which pickaxe can be USED (bronze 1, iron 1, steel 6, mithril 21, adamant 31, rune 41); ATTACK level decides ONLY whether it can be EQUIPPED (steel 5, mithril 20, adamant 30, rune 40). Select by Mining, equip only when Attack permits, otherwise CARRY the same selected tool — a 1-Attack/41-Mining account selects, carries, and uses a rune pickaxe (pickaxe_examples)"
|
- "Pickaxe: two SEPARATE gates per tier (pickaxe_tiers table): MINING level decides which pickaxe can be USED (bronze 1, iron 1, steel 6, mithril 21, adamant 31, rune 41); ATTACK level decides ONLY whether it can be EQUIPPED (steel 5, mithril 20, adamant 30, rune 40). Select by Mining, equip only when Attack permits, otherwise CARRY the same selected tool — a 1-Attack/41-Mining account selects, carries, and uses a rune pickaxe (pickaxe_examples)"
|
||||||
- "Run mode chosen at session start: fast-xp (powermine, drop every load) or banked-income (deterministic target mine_sites row, bank every load) — mining_modes table"
|
- "Run mode chosen at session start: fast-xp (powermine, drop every load) or banked-income (deterministic target mine_sites row, bank every load) — mining_modes table"
|
||||||
- "Bank route from the chosen mine (fast-xp drops instead when no bank leg is wanted)"
|
- "Bank route from the chosen mine (fast-xp drops instead when no bank leg is wanted)"
|
||||||
|
- "Below-15 fast-xp (Mining 1-14): copper/tin (17.5 xp) at the structured East Varrock fallback rows (mine_sites se-varrock-copper / se-varrock-tin — no aggressive NPCs, safe at any combat level); the deterministic selection is pinned in mining_selections (levels 1 and 14) and recomputed by the validator"
|
||||||
- "Al Kharid powermine HARD GATE: combat level >= 29 (a monster attacks players at <= 2x its level; the scorpion is level 14, so its aggro ceiling is combat 28 and 29+ is safe). Sub-combat-29 accounts run fast-xp at the South-east Varrock DROP site (no aggressive NPCs) — the mode does not change to banking"
|
- "Al Kharid powermine HARD GATE: combat level >= 29 (a monster attacks players at <= 2x its level; the scorpion is level 14, so its aggro ceiling is combat 28 and 29+ is safe). Sub-combat-29 accounts run fast-xp at the South-east Varrock DROP site (no aggressive NPCs) — the mode does not change to banking"
|
||||||
- "adamantite @ Al Kharid south REQUIRES world hopping (mine_sites row: world_hop true, hop_world action) — respawns are 4 min and the wiki's 120+ ores/hr assumes hopping F2P worlds"
|
- "adamantite @ Al Kharid south REQUIRES world hopping (mine_sites row: world_hop true, hop_world action) — respawns are 4 min and the wiki's 120+ ores/hr assumes hopping F2P worlds"
|
||||||
|
|
||||||
@ -53,7 +57,7 @@ best_practice:
|
|||||||
why: "the quest reward alone takes Mining from 1 to 10; the materials (6 clay, 4 copper, 2 iron) mine at level 1 except iron, which can be bought on the GE"
|
why: "the quest reward alone takes Mining from 1 to 10; the materials (6 clay, 4 copper, 2 iron) mine at level 1 except iron, which can be bought on the GE"
|
||||||
source: "OSRS wiki — Free-to-play Mining training (Level 1-10: Doric's Quest)"
|
source: "OSRS wiki — Free-to-play Mining training (Level 1-10: Doric's Quest)"
|
||||||
- name: "powermine iron for maximum XP (fast-xp only)"
|
- name: "powermine iron for maximum XP (fast-xp only)"
|
||||||
why: "iron (level 15, 35 xp) is the fastest F2P training ore; Al Kharid is the only F2P site with three iron rocks around one tile (combat 29+ gate) and South-east Varrock's two iron rocks serve sub-29 accounts with the same drop behaviour — the mode is unchanged. Modeled fast-xp rate ~28,000 XP/hr at 61+ with rune (success model + drop loop + breaks pinned in economy); drop the ores, banking costs XP"
|
why: "iron (level 15, 35 xp) is the fastest F2P training ore; Al Kharid is the only F2P site with three iron rocks around one tile (combat 29+ gate) and South-east Varrock's two iron rocks serve sub-29 accounts with the same drop behaviour — the mode is unchanged. Below 15 the structured copper/tin fallback (se-varrock-copper / se-varrock-tin, 17.5 xp, safe East Varrock) keeps the same drop behaviour for level 1-14 (mining_selections pins levels 1 and 14). Modeled fast-xp rate ~28,000 XP/hr at 61+ with rune (success model + drop loop + breaks pinned in economy); drop the ores, banking costs XP"
|
||||||
source: "OSRS wiki — Free-to-play Mining training (Levels 15-99: Iron ore); OSRS wiki — Aggressiveness; OSRS wiki — Iron rocks (respawn ~5.4 s)"
|
source: "OSRS wiki — Free-to-play Mining training (Levels 15-99: Iron ore); OSRS wiki — Aggressiveness; OSRS wiki — Iron rocks (respawn ~5.4 s)"
|
||||||
- name: "bank iron at the South-east Varrock mine (banked-income anchor)"
|
- name: "bank iron at the South-east Varrock mine (banked-income anchor)"
|
||||||
why: "the guide names this F2P banking location explicitly; the eastern Varrock bank is the closest bank leg (~30 s per load), and the ores feed Smithing. Modeled ~49,900 gp/hr with rune (midpoint policy model, see economy comments)"
|
why: "the guide names this F2P banking location explicitly; the eastern Varrock bank is the closest bank leg (~30 s per load), and the ores feed Smithing. Modeled ~49,900 gp/hr with rune (midpoint policy model, see economy comments)"
|
||||||
@ -64,15 +68,18 @@ best_practice:
|
|||||||
- name: "runite is NOT selectable in this entry"
|
- name: "runite is NOT selectable in this entry"
|
||||||
why: "F2P runite sits in the Wilderness with a ~12-minute respawn — modelling it would require Wilderness travel and PK survival plus heavy world hopping; the mine_sites row is selectable: false and the entry refuses it rather than hand-waving the hazard"
|
why: "F2P runite sits in the Wilderness with a ~12-minute respawn — modelling it would require Wilderness travel and PK survival plus heavy world hopping; the mine_sites row is selectable: false and the entry refuses it rather than hand-waving the hazard"
|
||||||
source: "OSRS wiki — Runite ore (respawn ~12 min; F2P rocks in the Wilderness); mine_sites row runite-wilderness"
|
source: "OSRS wiki — Runite ore (respawn ~12 min; F2P rocks in the Wilderness); mine_sites row runite-wilderness"
|
||||||
- name: "superheat coal (optional banked variant): West Lumbridge Swamp mine"
|
- name: "superheat coal (informational only — NOT a selectable banked-income target)"
|
||||||
why: "coal (level 30, 50 xp) banks reasonably from the Lumbridge Swamp mine; with 43 Magic, Superheat Item converts coal into bars without a furnace, cutting bank trips (staff of fire + nature runes)"
|
why: "the West Lumbridge Swamp mine holds coal (level 30, 50 xp); with 43 Magic, Superheat Item converts coal to bars without a furnace. This entry does NOT declare a coal mine_sites row: banked-income targets are iron and adamantite ONLY, so superheat-coal is background knowledge (staff of fire + nature runes), never an advertised or executable target — a2's target set matches mining_modes.banked-income.targets exactly"
|
||||||
source: "OSRS wiki — Free-to-play Mining training (Levels 30-99: Superheat Item)"
|
source: "OSRS wiki — Free-to-play Mining training (Levels 30-99: Superheat Item, background note only)"
|
||||||
- name: "worked example — fast-xp session (preparation -> first full inventory -> first break -> resume)"
|
- name: "worked example — fast-xp session (preparation -> first full inventory -> first break -> resume)"
|
||||||
why: "Account: Mining 41, Attack 1, combat 35 (passes the Al Kharid gate). (1) prepare: mode fast-xp; ore policy iron 15+; pickaxe by MINING level -> rune (41 <= 41); equip gate Attack 1 < 40 -> CARRY the same tool (27 ore slots); the rune pickaxe is owned, so acquire = a9 withdraw-tool (bank_inventory); initial inventory = pickaxe + empty ore space. (2) travel: walk to Al Kharid (combat 35 >= 29 OK) and position at the 3-rock cluster. (3) mining rotations: click a fresh iron rock (a2, rune cadence [1800, 3600] ms) -> wait_rock: ore gained after ~1.33 rolls (success model) -> mine; repeat until the inventory is full. (4) first full-inventory boundary: 27 ores -> drop_run: 27 executions of a6 (right_click Drop, [200, 800] ms each) -> count_item ore == 0 -> mine. (5) first scheduled break: after the 8th-14th rotation the break counter trips -> break_state: take_break 60-180 s (a15). (6) resume: reposition at the cluster (a16) -> mine; the loop repeats until the XP target or session cap -> complete. Modeled policy rate: 803 ores/hr = 28,105 XP/hr -> pin 28,000 (economy)"
|
why: "Account: Mining 41, Attack 1, combat 35 (passes the Al Kharid gate). (1) prepare: mode fast-xp; ore policy iron 15+; pickaxe by MINING level -> rune (41 <= 41); equip gate Attack 1 < 40 -> CARRY the same tool (27 ore slots); the rune pickaxe is owned, so acquire = a9 withdraw-tool (bank_inventory); initial inventory = pickaxe + empty ore space. (2) travel: walk to Al Kharid (combat 35 >= 29 OK) and position at the 3-rock cluster. (3) mining rotations: click a fresh iron rock (a2, rune cadence [1800, 3600] ms) -> wait_rock: ore gained after ~1.33 rolls (success model) -> mine; repeat until the inventory is full. (4) first full-inventory boundary: 27 ores -> drop_run: 27 executions of a6 (right_click Drop, [200, 800] ms each) -> count_item ore == 0 -> mine. (5) first scheduled break: after the 8th-14th rotation the break counter trips -> break_state: take_break 60-180 s (a16). (6) resume: reposition at the cluster (a17) -> mine; the loop repeats until the XP target or session cap -> complete. Modeled policy rate: 803 ores/hr = 28,105 XP/hr -> pin 28,000 (economy)"
|
||||||
source: "derived from this entry's policy model (state_machine prepare/travel/mine/wait_rock/drop_run/break_state/complete + actions + run_control.break + mine_sites/rolls_per_ore), synthesized 2026-08-28"
|
source: "derived from this entry's policy model (state_machine prepare/travel/mine/wait_rock/drop_run/break_state/complete + actions + run_control.break + mine_sites/rolls_per_ore), synthesized 2026-08-28"
|
||||||
- name: "worked example — banked-income adamantite session (preparation -> first full inventory -> first break -> resume)"
|
- name: "worked example — banked-income adamantite session (preparation -> first full inventory -> first break -> resume)"
|
||||||
why: "Account: Mining 70, Attack 40, combat 60. Target: 500,000 gp banked or a 2 h session cap. (1) prepare: mode banked-income; target row = al-kharid-south-adamantite (mine_sites: ore level 70 <= Mining 70 OK; access/route validated; inventory policy bank) — the row id is logged to activity state; pickaxe by MINING level -> rune (41 <= 70); equip gate Attack 40 >= 40 -> EQUIP (28 ore slots); tool owned, withdraw from bank (a9). (2) travel: walk to the Al Kharid south adamantite spot. (3) mining rotations: click a fresh adamantite rock (rune roll 1.8 s, delay [1800, 3600] ms) -> wait_rock: ore gained -> mine; when BOTH rocks are depleted -> hop: hop_world (a14) to a fresh F2P world (world_hop row) and continue — this is where the wiki's 120 ores/hr comes from. (4) first full-inventory boundary: 28 ores -> bank_run: walk to the Al Kharid bank (a3), deposit all 28 (a4; 28 x 584 = 16,352 gp logged), walk back (a5) -> mine. (5) first scheduled break: after 8-14 rotations -> break_state: take_break 60-180 s (independent of the bank trips). (6) resume: reposition (a16) -> mine; complete when the banked value >= 500,000 gp or the session cap hits"
|
why: "Account: Mining 70, Attack 40, combat 60. Target: 500,000 gp banked or a 2 h session cap. (1) prepare: mode banked-income; target row = al-kharid-south-adamantite (mine_sites: ore level 70 <= Mining 70 OK; access/route validated; inventory policy bank) — the row id is logged to activity state; pickaxe by MINING level -> rune (41 <= 70); equip gate Attack 40 >= 40 -> EQUIP (28 ore slots); tool owned, withdraw from bank (a9). (2) travel: walk to the Al Kharid south adamantite spot. (3) mining rotations: click a fresh adamantite rock (rune roll 1.8 s, delay [1800, 3600] ms) -> wait_rock: ore gained -> mine; when BOTH rocks are depleted -> hop: hop_world (a15) to a fresh F2P world (world_hop row) and continue — this is where the wiki's 120 ores/hr comes from. (4) first full-inventory boundary: 28 ores -> bank_run: walk to the Al Kharid bank (a3), deposit all 28 (a4; 28 x 584 = 16,352 gp logged), walk back (a5) -> mine. (5) first scheduled break: after 8-14 rotations -> break_state: take_break 60-180 s (independent of the bank trips). (6) resume: reposition (a17) -> mine; complete when the banked value >= 500,000 gp or the session cap hits"
|
||||||
source: "derived from this entry's policy model (state_machine prepare/travel/mine/wait_rock/hop/bank_run/break_state/complete + actions + mine_sites.al-kharid-south-adamantite), synthesized 2026-08-28"
|
source: "derived from this entry's policy model (state_machine prepare/travel/mine/wait_rock/hop/bank_run/break_state/complete + actions + mine_sites.al-kharid-south-adamantite), synthesized 2026-08-28"
|
||||||
|
- name: "worked example — level-1 fast-xp copper/tin session (preparation -> first full inventory -> first break -> resume)"
|
||||||
|
why: "Account: Mining 1, Attack 1, combat 3. (1) prepare: mode fast-xp; below-15 selection pinned at level 1 (mining_selections) -> se-varrock-copper / se-varrock-tin; pickaxe by MINING -> the canonical selection at Mining 1 (bronze; iron shares the Mining-1 gate and can be substituted once owned); equip gate Attack 1 -> no equip, CARRY; the tool is owned, so acquire = a9 withdraw-tool (bank_inventory). (2) travel: walk to the East Varrock copper/tin rocks (safe — no aggressive NPCs) and position at the cluster. (3) mining rotations: click a fresh copper or tin rock (a2, bronze cadence [4800, 6600] ms) -> wait_rock: ore gained after ~1.6 rolls (success model) -> mine; both ores are 17.5 xp each. (4) first full-inventory boundary: 27 ores -> drop_run: a6 drops ONE slot per execution (right_click Drop, [200, 800] ms), looping until count_item ore == 0 -> mine. (5) first scheduled break: after the 8th-14th rotation the break counter trips -> break_state: take_break 60-180 s (a16). (6) resume: reposition at the cluster (a17) -> mine; complete on the XP/level target. Modeled policy rate: ~360 ores/hr = 6,300 XP/hr at the bronze cadence midpoint (economy)."
|
||||||
|
source: "derived from this entry's policy model (mining_selections levels 1/14 + mine_sites se-varrock-copper / se-varrock-tin + state_machine + actions a9/a2/a6/a16/a17), synthesized 2026-08-28"
|
||||||
|
|
||||||
pickaxe_tiers:
|
pickaxe_tiers:
|
||||||
bronze-pickaxe:
|
bronze-pickaxe:
|
||||||
@ -120,13 +127,26 @@ pickaxe_examples:
|
|||||||
expected_tier: mithril-pickaxe
|
expected_tier: mithril-pickaxe
|
||||||
expected_equipped: false # 30 Mining selects mithril (21); Attack 5 < 20 -> CARRY
|
expected_equipped: false # 30 Mining selects mithril (21); Attack 5 < 20 -> CARRY
|
||||||
|
|
||||||
|
# Deterministic mode-selection proof (governor bounce 5, 2026-08-28): the
|
||||||
|
# validator recomputes every row from mining_modes + mine_sites (eligible =
|
||||||
|
# selectable fast-xp site whose mining_level <= level; choose the highest
|
||||||
|
# ore xp, tie-break lexicographic site id) and compares. The level-1 and
|
||||||
|
# level-14 rows prove a below-15 account can always arm a structured
|
||||||
|
# copper/tin fast-xp run (mirrors the pickaxe_examples recompute pattern).
|
||||||
|
mining_selections:
|
||||||
|
fast_xp:
|
||||||
|
- level: 1
|
||||||
|
expected_site: se-varrock-copper # copper & tin share the East Varrock rocks (17.5 xp)
|
||||||
|
- level: 14
|
||||||
|
expected_site: se-varrock-copper # iron needs 15, so 1-14 stays on the copper/tin fallback
|
||||||
|
|
||||||
# Mode contract (owner decision 2026-08-28): both modes explicit; each mode's
|
# Mode contract (owner decision 2026-08-28): both modes explicit; each mode's
|
||||||
# sites/targets reference mine_sites rows; inventory policies are fixed.
|
# sites/targets reference mine_sites rows; inventory policies are fixed.
|
||||||
mining_modes:
|
mining_modes:
|
||||||
fast-xp:
|
fast-xp:
|
||||||
inventory_policy: drop # powermine: every load dropped, never banked
|
inventory_policy: drop # powermine: every load dropped, never banked
|
||||||
ore_policy: "iron (level 15, 35 xp) from 15 onward; copper/tin (17.5 xp) below 15 — never highest-available; sub-combat-29 accounts DROP at the South-east Varrock site (safe), combat 29+ may use the Al Kharid powermine — the mode never switches to banking"
|
ore_policy: "Mining 15+: iron (level 15, 35 xp) — never highest-available; Mining 1-14: copper/tin (17.5 xp) at the structured fallback rows (mine_sites se-varrock-copper / se-varrock-tin, level 1, safe); sub-combat-29 accounts DROP at the South-east Varrock site (safe), combat 29+ may use the Al Kharid powermine — the mode never switches to banking; site selection pinned in mining_selections (levels 1 and 14)"
|
||||||
sites: [al-kharid-powermine, se-varrock-drop]
|
sites: [al-kharid-powermine, se-varrock-drop, se-varrock-copper, se-varrock-tin]
|
||||||
banked-income:
|
banked-income:
|
||||||
inventory_policy: bank # every load banked until the GP target
|
inventory_policy: bank # every load banked until the GP target
|
||||||
targets: [se-varrock-bank, al-kharid-south-adamantite]
|
targets: [se-varrock-bank, al-kharid-south-adamantite]
|
||||||
@ -168,6 +188,36 @@ mine_sites:
|
|||||||
access: "no aggressive NPCs — safe at any combat level (the sub-29 fast-xp site)"
|
access: "no aggressive NPCs — safe at any combat level (the sub-29 fast-xp site)"
|
||||||
safety: "none required"
|
safety: "none required"
|
||||||
route: "drop in place — no bank leg"
|
route: "drop in place — no bank leg"
|
||||||
|
se-varrock-copper:
|
||||||
|
ore: Copper ore
|
||||||
|
ore_id: 436
|
||||||
|
mining_level: 1
|
||||||
|
xp: 17.5
|
||||||
|
rock_count: 2
|
||||||
|
respawn_seconds: 5.4
|
||||||
|
rolls_per_ore: 1.6 # below-15 success model (lower than iron 61+ = 1.33)
|
||||||
|
modeled_ores_per_hour: 360 # bronze cadence midpoint 5.7 s: 1.6 x 5.7 + 0.5 + 0.39 = 10.01 s/ore (economy)
|
||||||
|
world_hop: false
|
||||||
|
selectable: true
|
||||||
|
inventory_policy: drop
|
||||||
|
access: "East Varrock copper/tin rocks — no aggressive NPCs; safe at any combat level"
|
||||||
|
safety: "none required"
|
||||||
|
route: "drop in place; tin stands at the same rocks (se-varrock-tin) — a below-15 fast-xp run mines both copper and tin (17.5 xp each)"
|
||||||
|
se-varrock-tin:
|
||||||
|
ore: Tin ore
|
||||||
|
ore_id: 438
|
||||||
|
mining_level: 1
|
||||||
|
xp: 17.5
|
||||||
|
rock_count: 2
|
||||||
|
respawn_seconds: 5.4
|
||||||
|
rolls_per_ore: 1.6
|
||||||
|
modeled_ores_per_hour: 360
|
||||||
|
world_hop: false
|
||||||
|
selectable: true
|
||||||
|
inventory_policy: drop
|
||||||
|
access: "East Varrock tin/copper rocks — no aggressive NPCs; safe at any combat level"
|
||||||
|
safety: "none required"
|
||||||
|
route: "drop in place; copper stands at the same rocks (se-varrock-copper) — a below-15 fast-xp run mines both copper and tin (17.5 xp each)"
|
||||||
se-varrock-bank:
|
se-varrock-bank:
|
||||||
ore: Iron ore
|
ore: Iron ore
|
||||||
ore_id: 440
|
ore_id: 440
|
||||||
@ -192,7 +242,7 @@ mine_sites:
|
|||||||
respawn_seconds: 240 # wiki F2P adamantite guide: ~4-min respawn
|
respawn_seconds: 240 # wiki F2P adamantite guide: ~4-min respawn
|
||||||
rolls_per_ore: 2.0 # conservative success input at 70 Mining (rate is respawn-bound, not success-bound)
|
rolls_per_ore: 2.0 # conservative success input at 70 Mining (rate is respawn-bound, not success-bound)
|
||||||
modeled_ores_per_hour: 120 # Sourced measured baseline: wiki money guide ~120 ores/hr WITH world hopping; no-hop ceiling ~30 ores/hr
|
modeled_ores_per_hour: 120 # Sourced measured baseline: wiki money guide ~120 ores/hr WITH world hopping; no-hop ceiling ~30 ores/hr
|
||||||
world_hop: true # hop_world required (a14); the modelled rate assumes it
|
world_hop: true # hop_world required (a15); the modelled rate assumes it
|
||||||
selectable: true
|
selectable: true
|
||||||
inventory_policy: bank
|
inventory_policy: bank
|
||||||
access: "Al Kharid south rocks (no aggressive NPCs at this cluster)"
|
access: "Al Kharid south rocks (no aggressive NPCs at this cluster)"
|
||||||
@ -241,8 +291,10 @@ economy:
|
|||||||
# banked adamantite @ Al Kharid south (hop): 120 ores/hr (sourced
|
# banked adamantite @ Al Kharid south (hop): 120 ores/hr (sourced
|
||||||
# measured baseline) x 584 = 70,080 gp/hr; no-hop ceiling ~30 ores/hr
|
# measured baseline) x 584 = 70,080 gp/hr; no-hop ceiling ~30 ores/hr
|
||||||
# = 17,520 gp/hr — the entry models ONLY the hop rate.
|
# = 17,520 gp/hr — the entry models ONLY the hop rate.
|
||||||
# bronze path (below 15, copper/tin 17.5 xp): cadence midpoint 5.7 s ->
|
# copper/tin path (Mining 1-14, 17.5 xp): cadence midpoint 5.7 s
|
||||||
# ~8,800 XP/hr.
|
# (bronze [4800, 6600]) -> 1.6 rolls x 5.7 + 0.5 drop + 0.39 break =
|
||||||
|
# 10.01 s/ore -> 360 ores/hr -> 6,300 XP/hr (mine_sites
|
||||||
|
# se-varrock-copper / se-varrock-tin).
|
||||||
# EXTERNAL BENCHMARK (NOT the modeled rate): the wiki's 50,000 XP/hr
|
# EXTERNAL BENCHMARK (NOT the modeled rate): the wiki's 50,000 XP/hr
|
||||||
# (41+) / 52,500 XP/hr (61+) iron powermine figures assume a continuous
|
# (41+) / 52,500 XP/hr (61+) iron powermine figures assume a continuous
|
||||||
# 3-tick rotation with zero delay/drop/break overhead; the configured
|
# 3-tick rotation with zero delay/drop/break overhead; the configured
|
||||||
@ -265,6 +317,7 @@ economy:
|
|||||||
- "F2P ore chain (wiki guide): clay 1/5xp, copper 1/17.5, tin 1/17.5, iron 15/35, silver 20/40, coal 30/50, gold 40/65, mithril 55/80, adamantite 70/95, runite 85/125"
|
- "F2P ore chain (wiki guide): clay 1/5xp, copper 1/17.5, tin 1/17.5, iron 15/35, silver 20/40, coal 30/50, gold 40/65, mithril 55/80, adamantite 70/95, runite 85/125"
|
||||||
- "Sell prices 2026-08-27 (low edge): iron 70, coal 151, silver 73, gold 154, mithril 159, adamantite 584, runite 10,265"
|
- "Sell prices 2026-08-27 (low edge): iron 70, coal 151, silver 73, gold 154, mithril 159, adamantite 584, runite 10,265"
|
||||||
- "fast-xp: powermine iron 15+ and drop every load — XP is the product, realized gp 0; modeled 803 ores/hr -> 28,105 XP/hr (pin 28,000) at 61+ rune"
|
- "fast-xp: powermine iron 15+ and drop every load — XP is the product, realized gp 0; modeled 803 ores/hr -> 28,105 XP/hr (pin 28,000) at 61+ rune"
|
||||||
|
- "fast-xp 1-14 (copper/tin 17.5 xp): modeled ~360 ores/hr -> 6,300 XP/hr at the bronze cadence midpoint (economy comment) — structured rows se-varrock-copper / se-varrock-tin, pinned at levels 1 and 14 in mining_selections"
|
||||||
- "banked-income iron @ SE Varrock: modeled 713 ores/hr -> 49,910 gp/hr (pin 49,900); deterministic target row (mine_sites.se-varrock-bank)"
|
- "banked-income iron @ SE Varrock: modeled 713 ores/hr -> 49,910 gp/hr (pin 49,900); deterministic target row (mine_sites.se-varrock-bank)"
|
||||||
- "banked-income adamantite @ Al Kharid south: respawn-BOUND site (2 rocks, 4-min respawn) — modeled 120 ores/hr ONLY with world hopping (hop_world) = 70,080 gp/hr; without hopping the ceiling is ~30 ores/hr = 17,520 gp/hr (wiki F2P adamantite money guide)"
|
- "banked-income adamantite @ Al Kharid south: respawn-BOUND site (2 rocks, 4-min respawn) — modeled 120 ores/hr ONLY with world hopping (hop_world) = 70,080 gp/hr; without hopping the ceiling is ~30 ores/hr = 17,520 gp/hr (wiki F2P adamantite money guide)"
|
||||||
- "runite is NOT a selectable target in this entry — F2P runite sits in the Wilderness (PK risk, ~12-min respawn); the mine_sites row is selectable: false"
|
- "runite is NOT a selectable target in this entry — F2P runite sits in the Wilderness (PK risk, ~12-min respawn); the mine_sites row is selectable: false"
|
||||||
@ -277,22 +330,25 @@ state_machine:
|
|||||||
goal: >-
|
goal: >-
|
||||||
Session start. 1) Choose the run mode (mining_modes): fast-xp
|
Session start. 1) Choose the run mode (mining_modes): fast-xp
|
||||||
(powermine, drop) or banked-income (deterministic target mine_sites
|
(powermine, drop) or banked-income (deterministic target mine_sites
|
||||||
row, bank). 2) fast-xp ore policy: iron 15+ (copper/tin below 15),
|
row, bank). 2) fast-xp ore/site selection (deterministic; pinned in
|
||||||
site from mining_modes.fast-xp.sites (combat 29+ -> Al Kharid
|
mining_selections at levels 1 and 14): Mining 15+ -> iron site from
|
||||||
powermine, else SE Varrock drop — SAME mode, never banking).
|
mining_modes.fast-xp.sites (combat 29+ -> Al Kharid powermine, else
|
||||||
banked-income: pick ONE row from mining_modes.banked-income.targets
|
SE Varrock drop — SAME mode, never banking); Mining 1-14 -> the
|
||||||
and validate: level_is Mining >= row mining_level, the row's access
|
structured copper/tin fallback (mine_sites se-varrock-copper /
|
||||||
gates hold (e.g. adamantite requires the hop policy), inventory
|
se-varrock-tin, 17.5 xp, safe). banked-income: pick ONE row from
|
||||||
policy == bank; the row id is logged to activity state. 3) Pickaxe:
|
mining_modes.banked-income.targets and validate: level_is Mining >=
|
||||||
select the highest pickaxe_tiers row whose mining_level the account
|
row mining_level, the row's access gates hold (e.g. adamantite
|
||||||
meets (rune is usable at 41 Mining and equipable at 40 Attack).
|
requires the hop policy), inventory policy == bank; the row id is
|
||||||
4) Equip ONLY when level_is Attack >= the row's attack_level;
|
logged to activity state. 3) Pickaxe: select the highest
|
||||||
otherwise carry the same selected tool (a 1-Attack/41-Mining account
|
pickaxe_tiers row whose mining_level the account meets (rune is
|
||||||
selects and CARRIES a rune pickaxe). 5) Acquire the tool if missing
|
usable at 41 Mining and equipable at 40 Attack). 4) Equip ONLY when
|
||||||
(a8-a12: check / withdraw-owned / buy / wait / collect) and build
|
level_is Attack >= the row's attack_level; otherwise carry the same
|
||||||
the initial inventory: pickaxe (equipped or carried) + empty ore
|
selected tool (a 1-Attack/41-Mining account selects and CARRIES a
|
||||||
space; no food (all routes gate-safe). 6) Record mode + target row
|
rune pickaxe). 5) Acquire the tool if missing (a8-a13: check /
|
||||||
id in activity state.
|
withdraw-owned / open GE / place offer / bounded wait+collect) and
|
||||||
|
build the initial inventory: pickaxe (equipped or carried) + empty
|
||||||
|
ore space; no food (all routes gate-safe, incl. the copper/tin
|
||||||
|
fallback). 6) Record mode + target row id in activity state.
|
||||||
next: [travel, complete, failed]
|
next: [travel, complete, failed]
|
||||||
travel:
|
travel:
|
||||||
goal: "walk/teleport to the selected mine_sites location (fast-xp: Al Kharid 3-rock powermine at combat 29+, else South-east Varrock; banked-income: the session's validated target row) and position at the target cluster; arrive with the pickaxe equipped or carried per the prepare gate"
|
goal: "walk/teleport to the selected mine_sites location (fast-xp: Al Kharid 3-rock powermine at combat 29+, else South-east Varrock; banked-income: the session's validated target row) and position at the target cluster; arrive with the pickaxe equipped or carried per the prepare gate"
|
||||||
@ -301,9 +357,10 @@ state_machine:
|
|||||||
goal: >-
|
goal: >-
|
||||||
Mine the session target rock until the inventory is full or the run
|
Mine the session target rock until the inventory is full or the run
|
||||||
target is reached. Rock selection is MODE-DRIVEN and deterministic:
|
target is reached. Rock selection is MODE-DRIVEN and deterministic:
|
||||||
fast-xp mines iron (15+) or copper/tin (<15); banked-income mines
|
fast-xp mines iron (15+) or copper/tin (<15, the structured
|
||||||
ONLY the session's target mine_sites row (never the highest
|
se-varrock fallback rows); banked-income mines ONLY the session's
|
||||||
available rock). Every a2 click is followed by the wait_rock outcome
|
target mine_sites row (never the highest available rock). Every a2
|
||||||
|
click is followed by the wait_rock outcome
|
||||||
wait — never chain clicks on the same rock. A world_hop site
|
wait — never chain clicks on the same rock. A world_hop site
|
||||||
(adamantite) hops when both rocks are depleted.
|
(adamantite) hops when both rocks are depleted.
|
||||||
next: [wait_rock, drop_run, bank_run, hop, recover, survive, complete]
|
next: [wait_rock, drop_run, bank_run, hop, recover, survive, complete]
|
||||||
@ -311,7 +368,7 @@ state_machine:
|
|||||||
goal: "after clicking a rock (a2), wait for the mining outcome — ore gained (may take several rolls: rolls_per_ore), rock depleted, or roll timeout (2x the equipped tier's roll) — before any re-click; never re-click the active rock while its roll is unresolved; respawns of the site's rock_count rocks are absorbed here (wiki respawn figures in mine_sites)"
|
goal: "after clicking a rock (a2), wait for the mining outcome — ore gained (may take several rolls: rolls_per_ore), rock depleted, or roll timeout (2x the equipped tier's roll) — before any re-click; never re-click the active rock while its roll is unresolved; respawns of the site's rock_count rocks are absorbed here (wiki respawn figures in mine_sites)"
|
||||||
next: [mine, hop, drop_run, bank_run, recover]
|
next: [mine, hop, drop_run, bank_run, recover]
|
||||||
hop:
|
hop:
|
||||||
goal: "world_hop sites ONLY (al-kharid-south-adamantite): both target rocks are depleted -> hop_world (a14) to a fresh F2P world and continue mining its fresh rocks; hop count tracked; after 8 consecutive hops with no ore gained, go to recover (possible world lockout / price-stale)"
|
goal: "world_hop sites ONLY (al-kharid-south-adamantite): both target rocks are depleted -> hop_world (a15) to a fresh F2P world and continue mining its fresh rocks; hop count tracked; after 8 consecutive hops with no ore gained, go to recover (possible world lockout / price-stale)"
|
||||||
next: [mine, recover]
|
next: [mine, recover]
|
||||||
drop_run:
|
drop_run:
|
||||||
goal: "fast-xp ONLY: drop every occupied ore slot — one right-click Drop per slot (a6 re-executed), looping until count_item ore == 0. Slot count is DYNAMIC: inventory capacity minus non-ore items (equipped pickaxe = 28 ore slots, carried = 27, any session load = fewer) — never a hardcoded loop count"
|
goal: "fast-xp ONLY: drop every occupied ore slot — one right-click Drop per slot (a6 re-executed), looping until count_item ore == 0. Slot count is DYNAMIC: inventory capacity minus non-ore items (equipped pickaxe = 28 ore slots, carried = 27, any session load = fewer) — never a hardcoded loop count"
|
||||||
@ -320,10 +377,10 @@ state_machine:
|
|||||||
goal: "banked-income ONLY: walk to the nearest bank, deposit all ores (activity state: target row id + load value logged), walk back to the mine; the pickaxe stays (equipped or carried) and the inventory is rebuilt as empty ore space for the next load"
|
goal: "banked-income ONLY: walk to the nearest bank, deposit all ores (activity state: target row id + load value logged), walk back to the mine; the pickaxe stays (equipped or carried) and the inventory is rebuilt as empty ore space for the next load"
|
||||||
next: [mine, break_state, complete]
|
next: [mine, break_state, complete]
|
||||||
break_state:
|
break_state:
|
||||||
goal: "scheduled break independent of incidental banking: after every run_control.break.every rotations (8-14) take_break (60-180 s AFK, a15), then reposition at the cluster (a16) and resume mining"
|
goal: "scheduled break independent of incidental banking: after every run_control.break.every rotations (8-14) take_break (60-180 s AFK, a16), then reposition at the cluster (a17) and resume mining"
|
||||||
next: [mine, complete]
|
next: [mine, complete]
|
||||||
recover:
|
recover:
|
||||||
goal: "diagnose and fix: no fresh rock of the target tier for 2 respawn cycles (rotate cluster / wait respawn / hop for world_hop rows); invalid location (is_at fails — wrong mine or wrong ore) -> re-travel to the correct mine_sites location; missing tool (has_item pickaxe false) -> acquire (a8-a12) and re-prepare; path failure (move_to on_fail) -> retry travel. Persistent after 3 recoveries -> failed"
|
goal: "diagnose and fix: no fresh rock of the target tier for 2 respawn cycles (rotate cluster / wait respawn / hop for world_hop rows); invalid location (is_at fails — wrong mine or wrong ore) -> re-travel to the correct mine_sites location; missing tool (has_item pickaxe false) -> acquire (a8-a13) and re-prepare; path failure (move_to on_fail) -> retry travel. Persistent after 3 recoveries -> failed"
|
||||||
next: [prepare, travel, mine, failed]
|
next: [prepare, travel, mine, failed]
|
||||||
survive:
|
survive:
|
||||||
goal: "defensive fallback only (the 29+ gate means scorpions never aggro at Al Kharid): if attacked anyway (gate bypassed/griefed), retreat out of the aggro radius and re-enter the cluster when safe; no food loop is modeled"
|
goal: "defensive fallback only (the 29+ gate means scorpions never aggro at Al Kharid): if attacked anyway (gate bypassed/griefed), retreat out of the aggro radius and re-enter the cluster when safe; no food loop is modeled"
|
||||||
@ -421,7 +478,7 @@ state_machine:
|
|||||||
when: "session cap reached during the break"
|
when: "session cap reached during the break"
|
||||||
to: complete
|
to: complete
|
||||||
- from: recover
|
- from: recover
|
||||||
when: "tool missing -> re-acquired (a8-a12) or withdrawn from bank"
|
when: "tool missing -> re-acquired (a8-a13) or withdrawn from bank"
|
||||||
to: prepare
|
to: prepare
|
||||||
- from: recover
|
- from: recover
|
||||||
when: "wrong location -> re-routed to the correct mine_sites location"
|
when: "wrong location -> re-routed to the correct mine_sites location"
|
||||||
@ -458,7 +515,7 @@ actions:
|
|||||||
verb: click_object
|
verb: click_object
|
||||||
target: "fresh rock of the session target tier — never the rock whose roll is in progress"
|
target: "fresh rock of the session target tier — never the rock whose roll is in progress"
|
||||||
params:
|
params:
|
||||||
rock: "MODE-DRIVEN: fast-xp -> iron rock (level 15+; copper/tin below 15); banked-income -> ONLY the session's target mine_sites row (silver 20, coal 30, gold 40, mithril 55, adamantite 70) — never highest-available"
|
rock: "MODE-DRIVEN: fast-xp -> Mining 15+: iron rock (Al Kharid 3-rock / SE Varrock 2-rock); Mining 1-14: copper/tin rock at the East Varrock fallback (mine_sites se-varrock-copper / se-varrock-tin, 17.5 xp); banked-income -> ONLY the session's declared target row from mining_modes.banked-income.targets (iron @ se-varrock-bank or adamantite @ al-kharid-south-adamantite — the ONLY declared/validated banked targets; no other ore is advertised) — never highest-available"
|
||||||
gate: "level_is Mining >= the site row's mining_level (e.g. adamantite = 70), and for banked-income the rock must be at the session's validated mine_sites location"
|
gate: "level_is Mining >= the site row's mining_level (e.g. adamantite = 70), and for banked-income the rock must be at the session's validated mine_sites location"
|
||||||
mode_visible: "activity state logs mode + target row id + ore name on every rotation — the target is visible, never implicit"
|
mode_visible: "activity state logs mode + target row id + ore name on every rotation — the target is visible, never implicit"
|
||||||
rotation: "the site's rock_count cluster (Al Kharid 3-rock / SE Varrock 2-rock / adamantite 2-rock); click a fresh rock only after the wait_rock outcome wait (rolls_per_ore success model)"
|
rotation: "the site's rock_count cluster (Al Kharid 3-rock / SE Varrock 2-rock / adamantite 2-rock); click a fresh rock only after the wait_rock outcome wait (rolls_per_ore success model)"
|
||||||
@ -530,7 +587,7 @@ actions:
|
|||||||
verb: has_item
|
verb: has_item
|
||||||
target: "the selected pickaxe tier (Mining-gated: pickaxe_tiers)"
|
target: "the selected pickaxe tier (Mining-gated: pickaxe_tiers)"
|
||||||
params:
|
params:
|
||||||
branch: "owned -> a9 withdraw-tool (or straight to a13 equip-tool if already in the inventory); missing -> a10 buy-tool (GE purchase path)"
|
branch: "owned -> a9 withdraw-tool (or straight to a14 equip-tool if already in the inventory); missing -> the GE purchase branch: a10 open-ge -> a11 buy-tool -> a12 wait (bounded fill) -> a13 collect (verify)"
|
||||||
verify: "inventory holds exactly one pickaxe of the selected tier — never a second pickaxe"
|
verify: "inventory holds exactly one pickaxe of the selected tier — never a second pickaxe"
|
||||||
on_fail: skip
|
on_fail: skip
|
||||||
anti_ban:
|
anti_ban:
|
||||||
@ -548,6 +605,17 @@ actions:
|
|||||||
delay: [500, 1200]
|
delay: [500, 1200]
|
||||||
|
|
||||||
- id: a10
|
- id: a10
|
||||||
|
step: open-ge
|
||||||
|
verb: ge_open
|
||||||
|
target: grand-exchange
|
||||||
|
params:
|
||||||
|
location: "the GE booth (bank side) — REQUIRED before any ge_buy / ge_collect: the exchange interface must be open before an offer is placed or items are collected"
|
||||||
|
note: "only the purchase branch reaches the GE (a8 missing-tool); owned tools go straight to a9 withdraw-tool"
|
||||||
|
on_fail: retry
|
||||||
|
anti_ban:
|
||||||
|
delay: [600, 1600]
|
||||||
|
|
||||||
|
- id: a11
|
||||||
step: buy-tool
|
step: buy-tool
|
||||||
verb: ge_buy
|
verb: ge_buy
|
||||||
target: grand-exchange
|
target: grand-exchange
|
||||||
@ -555,32 +623,34 @@ actions:
|
|||||||
item: "the selected pickaxe tier (Mining-gated)"
|
item: "the selected pickaxe tier (Mining-gated)"
|
||||||
qty: 1
|
qty: 1
|
||||||
max_price: "GE mid + 10% cap"
|
max_price: "GE mid + 10% cap"
|
||||||
pair_with: "a11 wait-ge-fill (offer fill wait) then a12 collect-tool (collect + verify)"
|
note: "place exactly ONE buy offer; the fill waits at most the BOUNDED a12 window — a resting offer is never retried indefinitely"
|
||||||
|
pair_with: "a10 open-ge (before) then a12 wait-ge-fill (bounded) then a13 collect-tool (collect + verify)"
|
||||||
on_fail: retry
|
on_fail: retry
|
||||||
anti_ban:
|
anti_ban:
|
||||||
delay: [1200, 3000]
|
delay: [1200, 3000]
|
||||||
|
|
||||||
- id: a11
|
- id: a12
|
||||||
step: wait-ge-fill
|
step: wait-ge-fill
|
||||||
verb: ge_offers_done
|
verb: ge_offers_done
|
||||||
target: "the pickaxe purchase offer"
|
target: "the pickaxe purchase offer"
|
||||||
params:
|
params:
|
||||||
until: "the pickaxe offer fills or times out — never proceed with a pending offer"
|
until: "the pickaxe offer FILLS (has_item pickaxe) — poll for exactly ONE bounded fill window (3-6 min); on no-fill / partial-fill TIMEOUT: CANCEL the resting offer, collect the item if it finally filled or REFUND the gp (a13), then verify — fail CLOSED via recover (3 loops -> failed); never re-place the same resting offer"
|
||||||
on_fail: retry
|
on_fail: alert
|
||||||
anti_ban:
|
anti_ban:
|
||||||
delay: [900, 2400]
|
delay: [900, 2400]
|
||||||
|
|
||||||
- id: a12
|
- id: a13
|
||||||
step: collect-tool
|
step: collect-tool
|
||||||
verb: ge_collect
|
verb: ge_collect
|
||||||
target: grand-exchange
|
target: grand-exchange
|
||||||
params:
|
params:
|
||||||
verify: "has_item pickaxe == true after collection; otherwise recover (a8 path) — a failed purchase or equip is diagnosed, never assumed"
|
collect: "finished GE transactions — the bought pickaxe if the offer filled, and the gp refund if it was cancelled on timeout; collection closes the offer slot"
|
||||||
|
verify: "has_item pickaxe == true after collection; if still missing (no-fill / cancelled), diagnose via recover (a8 path, 3 loops -> failed) — a failed purchase is diagnosed, never silently re-queued"
|
||||||
on_fail: retry
|
on_fail: retry
|
||||||
anti_ban:
|
anti_ban:
|
||||||
delay: [600, 1400]
|
delay: [600, 1400]
|
||||||
|
|
||||||
- id: a13
|
- id: a14
|
||||||
step: equip-tool
|
step: equip-tool
|
||||||
verb: menu_option
|
verb: menu_option
|
||||||
target: "the selected pickaxe tier in the inventory"
|
target: "the selected pickaxe tier in the inventory"
|
||||||
@ -591,7 +661,7 @@ actions:
|
|||||||
anti_ban:
|
anti_ban:
|
||||||
delay: [600, 1400]
|
delay: [600, 1400]
|
||||||
|
|
||||||
- id: a14
|
- id: a15
|
||||||
step: hop-world
|
step: hop-world
|
||||||
verb: hop_world
|
verb: hop_world
|
||||||
target: "a fresh F2P world"
|
target: "a fresh F2P world"
|
||||||
@ -602,7 +672,7 @@ actions:
|
|||||||
anti_ban:
|
anti_ban:
|
||||||
delay: [900, 2200]
|
delay: [900, 2200]
|
||||||
|
|
||||||
- id: a15
|
- id: a16
|
||||||
step: take-break
|
step: take-break
|
||||||
verb: take_break
|
verb: take_break
|
||||||
target: "self"
|
target: "self"
|
||||||
@ -613,7 +683,7 @@ actions:
|
|||||||
anti_ban:
|
anti_ban:
|
||||||
delay: [300, 900]
|
delay: [300, 900]
|
||||||
|
|
||||||
- id: a16
|
- id: a17
|
||||||
step: reposition-cluster
|
step: reposition-cluster
|
||||||
verb: walk_to
|
verb: walk_to
|
||||||
target: "cluster center / fresh rock of the target tier"
|
target: "cluster center / fresh rock of the target tier"
|
||||||
@ -629,11 +699,12 @@ run_control:
|
|||||||
max_iterations: null
|
max_iterations: null
|
||||||
break:
|
break:
|
||||||
every: [8, 14] # rotations; the break counter is independent of incidental banking and hops
|
every: [8, 14] # rotations; the break counter is independent of incidental banking and hops
|
||||||
for: [60, 180] # seconds of idle AFK (take_break, a15)
|
for: [60, 180] # seconds of idle AFK (take_break, a16)
|
||||||
stop_conditions:
|
stop_conditions:
|
||||||
- "fast-xp: Mining XP/level target reached (session target); banked-income: banked GP target reached or session cap"
|
- "fast-xp: Mining XP/level target reached (session target); banked-income: banked GP target reached or session cap"
|
||||||
- "3 consecutive failed rock clicks (client issue — do not loop)"
|
- "3 consecutive failed rock clicks (client issue — do not loop)"
|
||||||
- "recover looped 3 times: persistent missing tool, invalid location, or path failure"
|
- "recover looped 3 times: persistent missing tool, invalid location, or path failure"
|
||||||
|
- "GE purchase fail-closed: the bounded fill window expired and the tool is still missing after cancel/refund/collect (recover looped 3 times) — never re-place a resting buy offer"
|
||||||
- "death: hard failure — the Al Kharid hard gate (combat 29+) and the survive (retreat) fallback prevent it in normal operation; if is_dead anyway (gate bypassed/griefed) log ERROR + alert and stop — no respawn loop"
|
- "death: hard failure — the Al Kharid hard gate (combat 29+) and the survive (retreat) fallback prevent it in normal operation; if is_dead anyway (gate bypassed/griefed) log ERROR + alert and stop — no respawn loop"
|
||||||
|
|
||||||
risk:
|
risk:
|
||||||
@ -642,13 +713,17 @@ risk:
|
|||||||
- "Mining is a staple low-risk method: long, repetitive, low-input behaviour that matches normal player sessions — the guide itself recommends hours of drop-mining."
|
- "Mining is a staple low-risk method: long, repetitive, low-input behaviour that matches normal player sessions — the guide itself recommends hours of drop-mining."
|
||||||
- "The powermine rotation is the detection vector if executed perfectly for hours — keep the a2 tier-aware cadence (wait_rock outcome wait + roll_table pause; anchor rune 1.8-3.6 s, never below the equipped tier's full roll) and take the break schedule."
|
- "The powermine rotation is the detection vector if executed perfectly for hours — keep the a2 tier-aware cadence (wait_rock outcome wait + roll_table pause; anchor rune 1.8-3.6 s, never below the equipped tier's full roll) and take the break schedule."
|
||||||
- "Al Kharid mine has aggressive level-14 scorpions (they attack players at combat level <= 28 — wiki Aggressiveness). The entry HARD-gates Al Kharid to combat 29+; sub-29 accounts run fast-xp at the South-east Varrock DROP site (no aggressive NPCs, same mode). No food is part of either route; the survive state (retreat) is a defensive fallback only."
|
- "Al Kharid mine has aggressive level-14 scorpions (they attack players at combat level <= 28 — wiki Aggressiveness). The entry HARD-gates Al Kharid to combat 29+; sub-29 accounts run fast-xp at the South-east Varrock DROP site (no aggressive NPCs, same mode). No food is part of either route; the survive state (retreat) is a defensive fallback only."
|
||||||
|
- "Below-15 fast-xp stays at the safe East Varrock copper/tin rocks (se-varrock-copper / se-varrock-tin — no aggressive NPCs), so no food or combat gate applies; the mode is unchanged (drop every load)."
|
||||||
- "World hopping (adamantite row only) is pace-sensitive: hop at the depletion trigger, not on a timer, and back off after 8 fruitless hops. The modelled 120 ores/hr is the wiki's hopping baseline — never claim it without the hop policy."
|
- "World hopping (adamantite row only) is pace-sensitive: hop at the depletion trigger, not on a timer, and back off after 8 fruitless hops. The modelled 120 ores/hr is the wiki's hopping baseline — never claim it without the hop policy."
|
||||||
- "Bottom line on rates: 28,000 XP/hr (fast-xp) and 70,080 gp/hr (adamantite w/ hop) are this entry's modelled policy rates derived in economy; the wiki's 52,500 XP/hr is a labeled external benchmark, not an achieved rate."
|
- "Bottom line on rates: 28,000 XP/hr (fast-xp iron 15+) and 6,300 XP/hr (fast-xp copper/tin below 15) are this entry's modelled fast-xp policy rates; 70,080 gp/hr (adamantite w/ hop) is the banked-income modelled rate — all derived in economy; the wiki's 52,500 XP/hr is a labeled external benchmark, not an achieved rate."
|
||||||
|
|
||||||
sources:
|
sources:
|
||||||
- "OSRS wiki — Active/passive aggressive monsters: Aggressiveness (a monster attacks players whose combat level is <= 2x its level; a level-14 scorpion is safe from combat level 29) — verified 2026-08-27"
|
- "OSRS wiki — Active/passive aggressive monsters: Aggressiveness (a monster attacks players whose combat level is <= 2x its level; a level-14 scorpion is safe from combat level 29) — verified 2026-08-27"
|
||||||
- "OSRS wiki — Scorpion (combat level 14, hitpoints 17; Al Kharid mine) — verified 2026-08-27"
|
- "OSRS wiki — Scorpion (combat level 14, hitpoints 17; Al Kharid mine) — verified 2026-08-27"
|
||||||
- "OSRS wiki — Free-to-play Mining training (ore level/xp table — all rows F2P; pickaxe tier table with tick intervals (bronze 8 -> rune 3); Doric's Quest 1,300 xp; iron 50,000 xp/hr at 41+ / 52,500 at 61+ cited as zero-overhead external benchmarks only — the configured midpoint cadence caps the ideal at ~46,667; Al Kharid 3-rock spot; SE Varrock banking; Superheat coal; scorpions noted — this entry hard-gates the mine to combat 29+ instead, so food is not modeled) — verified 2026-08-27"
|
- "OSRS wiki — Free-to-play Mining training (ore level/xp table — all rows F2P; pickaxe tier table with tick intervals (bronze 8 -> rune 3); Doric's Quest 1,300 xp; iron 50,000 xp/hr at 41+ / 52,500 at 61+ cited as zero-overhead external benchmarks only — the configured midpoint cadence caps the ideal at ~46,667; Al Kharid 3-rock spot; SE Varrock banking; Superheat coal; scorpions noted — this entry hard-gates the mine to combat 29+ instead, so food is not modeled) — verified 2026-08-27"
|
||||||
|
- "OSRS wiki — Copper ore / Tin ore (level 1, 17.5 XP each, F2P) — the below-15 fast-xp fallback rows (se-varrock-copper / se-varrock-tin) — verified 2026-08-28"
|
||||||
|
- "OSRS wiki — East of Varrock mine (copper/tin/iron rocks; no aggressive NPCs) — the safe below-15 and sub-29 fast-xp/SE Varrock location — verified 2026-08-28"
|
||||||
|
- "OSRS wiki — Grand Exchange (buy offers: place at mid, cancel/refund on timeout) — a10-a13 purchase loop — wiki mechanics, verified 2026-08-28"
|
||||||
- "OSRS wiki — Money making guide/Mining adamantite ore (F2P) (4-minute respawn; about 120+ ores/hour by hopping worlds only; at the committed 584 gp that is <=17,520 gp/hr without hopping or ~70,080 gp/hr at 120 ores/hr) — verified 2026-08-28"
|
- "OSRS wiki — Money making guide/Mining adamantite ore (F2P) (4-minute respawn; about 120+ ores/hour by hopping worlds only; at the committed 584 gp that is <=17,520 gp/hr without hopping or ~70,080 gp/hr at 120 ores/hr) — verified 2026-08-28"
|
||||||
- "OSRS wiki — Iron rocks (respawn approximately 5.4 seconds) — verified 2026-08-28"
|
- "OSRS wiki — Iron rocks (respawn approximately 5.4 seconds) — verified 2026-08-28"
|
||||||
- "OSRS wiki — Runite ore (respawn about twelve minutes; F2P rocks in the Wilderness) — verified 2026-08-28"
|
- "OSRS wiki — Runite ore (respawn about twelve minutes; F2P rocks in the Wilderness) — verified 2026-08-28"
|
||||||
|
|||||||
@ -123,6 +123,26 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"mining_selections": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"fast_xp": {
|
||||||
|
"type": "array",
|
||||||
|
"minItems": 1,
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"required": ["level", "expected_site"],
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"level": { "type": "integer", "minimum": 1, "maximum": 126 },
|
||||||
|
"expected_site": { "type": "string", "minLength": 2 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
"mine_sites": {
|
"mine_sites": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"minProperties": 1,
|
"minProperties": 1,
|
||||||
|
|||||||
@ -92,6 +92,25 @@ def select_pickaxe(mining_level, tiers):
|
|||||||
return best
|
return best
|
||||||
|
|
||||||
|
|
||||||
|
def select_fast_site(mining_level, modes, sites):
|
||||||
|
"""Deterministic fast-xp site selection (mining_selections recompute):
|
||||||
|
highest ore XP among eligible selectable fast-xp sites whose
|
||||||
|
mining_level <= level; tie-break lexicographic site id (copper/tin share
|
||||||
|
an XP+level tie). Returns the site id or None."""
|
||||||
|
best_xp, cands = -1, []
|
||||||
|
for sid in (modes.get("fast-xp", {}).get("sites", []) or []):
|
||||||
|
sdef = sites.get(sid)
|
||||||
|
if not isinstance(sdef, dict) or sdef.get("selectable") is not True:
|
||||||
|
continue
|
||||||
|
ml, xp = sdef.get("mining_level"), sdef.get("xp")
|
||||||
|
if isinstance(ml, int) and isinstance(xp, (int, float)) and ml <= mining_level:
|
||||||
|
if xp > best_xp:
|
||||||
|
best_xp, cands = xp, [sid]
|
||||||
|
elif xp == best_xp:
|
||||||
|
cands.append(sid)
|
||||||
|
return sorted(cands)[0] if cands else None
|
||||||
|
|
||||||
|
|
||||||
def mining_model_errors(rel, data):
|
def mining_model_errors(rel, data):
|
||||||
"""STRUCTURED mining-model gates (owner guidance 2026-08-28; replaces the
|
"""STRUCTURED mining-model gates (owner guidance 2026-08-28; replaces the
|
||||||
earlier phrase-search checks, which could pass on comments alone)."""
|
earlier phrase-search checks, which could pass on comments alone)."""
|
||||||
@ -230,6 +249,88 @@ def mining_model_errors(rel, data):
|
|||||||
f"(3600 / (rolls_per_ore x 2.7 s)) — the rate exceeds what "
|
f"(3600 / (rolls_per_ore x 2.7 s)) — the rate exceeds what "
|
||||||
f"the declared click policy can produce")
|
f"the declared click policy can produce")
|
||||||
|
|
||||||
|
# --- 4b. GE tool purchase must be executable end to end ---
|
||||||
|
gev = set(v for v in verbs if v in {
|
||||||
|
"ge_open", "ge_buy", "ge_offers_done", "ge_collect", "ge_sell"})
|
||||||
|
if "ge_buy" in gev:
|
||||||
|
for must, why in (("ge_open", "open the exchange before placing an offer"),
|
||||||
|
("ge_offers_done", "wait one BOUNDED fill window"),
|
||||||
|
("ge_collect", "collect the item / refund the gp on timeout")):
|
||||||
|
if must not in gev:
|
||||||
|
errors.append(
|
||||||
|
f"{rel}: ge_buy must be part of an executable GE loop — "
|
||||||
|
f"missing '{must}' ({why}); a resting offer must never be "
|
||||||
|
f"retried indefinitely")
|
||||||
|
elif gev:
|
||||||
|
if "ge_open" not in gev:
|
||||||
|
errors.append(
|
||||||
|
f"{rel}: GE verbs {sorted(gev)} require a ge_open action — "
|
||||||
|
f"the GE flow must start by opening the exchange")
|
||||||
|
|
||||||
|
# --- 4c. below-15 copper/tin path must be structurally arming-able ---
|
||||||
|
min_level = (data.get("accounts") or {}).get("min_level")
|
||||||
|
fx_levels = []
|
||||||
|
for sid in (modes.get("fast-xp", {}).get("sites", []) or []):
|
||||||
|
sdef = sites.get(sid)
|
||||||
|
if isinstance(sdef, dict) and sdef.get("selectable") is True:
|
||||||
|
ml = sdef.get("mining_level")
|
||||||
|
if isinstance(ml, int):
|
||||||
|
fx_levels.append(ml)
|
||||||
|
if isinstance(min_level, int) and min_level < 15:
|
||||||
|
if not fx_levels:
|
||||||
|
errors.append(
|
||||||
|
f"{rel}: min_level {min_level} (<15) but fast-xp has no "
|
||||||
|
f"structured selectable site")
|
||||||
|
else:
|
||||||
|
fmin = min(fx_levels)
|
||||||
|
if fmin > 14:
|
||||||
|
errors.append(
|
||||||
|
f"{rel}: fast-xp sites all require Mining >= {fmin} but "
|
||||||
|
f"the entry claims a copper/tin below-15 path (min_level "
|
||||||
|
f"{min_level}) — add a structured low-level (<=14) "
|
||||||
|
f"fallback site or raise min_level")
|
||||||
|
if fmin > min_level:
|
||||||
|
errors.append(
|
||||||
|
f"{rel}: the lowest fast-xp site requires Mining {fmin} "
|
||||||
|
f"but min_level is {min_level} — a level-{min_level} "
|
||||||
|
f"account cannot arm a fast-xp run")
|
||||||
|
|
||||||
|
# --- 4d. mining_selections pins (deterministic, recomputed) ---
|
||||||
|
sel = data.get("mining_selections")
|
||||||
|
if not isinstance(sel, dict) or not isinstance(sel.get("fast_xp"), list) \
|
||||||
|
or not sel["fast_xp"]:
|
||||||
|
errors.append(
|
||||||
|
f"{rel}: mining entries must declare mining_selections.fast_xp "
|
||||||
|
f"(level -> expected_site pins, recomputed by the validator)")
|
||||||
|
else:
|
||||||
|
rows = {}
|
||||||
|
for r in sel["fast_xp"]:
|
||||||
|
lvl = r.get("level") if isinstance(r, dict) else None
|
||||||
|
if not isinstance(lvl, int) or lvl < 1:
|
||||||
|
errors.append(
|
||||||
|
f"{rel}: mining_selections.fast_xp rows need a positive "
|
||||||
|
f"integer 'level'")
|
||||||
|
continue
|
||||||
|
rows[lvl] = r
|
||||||
|
if isinstance(min_level, int) and min_level <= 14:
|
||||||
|
for lvl in (1, 14):
|
||||||
|
if lvl not in rows:
|
||||||
|
errors.append(
|
||||||
|
f"{rel}: mining_selections.fast_xp must pin level "
|
||||||
|
f"{lvl} (a below-15 account must have a structured, "
|
||||||
|
f"selectable fast-xp site)")
|
||||||
|
for lvl, r in rows.items():
|
||||||
|
got = select_fast_site(lvl, modes, sites)
|
||||||
|
if got is None:
|
||||||
|
errors.append(
|
||||||
|
f"{rel}: no eligible selectable fast-xp site at level "
|
||||||
|
f"{lvl} — the low-level (copper/tin) fallback is missing")
|
||||||
|
elif r.get("expected_site") != got:
|
||||||
|
errors.append(
|
||||||
|
f"{rel}: mining_selections level {lvl} expects site "
|
||||||
|
f"'{r.get('expected_site')}' but the selection rule "
|
||||||
|
f"picks '{got}'")
|
||||||
|
|
||||||
# --- 5. fast-xp headline xp rate consistent with the modelled sites ---
|
# --- 5. fast-xp headline xp rate consistent with the modelled sites ---
|
||||||
eco = data.get("economy")
|
eco = data.get("economy")
|
||||||
xph = eco.get("xp_per_hour") if isinstance(eco, dict) else None
|
xph = eco.get("xp_per_hour") if isinstance(eco, dict) else None
|
||||||
@ -291,6 +392,16 @@ def run_selftest(verbose=False):
|
|||||||
"modeled_ores_per_hour": 803, "world_hop": False, "selectable": True,
|
"modeled_ores_per_hour": 803, "world_hop": False, "selectable": True,
|
||||||
"inventory_policy": "drop", "access": "combat 29+", "safety": "gate",
|
"inventory_policy": "drop", "access": "combat 29+", "safety": "gate",
|
||||||
"route": "drop in place"},
|
"route": "drop in place"},
|
||||||
|
"se-varrock-copper": {"ore": "Copper ore", "ore_id": 436, "mining_level": 1,
|
||||||
|
"xp": 17.5, "rock_count": 2, "respawn_seconds": 5.4, "rolls_per_ore": 1.6,
|
||||||
|
"modeled_ores_per_hour": 360, "world_hop": False, "selectable": True,
|
||||||
|
"inventory_policy": "drop", "access": "safe", "safety": "none",
|
||||||
|
"route": "drop in place"},
|
||||||
|
"se-varrock-tin": {"ore": "Tin ore", "ore_id": 438, "mining_level": 1,
|
||||||
|
"xp": 17.5, "rock_count": 2, "respawn_seconds": 5.4, "rolls_per_ore": 1.6,
|
||||||
|
"modeled_ores_per_hour": 360, "world_hop": False, "selectable": True,
|
||||||
|
"inventory_policy": "drop", "access": "safe", "safety": "none",
|
||||||
|
"route": "drop in place"},
|
||||||
"se-varrock-bank": {"ore": "Iron ore", "ore_id": 440, "mining_level": 15,
|
"se-varrock-bank": {"ore": "Iron ore", "ore_id": 440, "mining_level": 15,
|
||||||
"xp": 35, "rock_count": 2, "respawn_seconds": 5.4, "rolls_per_ore": 1.33,
|
"xp": 35, "rock_count": 2, "respawn_seconds": 5.4, "rolls_per_ore": 1.33,
|
||||||
"modeled_ores_per_hour": 713, "world_hop": False, "selectable": True,
|
"modeled_ores_per_hour": 713, "world_hop": False, "selectable": True,
|
||||||
@ -302,14 +413,20 @@ def run_selftest(verbose=False):
|
|||||||
"selectable": True, "inventory_policy": "bank", "access": "south rocks",
|
"selectable": True, "inventory_policy": "bank", "access": "south rocks",
|
||||||
"safety": "banked locally", "route": "bank 25s + hop_world"},
|
"safety": "banked locally", "route": "bank 25s + hop_world"},
|
||||||
}
|
}
|
||||||
good = {"pickaxe_tiers": canon, "pickaxe_examples": good_examples,
|
good = {"accounts": {"min_level": 1},
|
||||||
|
"pickaxe_tiers": canon, "pickaxe_examples": good_examples,
|
||||||
"mining_modes": {"fast-xp": {"inventory_policy": "drop",
|
"mining_modes": {"fast-xp": {"inventory_policy": "drop",
|
||||||
"ore_policy": "iron 15+",
|
"ore_policy": "iron 15+ / copper/tin under 15",
|
||||||
"sites": ["al-kharid-powermine"]},
|
"sites": ["al-kharid-powermine",
|
||||||
|
"se-varrock-copper",
|
||||||
|
"se-varrock-tin"]},
|
||||||
"banked-income": {"inventory_policy": "bank",
|
"banked-income": {"inventory_policy": "bank",
|
||||||
"targets": ["se-varrock-bank",
|
"targets": ["se-varrock-bank",
|
||||||
"al-kharid-south-adamantite"],
|
"al-kharid-south-adamantite"],
|
||||||
"stop": "gp target"}},
|
"stop": "gp target"}},
|
||||||
|
"mining_selections": {"fast_xp": [
|
||||||
|
{"level": 1, "expected_site": "se-varrock-copper"},
|
||||||
|
{"level": 14, "expected_site": "se-varrock-copper"}]},
|
||||||
"mine_sites": sites,
|
"mine_sites": sites,
|
||||||
"actions": [{"id": "a1", "step": "hop-world", "verb": "hop_world",
|
"actions": [{"id": "a1", "step": "hop-world", "verb": "hop_world",
|
||||||
"on_fail": "retry"}],
|
"on_fail": "retry"}],
|
||||||
@ -396,6 +513,33 @@ def run_selftest(verbose=False):
|
|||||||
check("xp_per_hour 28,000 within 2% of the modelled fast-xp rate 28,105 passes",
|
check("xp_per_hour 28,000 within 2% of the modelled fast-xp rate 28,105 passes",
|
||||||
errs == [])
|
errs == [])
|
||||||
|
|
||||||
|
# below-15 fallback + mining_selections pins (governor bounce 5)
|
||||||
|
no_fallback = {**good, "mining_modes": {
|
||||||
|
"fast-xp": {"inventory_policy": "drop", "ore_policy": "iron 15+ only",
|
||||||
|
"sites": ["al-kharid-powermine"]},
|
||||||
|
"banked-income": {"inventory_policy": "bank", "targets": ["se-varrock-bank",
|
||||||
|
"al-kharid-south-adamantite"], "stop": "gp target"}}}
|
||||||
|
errs = mining_model_errors("f14.yaml", no_fallback)
|
||||||
|
check("min_level 1 with iron-only fast-xp sites (no copper/tin fallback) is rejected",
|
||||||
|
any("below-15" in e for e in errs))
|
||||||
|
wrongpin = {**good, "mining_selections": {"fast_xp": [
|
||||||
|
{"level": 1, "expected_site": "se-varrock-tin"},
|
||||||
|
{"level": 14, "expected_site": "se-varrock-copper"}]}}
|
||||||
|
errs = mining_model_errors("f15.yaml", wrongpin)
|
||||||
|
check("mining_selections level-1 expected site mismatching the recomputed selection is rejected",
|
||||||
|
any("selection rule picks" in e for e in errs))
|
||||||
|
no_pin14 = {**good, "mining_selections": {"fast_xp": [
|
||||||
|
{"level": 1, "expected_site": "se-varrock-copper"}]}}
|
||||||
|
errs = mining_model_errors("f16.yaml", no_pin14)
|
||||||
|
check("mining_selections missing the level-14 pin is rejected when min_level < 15",
|
||||||
|
any("pin level 14" in e for e in errs))
|
||||||
|
ge_no_open = {**good, "actions": [
|
||||||
|
{"id": "a1", "step": "buy-pick", "verb": "ge_buy", "on_fail": "retry"},
|
||||||
|
{"id": "a2", "step": "hop-world", "verb": "hop_world", "on_fail": "retry"}]}
|
||||||
|
errs = mining_model_errors("f17.yaml", ge_no_open)
|
||||||
|
check("ge_buy without ge_open / ge_offers_done / ge_collect is rejected",
|
||||||
|
any("ge_open" in e for e in errs))
|
||||||
|
|
||||||
return errors
|
return errors
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user