A successful sell followed sell-filled-awaiting-collect -> closed, and 'closed' had no outgoing transition while the scheduler left closed slots untouched — every GE slot could perform ONE flip and then became permanently unusable (no rotations, breaks, or longer sessions). Fix (finding-by-finding, governor comment 10471): 1. 'closed' is no longer a sink. The completed cycle's ledger is reconciled and ARCHIVED at close, and the physical slot is released to free via the explicit archival transition closed -> free (flip-candidates.yaml slot_transitions, whens, scheduler_iteration, a9 archive step, summary, risk, sources). The scheduler pass dispatches the release (SLOT_DISPATCH['closed'] = 'release'), so a closed slot is only ever transient. 2. A deliberately closed cancelled sell releases identically: sell-cancelled-awaiting-collect -> closed -> free (whens updated). 3. Committed two-rotation regression (validator, wired into ge_lifecycle_errors for every flipping entry): slot_reuse_violations walks one physical slot through free -> buy-open -> buy-filled-awaiting-collect -> ready-to-sell -> sell-open -> sell-filled-awaiting-collect -> closed -> free -> buy-open (second buy in the SAME slot), validating every ledger frame against both conservation gates; archived_ledger_preserved_after_second_buy proves the rotation-1 archived ledger survives rotation 2 bit-for-bit (no loss, duplication, or mutation). Negative fixtures prove a closed sink or a closed that does not release to free FAILS. 4. ge_lifecycle_errors now requires closed == ['free'] exactly and rejects any machine where a state has no transitions. 5. Worked example: t5/t8 walk the release, t8b runs rotation 2 in the same physical slots. All prior fixtures preserved (tax x4, async-slot scheduler, collection-box, limit-window, side-aware conservation x25) — now 35 selftest checks. Evidence: python3 tools/validate.py -> 2 entries, 0 errors, 1 pre-existing warning; --selftest -> 35 PASS, 0 errors; git diff --check clean.
142 lines
8.7 KiB
Markdown
142 lines
8.7 KiB
Markdown
# OSRS Codex — Universal Action Grammar
|
|
|
|
The action grammar is the **bridge** between codex entries (client-agnostic)
|
|
and real scripts (client-specific). An entry never names a client API; it
|
|
uses a **verb** from this file. Each agent maintains the mapping table for
|
|
its own client.
|
|
|
|
A `verb` is one primitive, atomic capability. Compound behaviour is built by
|
|
chaining verbs in the entry's `actions[]` list and wiring the state machine.
|
|
|
|
Legend for the mapping table:
|
|
- `DB` = DreamBot (tblkit / OSBot-style Java)
|
|
- `MB` = Microbot
|
|
- `RL` = RuneLite plugin
|
|
- `—` = not expressible as a single primitive; entry should decompose.
|
|
|
|
> Columns are filled by each client owner as their client support lands.
|
|
> `—` is a legal value: it means "decompose into smaller verbs."
|
|
|
|
---
|
|
|
|
## A. World / presence
|
|
|
|
| verb | meaning | DB | MB | RL |
|
|
|-----------------|------------------------------------------------|--------------|-------------|----|
|
|
| `login` | authenticate the account | — | — | — |
|
|
| `select_world` | join a specific world by id/type | — | — | — |
|
|
| `hop_world` | switch worlds (F2P or P2P hop) | — | — | — |
|
|
| `is_logged_in` | predicate: authenticated & in-game | — | — | — |
|
|
|
|
## B. Movement
|
|
|
|
| verb | meaning | DB | MB | RL |
|
|
|-----------------|--------------------------------------------------|----|----|----|
|
|
| `move_to` | get to a named location (teleport-or-walk) | — | — | — |
|
|
| `walk_to` | path-walk to a tile | — | — | — |
|
|
| `teleport` | use a teleport (spell/item/scroll/portal) | — | — | — |
|
|
| `enter_region` | assert we are inside a named area (predicate) | — | — | — |
|
|
| `open_door` | open/lock an interactable door | — | — | — |
|
|
|
|
## C. Interaction (the core)
|
|
|
|
| verb | meaning | DB | MB | RL |
|
|
|--------------------|----------------------------------------------------|----|----|----|
|
|
| `use_item_on` | use inventory item `X` on target `Y` (or itself) | — | — | — |
|
|
| `click_object` | left-click a world object (NPC/NPC tile/thing) | — | — | — |
|
|
| `right_click` | click a specific menu option on a target | — | — | — |
|
|
| `talk_to` | open an NPC dialogue and pick a line | — | — | — |
|
|
| `click_button` | click a UI widget by stable reference | — | — | — |
|
|
| `menu_option` | select from an in-game menu (F-keys, menus) | — | — | — |
|
|
|
|
## D. Inventory / bank
|
|
|
|
| verb | meaning | DB | MB | RL |
|
|
|--------------------|----------------------------------------------------|----|----|----|
|
|
| `bank_inventory` | open bank, deposit/withdraw per params, close | — | — | — |
|
|
| `deposit_all` | deposit every bankable item | — | — | — |
|
|
| `withdraw` | withdraw a named item up to a quantity | — | — | — |
|
|
| `has_item` | predicate: inventory holds item ≥ qty | — | — | — |
|
|
| `count_item` | read inventory quantity of an item | — | — | — |
|
|
| `move_to_inv` | move item from bank/ground into inventory | — | — | — |
|
|
| `sort_inventory` | reorder inventory into a known layout | — | — | — |
|
|
|
|
## E. Exchange (Grand Exchange)
|
|
|
|
| verb | meaning | DB | MB | RL |
|
|
|--------------------|----------------------------------------------------|----|----|----|
|
|
| `ge_open` | open GE at a bank | — | — | — |
|
|
| `ge_buy` | buy `qty` of `item` at offer price, paced | — | — | — |
|
|
| `ge_sell` | sell `qty` of `item`, confirm | — | — | — |
|
|
| `ge_cancel` | abort an offer (quote_age_policy only — stale edge or strategy reallocation, never a 4h limit-window reset): BUY — filled items + refunded CASH (unspent remainder) enter the GE COLLECTION BOX; SELL — unsold units + proceeds received so far enter the box; NEVER directly to inventory; the 4h buy limit is NOT renewed | — | — | — |
|
|
| `ge_offers_done` | predicate: no pending buy/sell offers | — | — | — |
|
|
| `ge_collect` | withdraw from the GE collection box: bought (filled) items, refunded CASH, unsold units, sale proceeds; reconcile the SIDE-AWARE per-slot ledger (buy: quoted = filled + still_open + cancelled_unfilled; sell: quoted = sold + still_open + returned_unsold) before any slot reuse; a completed cycle closes with the ledger reconciled + ARCHIVED and the same pass releases the physical slot to free (`closed -> free` archival transition), so the slot immediately runs the next flip (governor 10471) | — | — | — |
|
|
| `ge_check_price` | read current buy/sell price of an item | — | — | — |
|
|
|
|
## F. Combat
|
|
|
|
| verb | meaning | DB | MB | RL |
|
|
|--------------------|----------------------------------------------------|----|----|----|
|
|
| `attack` | start/continue attacking a target | — | — | — |
|
|
| `prayer` | toggle a prayer on/off | — | — | — |
|
|
| `buff` | apply a buff item/potion | — | — | — |
|
|
| `eat` | heal when HP < threshold | — | — | — |
|
|
| `retreat` | disengage and reposition | — | — | — |
|
|
| `is_dead` | predicate: account is dead | — | — | — |
|
|
| `respawn` | return to a spawn/bank after death | — | — | — |
|
|
|
|
## G. Observation (predicates)
|
|
|
|
Predicates return a boolean and drive `state_machine.transitions`. They are
|
|
**free** (no anti-ban cost) and may be polled every tick.
|
|
|
|
| verb | meaning |
|
|
|------------------|------------------------------------------|
|
|
| `is_at` | at a named location |
|
|
| `has_item` | inventory holds item ≥ qty |
|
|
| `item_count` | quantity of an item in inv/bank |
|
|
| `level_is` | a skill is at/above a level |
|
|
| `xp_is` | a skill's xp at/above a threshold |
|
|
| `hp_is` | HP below a threshold |
|
|
| `is_dead` | dead |
|
|
| `ge_clear` | no pending GE offers |
|
|
| `bank_open` | a bank is open |
|
|
| `quest_state` | a quest is started/completed |
|
|
| `npc_present` | a named NPC is in range/visible |
|
|
|
|
## H. Housekeeping / safety
|
|
|
|
| verb | meaning | DB | MB | RL |
|
|
|-----------------|--------------------------------------------------|----|----|----|
|
|
| `log` | write a sentinel log line (RESULT/DONE/ERROR) | — | — | — |
|
|
| `alert` | raise a humanised alert (operator inbox) | — | — | — |
|
|
| `sleep` | humanised pause `delay:[min,max]` | — | — | — |
|
|
| `human_move` | anti-ban mouse wander / cursor nudge | — | — | — |
|
|
| `take_break` | scheduled AFK pause (run_control.break) | — | — | — |
|
|
|
|
---
|
|
|
|
## Parameter conventions
|
|
|
|
`params` are key/value and client-agnostic. Recognised keys:
|
|
|
|
- `location` — a **named** place. Must resolve to a real, named OSRS
|
|
location (never a bare coordinate in the entry; coordinates live in the
|
|
client mapping).
|
|
- `item` / `on` — canonical item names (exact wiki names).
|
|
- `qty`, `buffer` — counts.
|
|
- `method` — ordered preference list for how to achieve the verb
|
|
(e.g. `[teleport, walk]`); the client tries in order.
|
|
- `menu`, `option` — the exact right-click/option string.
|
|
- `price` / `max_price` — GP ceiling for a GE buy (anti-loss).
|
|
- `threshold` — a level/xp/hp cutoff for predicates and `eat`.
|
|
|
|
## Anti-ban hints (optional, per action)
|
|
|
|
- `delay: [min, max]` — randomised ms to sleep after the action.
|
|
- `mouse` — free-text humanisation directive (wander, jitter, bezier).
|
|
- `jitter` — randomise click offset in px.
|
|
|
|
These are **hints**, not guarantees. The translating agent may strengthen
|
|
them, never weaken a codex-mandated value.
|