Client-agnostic source of truth for everything botable in OSRS: activities, ordering, actions, requirements. AI agents translate entries into client APIs.
Go to file
Claude a0b03b87c6 codex: mining-f2p — level-1 pickaxe tie-break: Mining 1 selects+equips iron (bounce-fix attempt 6)
Owner guidance 2026-08-29 for governor review 10476 (PR #11), finding by finding:

1. Explicit tier rank/tie-break for equal Mining gates. pickaxe_tiers
   declared bronze and iron both at Mining 1 / Attack 1 while the
   level-1 worked example called bronze canonical and carried it (27
   slots) — internally contradictory under the entry's own
   highest-unlocked acquisition policy. pickaxe_tiers now carries an
   explicit rank (bronze 1 .. rune 6) and the selection rule resolves
   equal Mining gates by rank: Mining 1 deterministically selects IRON
   (7-tick roll, rank 2) over bronze (rank 1), and Attack 1 EQUIPS it
   (iron attack gate = 1) -> 28 ore slots. Stated at every policy
   layer (summary, accounts.requires_other, best_practice.equipment,
   prepare state, economy.supplies, a14 equip-tool gate, pickaxe_tiers
   head comment). An owned-only bronze run is documented as an operator
   choice, never the entry's selection rule.

2. Level-1 lifecycle/rate inputs recomputed. The level-1 worked
   example now uses the equipped iron pickaxe: 28 ore slots per drop
   load, iron cadence [4200, 6000] ms (midpoint 5.1 s), and the
   copper/tin rate re-derived from that cadence: 1.6 rolls x 5.1 + 0.5
   drop + 0.39 break = 9.05 s/ore -> 398 ores/hr -> ~6,960 XP/hr (pin
   6,900), replacing the bronze-midpoint 360 ores/hr / 6,300 XP/hr.
   Updated in mine_sites (se-varrock-copper / se-varrock-tin),
   economy comment block, profit_drivers, worktree example, and risk
   notes; no other rate changes (fast-xp iron 28,000 and banked rates
   untouched).

3. Recomputed 1-Attack/1-Mining fixture + capacity proof. Schema:
   pickaxe_tiers gains required rank (1..6); pickaxe_examples gain
   required expected_slots (28 equipped / 27 carried). Validator:
   select_pickaxe() ties by rank; every pickaxe_examples row is
   recomputed including expected_slots, the 1-Attack/41-Mining
   rune-carry fixture is preserved, and the 1-Attack/1-Mining row is
   now mandatory (selects iron, equipped, 28). Committed negative
   fixtures f18-f22: bronze-at-Mining-1, carried-at-Attack-1, wrong
   slots, missing 1/1 fixture, and a tier missing rank are all
   rejected (22 selftests pass).

Preserved: complete GE tool acquisition loop, structured copper/tin
below-15 fallback, fast-xp/banked-income modes, dynamic 27/28
inventory handling, declared banked targets, respawn/world-hop model,
and all prior rate gates. version 6 -> 7, updated 2026-08-29.

Gate: python3 tools/validate.py -> 2 entries, 0 errors, 1 pre-existing
F2P WARN (low-alch-f2p researched, untouched); --selftest -> 22 PASS;
git diff --check clean.
2026-08-29 03:12:40 -05:00
codex codex: mining-f2p — level-1 pickaxe tie-break: Mining 1 selects+equips iron (bounce-fix attempt 6) 2026-08-29 03:12:40 -05:00
docs Codex skeleton: schema contract, action grammar, data-sources rules, JSON schema, validator, golden example (low-alch-f2p, wiki+price verified), README 2026-08-27 02:59:55 -05:00
schemas codex: mining-f2p — level-1 pickaxe tie-break: Mining 1 selects+equips iron (bounce-fix attempt 6) 2026-08-29 03:12:40 -05:00
tools codex: mining-f2p — level-1 pickaxe tie-break: Mining 1 selects+equips iron (bounce-fix attempt 6) 2026-08-29 03:12:40 -05:00
README.md Codex skeleton: schema contract, action grammar, data-sources rules, JSON schema, validator, golden example (low-alch-f2p, wiki+price verified), README 2026-08-27 02:59:55 -05:00

OSRS Codex

One source of truth for everything that can be botted in OSRS.

Every bot-able activity — alching, mining, slayer, bosses, trading — is described here once, in a strict client-agnostic YAML structure: requirements, execution order (state machine), the exact action sequence, economics, best-in-class setup, and anti-ban notes.

AI agents building scripts do not re-learn the game. They read a codex entry and translate it into the target client API (DreamBot / Microbot / Storm / RuneLite plugins / …). The game knowledge lives in this repo; the client glue lives in whatever script is being written.

client-agnostic                client-specific (NOT in this repo)
+----------------+             +-------------------+
| codex entry    |  translate  | DreamBot Java     |
| (YAML, strict) |  ---------> | Microbot JS       |
| actions: verbs |             | RuneLite plugin   |
+----------------+             +-------------------+

Layout

codex/<domain>/<entry-id>.yaml   # one entry per activity
  economy/       trading, alching, flipping
  training/      skill grinds (magic, mining, woodcutting, ...)
  combat/        bosses
  combat-slayers/
  quests/        quest entries (referenced by requires_quest)
  transport/     teleport/teleport-reach recipes (shared by many entries)
  meta/          account rotation, world hopping, break scheduling
docs/schema.md         # the entry contract (read this first)
docs/action-grammar.md # the universal verb vocabulary
docs/data-sources.md   # where every fact must come from + how to verify
schemas/entry.schema.json
tools/validate.py      # the gate: python3 tools/validate.py (must exit 0)

The rules (short version)

  1. One entry = one activity. State machine + action list, both mandatory.
  2. Every fact carries a source. Wiki-cited or researched <date> (a TODO: follow-up issue must land the proper citation). Live prices are re-verified against prices.runescape.wiki on every bump.
  3. Best-in-class setup is mandatory (best_practice). Top-operator execution: staff of fire for alchemy, noted items, shortest routes. Translators adopt it by default; deviating requires improvised: true.
  4. Anti-ban is first-class. Every action declares delay bounds and movement style; entries carry risk.ban_level + notes.
  5. The gate must pass before a PR merges: python3 tools/validate.py.
  6. Never mix in client knowledge. No DreamBot/Microbot/Storm API names in entries. Translations live in script repos, referencing the entry id.

Entry lifecycle

draft → verified (all facts sourced, prices re-checked, validator clean) → stale (facts > 30d old or prices moved materially). Stale entries are skipped by translators unless explicitly allowed.

Contributing

This repo is issue-driven: all content is specified in Gitea issues (acceptance criteria + source URLs + expected output path), implemented in branches, and gated by tools/validate.py in CI. No direct pushes.