From 3572255a11f64edfb6ab4f1c7cfe4a45b7f17c30 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 28 Aug 2026 03:19:13 -0500 Subject: [PATCH] =?UTF-8?q?codex:=20complete=20GE-flip=20lifecycle=20per?= =?UTF-8?q?=20owner=20addendum=20=E2=80=94=20partial=20fills,=20ge=5Fcance?= =?UTF-8?q?l=20recovery,=20ledger,=20break/resume,=20realized=20rates=20(b?= =?UTF-8?q?ounce-fix=204)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Owner lifecycle addendum (2026-08-28) + governor bounce 4 (lifecycle contract): - state machine now covers the ENTIRE buy -> sell -> collect flow with no stranded state: partial fills tracked per slot (filled_qty ledger), 4h-lapse buys go to a new cancel_requote state (ge_cancel: units return to inventory, cash refunds, slot freed) instead of collect, cancelled units still sell at the high edge, lapse sells re-quote or lower rather than strand - action grammar + schema extended ONCE with the cancellation mutation ge_cancel (was missing; ge_clear/ge_offers_done are predicates only) and used explicitly in the new a8 cancel-requote action - concrete runtime state: minimum per-slot capital table (buy x 4h limit), members 8-slot vs F2P 3-slot paths, per-slot offer phase + quantities, buy-limit window, inventory/collection reconciliation in a9 - breaks connected to an explicit safe/resume path: resting offers persist server-side + per-slot ledger survive the pause; resume = re-open GE, re-check offers, continue current phase; never break mid-collect/mid-place - rates qualified against the full lifecycle: 149,500 gp/h is named the 4h buy-limit CEILING; realized range = ceiling x fill_factor (~0.5-0.9) x duty_cycle (~0.90-0.95) ~ 96,300 gp/h midpoint; gp_per_hour_low 74,750 - pinned worked example: capital 22.5M -> 8 slot quotes -> arrowtips partial fill (4,000/10,000 tracked) -> iron bar full fill sell (90,000 net) -> cosmic no-fill ge_cancel + requote -> arrowtips partial matures at lapse (cancel, sell 4,000, 68,000 net) -> first break after 6-10 rotations -> resume -> stop conditions - version 2 -> 3; evidence: validate 2 entries 0 errors 1 pre-existing WARN, selftest 4 PASS (fractional-tax fail, ge non-margin pass, floored pass, above-cap pass), synthetic merge main 79cab78 + head clean + gate green, git diff --check clean --- codex/economy/flip-candidates.yaml | 229 +++++++++++++++++++++++------ docs/action-grammar.md | 1 + schemas/entry.schema.json | 2 +- 3 files changed, 182 insertions(+), 50 deletions(-) diff --git a/codex/economy/flip-candidates.yaml b/codex/economy/flip-candidates.yaml index 22ab173..d65a375 100644 --- a/codex/economy/flip-candidates.yaml +++ b/codex/economy/flip-candidates.yaml @@ -3,17 +3,22 @@ title: GE Flipping (margin trading) domain: economy tags: [flipping, merchanting, ge, money-making, hybrid] status: verified -version: 2 -updated: "2026-08-27" # ISO dates must stay quoted — YAML 1.1 parses bare dates to datetime.date +version: 3 # 3: bounce-fix 4 2026-08-28 (owner lifecycle addendum) — complete runnable flow: partial fills, ge_cancel + requote recovery, per-slot ledger, break/resume path, lifecycle-qualified rates, worked example pinned; ge_cancel added to the action grammar + schema +updated: "2026-08-28" # ISO dates must stay quoted — YAML 1.1 parses bare dates to datetime.date summary: > Buy-and-sell Grand Exchange margin flipping: place resting buy offers at the low edge of an item's price band and resting sell offers at the high edge, harvesting the spread on high-volume items. There are no skill or quest requirements — capital breadth and slot discipline are the whole - game. Members accounts run 8 GE slots over the full candidate set; - F2P accounts get 3 slots and F2P-tradeable rows only (separate F2P path - in profit_drivers). + game. Members accounts run 8 GE slots over the full candidate set; F2P + accounts get 3 slots and F2P-tradeable rows only (separate F2P path in + profit_drivers). Lifecycle (owner addendum 2026-08-28): the entry models + the complete runnable flow — capital allocation, per-slot quotes with a + quoted/filled/sold/collected ledger, partial fills, ge_cancel + + requote recovery on window lapse or stale prices, collection and + reconciliation, breaks on resting offers, and explicit stop conditions — + with a pinned worked example and realized (not idealised) rates. accounts: membership: hybrid # members: 8 slots/full set; F2P: 3 slots/F2P rows (see economy) @@ -22,6 +27,7 @@ accounts: requires_other: - "Post-Tutorial Island account with Grand Exchange access (no skill or quest requirement)" - "Members account: 8 GE slots, full candidate set (the modeled path below). F2P account: 3 GE slots and F2P-tradeable rows only — run the F2P path in profit_drivers." + - "Minimum starting capital: per slot = buy edge x 4h limit (arrowtips 2.23M, iron bar 1.45M, cosmic 2.196M, silver ore 0.949M, swordfish 3.09M, lobster 1.59M, magic logs 9.264M, mud 1.728M at the 2026-08-27 snapshot) — full 8-slot members coverage ~22.5M; the 3-slot F2P path needs ~5.5M (iron 1.45M + cosmic 2.196M + silver 0.949M). Capital below one slot's requirement takes that slot off the table." best_practice: equipment: @@ -58,15 +64,22 @@ best_practice: members set — a hybrid account must swap to the 3-slot F2P path (Iron bar / Cosmic rune / Silver ore) instead of chasing members-only rows it cannot buy." source: "OSRS wiki — Grand Exchange (Members get eight Grand Exchange slots ... free players are limited to three. Additionally, free players may only purchase free-to-play items, and not members' items)" + - name: keep a per-slot offer ledger; cancel-and-requote on lapse, never strand units + why: "Every slot tracks quoted qty -> filled qty -> sold qty -> collected proceeds. + A partially-filled offer keeps resting with its acquired units attached; on the 4h + window lapse or a stale price the slot is ge_cancel'ed — acquired units return to + inventory, unspent cash refunds — then re-quoted at the fresh edge (buy) or exited + at the current high edge (sell). No items, coins, or GE slots are ever stranded." + source: "OSRS wiki — Grand Exchange (offer mechanics; 4h window); docs/action-grammar.md (ge_cancel, added 2026-08-28)" economy: # Model (documented, reproducible from the snapshot): # Members path (8 GE slots — the modeled economics below): # per slot: buy `limit` units at the low edge, sell at the high edge. - # tax_pu = floor(0.02 * sell) # 2% convenience fee, rounded DOWN to - # # whole coins per item; the 5M/item cap - # # and the sub-50gp rounding exemption - # # are not hit at these prices + # tax_pu = min(floor(0.02 * sell), 5_000_000) # 2% convenience fee, + # # rounded DOWN to whole coins per item, + # # capped 5M/item (owner decision + # # 2026-08-28; cap never hit here) # net_pu = sell - tax_pu - buy # integer per-item net (floored tax) # 4h/slot = net_pu * limit # buy-limit window caps per-4h volume # F2P path (3 GE slots, F2P-tradeable rows only): same arithmetic, top-3 @@ -74,13 +87,25 @@ economy: # Snapshots 2026-08-27: prices.runescape.wiki mapping + latest; limits and # members flags cross-checked against the wiki item pages (all agree). Top 8 # by 4h/slot below in profit_drivers. + # + # Lifecycle qualification (owner addendum 2026-08-28): the 4h figures are + # an economic CEILING — ideal full fills of every slot with zero overhead. + # The realized operating range is: + # realized gp/h = ceiling x fill_factor x duty_cycle, where + # fill_factor ~0.5-0.9 (partial fills, cancels, requotes reduce the + # filled volume) and duty_cycle ~0.90-0.95 (scan + place + collect + # ~3 min per ~40-min rotation; breaks every 6-10 rotations). + # Example midpoint: 149,500 x 0.70 x 0.92 ≈ 96,300 gp/h. + # gp_per_hour_low (74,750) = 50% of the ceiling — a conservative realized + # lower bound; gp_per_hour_high (149,500) = the named ceiling, never + # presented as the achieved runtime rate. item: Rune arrowtips # anchor: top candidate by modeled 4h/slot (members) item_id: 44 cost_per_cycle: 223 # buy @ low edge per unit (snapshot 2026-08-27) income_per_cycle: 244 # sell @ high edge per unit, gross (snapshot 2026-08-27) - net_per_cycle: 17 # 244 - floor(244*0.02) - 223 = 244 - 4 - 223 (floored tax) - gp_per_hour_low: 74750 # 50% of the top-8 modeled upper bound — partial fills/drift - gp_per_hour_high: 149500 # top-8 modeled upper bound: sum(4h/slot) / 4 (8 slots, full fills) + net_per_cycle: 17 # 244 - min(floor(244*0.02), 5M) - 223 = 244 - 4 - 223 (floored, capped tax) + gp_per_hour_low: 74750 # realized lower bound = 50% of the ceiling: partial fills, cancels/requotes, collection trips, breaks + gp_per_hour_high: 149500 # 4h buy-limit CEILING: sum(4h/slot) / 4 (8 members slots, ideal full fills, zero overhead) — qualified above xp_per_hour: 0 # flipping awards no XP supplies: - item: Rune arrowtips # canonical wiki names per action-grammar conventions @@ -98,70 +123,95 @@ economy: profit_drivers: - "Spread per unit x trade volume; volume is the safety factor (high-volume items fill faster and drift less)" - "Slot breadth: cover as many net-positive candidates as capital allows (members 8 slots / F2P 3 slots)" - - "Members path — snapshot 2026-08-27 top 8 by modeled 4h/slot (floored 2% tax): Rune arrowtips 170,000 (M, buy 223 / sell 244 / limit 10000); Iron bar 90,000 (F2P, 145/157/10000); Cosmic rune 72,000 (F2P, 122/128/18000); Magic logs 72,000 (M, 772/793/12000); Silver ore 65,000 (F2P, 73/79/13000); Mud rune 54,000 (M, 96/101/18000); Raw swordfish 45,000 (F2P, 206/213/15000); Raw lobster 30,000 (F2P, 106/110/15000) — total 598,000 per 4h = 149,500 gp/h on 8 slots" - - "F2P path — 3 slots, F2P-tradeable rows only: Iron bar 90,000 + Cosmic rune 72,000 + Silver ore 65,000 = 227,000 per 4h = 56,750 gp/h (alternates: Raw swordfish 45,000, Raw lobster 30,000)" + - "Members path — snapshot 2026-08-27 top 8 by modeled 4h/slot (floored+capped 2% tax): Rune arrowtips 170,000 (M, buy 223 / sell 244 / limit 10000); Iron bar 90,000 (F2P, 145/157/10000); Cosmic rune 72,000 (F2P, 122/128/18000); Magic logs 72,000 (M, 772/793/12000); Silver ore 65,000 (F2P, 73/79/13000); Mud rune 54,000 (M, 96/101/18000); Raw swordfish 45,000 (F2P, 206/213/15000); Raw lobster 30,000 (F2P, 106/110/15000) — total 598,000 per 4h = 149,500 gp/h CEILING on 8 slots" + - "F2P path — 3 slots, F2P-tradeable rows only: Iron bar 90,000 + Cosmic rune 72,000 + Silver ore 65,000 = 227,000 per 4h = 56,750 gp/h ceiling (alternates: Raw swordfish 45,000, Raw lobster 30,000)" - "Post-2%-fee reality: 11 of 21 classic staples are net-positive at band edges for members; sub-2%-spread items (law/chaos/blood runes, dragon bones, adamantite/mithril bars) need sub-low buys or above-high sells" + - "Realized vs ceiling (work the full lifecycle): realized gp/h = ceiling x fill_factor (~0.5-0.9, partials/cancels/requotes) x duty_cycle (~0.90-0.95, scan/place/collect + breaks) — e.g. 149,500 x 0.70 x 0.92 ~ 96,300 gp/h midpoint; do not quote the ceiling as an achieved rate" state_machine: initial: idle terminal: [complete, failed] states: idle: - goal: be logged in at a bank with a GE booth, capital >= floor - next: [scan, complete, failed] + goal: "be logged in at a bank with a GE booth, capital >= floor, per-slot offer ledger empty (quoted = filled = sold = collected = 0 for every slot)" + next: [scan, complete] scan: - goal: read the current high/low band for every candidate + goal: "read the current high/low band for every candidate; compute net-positive edges with floored+capped tax" next: [buy, idle] buy: - goal: place one resting buy offer per slot at or below the low edge - next: [wait_buy_fill, collect, idle] + goal: "place one resting buy offer per free slot at or below the low edge; record quoted qty and remaining 4h limit per slot in the ledger" + next: [wait_buy_fill, idle] wait_buy_fill: - goal: hold BUY offers; re-quote any approaching the 4h window lapse - next: [sell, buy, collect] + goal: "hold BUY offers; track filled_qty per slot (partial fills included, units stay attached to the resting offer); on the 4h window lapse or a stale price, cancel the unfilled balance" + next: [sell, cancel_requote] sell: - goal: place one sell offer per filled slot at or above the high edge - next: [wait_sell_fill, collect] + goal: "place one sell offer per slot holding units (its filled_qty) at or above the high edge" + next: [wait_sell_fill, cancel_requote] wait_sell_fill: - goal: hold SELL offers; re-quote any approaching the 4h window lapse - next: [collect, sell, idle] + goal: "hold SELL offers; track sold qty per slot; on lapse or a stale price, cancel and re-quote — units are never left stranded" + next: [collect, cancel_requote] + cancel_requote: + goal: "ge_cancel the timed-out/stale offers of the current phase: acquired units return to inventory, unspent cash refunds, slot freed; re-quote at a fresh edge (buy when margin is still positive; sell to exit at the current high edge) or free the slot" + next: [wait_buy_fill, sell, wait_sell_fill] collect: - goal: collect proceeds, deposit coins, log the cycle + goal: "collect proceeds, deposit coins, reconcile (inventory empty of flip items, all GE slots free, each slot's ledger closed with a logged RESULT)" next: [scan, complete, idle] complete: - goal: session GP target reached + goal: "session GP target reached" failed: - goal: hard failure — stop, log ERROR sentinel, alert + goal: "hard failure — stop, log ERROR sentinel, alert" transitions: - from: idle - when: "capital below floor OR session target reached" + when: "GE access available AND capital >= floor AND session target not reached" + to: scan + - from: idle + when: "capital below floor OR session target already reached" to: complete - from: scan - when: "no candidate net-positive at band edges on 3 consecutive scans" + when: "at least one net-positive candidate at the scanned band edges (floored+capped tax)" + to: buy + - from: scan + when: "no net-positive candidate on 3 consecutive scans (prices stale — stand down)" to: idle - from: buy - when: "all slots quoted" + when: "all free slots quoted (quoted qty recorded per slot)" to: wait_buy_fill + - from: buy + when: "capital exhausted before quoting (insufficient funds)" + to: idle - from: wait_buy_fill - when: "all pending buys filled" + when: "a slot's buy offer is FULLY filled (filled_qty == quoted qty) — that slot's units move to sell" to: sell - from: wait_buy_fill - when: "4h window lapse with unfilled BUY offers" - to: collect + when: "a slot's buy offer hits the 4h window lapse or a stale price with filled_qty < quoted qty — ge_cancel: acquired units return to inventory, unspent cash refunds, slot freed" + to: cancel_requote + - from: cancel_requote + when: "re-quoted buy offers placed at the fresh low edge (window renewed, margin still positive)" + to: wait_buy_fill + - from: cancel_requote + when: "buy-side margin is gone — free the slot on the buy side; any acquired units from the cancelled offer still sell at the current high edge (exit at cost or a small loss rather than strand inventory)" + to: sell + - from: cancel_requote + when: "re-quoted sell offers placed at the fresh high edge (or lowered to the current band) for units in hand" + to: wait_sell_fill - from: sell - when: "sells placed" + when: "sell offers placed for all units in hand (filled_qty per slot)" to: wait_sell_fill - from: wait_sell_fill - when: "all pending sells filled" + when: "all pending sells filled — per-slot proceeds ready to collect" to: collect - from: wait_sell_fill - when: "4h window lapse with unfilled SELL offers" - to: sell + when: "a sell offer hits the 4h window lapse or a stale price — ge_cancel and re-quote at the fresh high edge or lower to the current band; units are never stranded" + to: cancel_requote - from: collect when: "session GP target reached" to: complete - from: collect - when: "rotation done and window open" + when: "rotation done and window open — start the next rotation" to: scan + - from: collect + when: "capital fell below floor after reconciliation" + to: idle actions: - id: a1 @@ -192,6 +242,7 @@ actions: params: items: "top-N candidates from the entry table" band: "high and low edge per item" + margin: "net-positive = sell - min(floor(0.02 x sell), 5,000,000) - buy > 0" on_fail: skip anti_ban: delay: [1200, 2800] @@ -202,9 +253,10 @@ actions: target: grand-exchange params: item: "per candidate slot" - qty: "min(remaining 4h limit, slot capacity)" + qty: "min(remaining 4h limit, slot capacity, capital available)" price: "low edge (rounded down)" max_price: "low edge — never instant" + ledger: "record quoted qty and remaining 4h limit per slot" on_fail: skip anti_ban: delay: [900, 2700] @@ -214,39 +266,71 @@ actions: verb: sleep params: delay: [6000, 12000] - until: "ge_offers_done changes or 4h window lapse" + until: "ge_offers_done changes or a fill event or 4h window lapse" on_fail: retry anti_ban: delay: [300, 900] - id: a6 + step: check-fills + verb: ge_offers_done + target: "all quoted slots" + params: + phase: "buy (no pending sells) | sell (no pending buys)" + per_slot: "filled_qty vs quoted_qty for every slot (partial fills included)" + verdict: "full | partial | none | 4h-lapse" + on_fail: retry + + - id: a7 step: place-sells verb: ge_sell target: grand-exchange params: - item: "per filled slot" - qty: "filled quantity" + item: "per slot holding units (filled_qty)" + qty: "filled_qty of that slot" price: "high edge (rounded up)" + ledger: "record sold qty per slot" on_fail: skip anti_ban: delay: [900, 2700] - - id: a7 + - id: a8 + step: cancel-requote + verb: ge_cancel + target: "timed-out or stale slot offers (current phase)" + params: + offers: "the slots that hit the 4h window lapse or a stale price" + cancelled: "acquired units return to inventory; unspent cash refunds; slot freed" + requote: "buy: re-place at the fresh low edge when the margin is still positive; sell: re-place at the fresh high edge or lower to the current band; margin gone on the buy side: free the slot and sell any acquired units to exit" + on_fail: retry + + - id: a9 step: collect-and-log verb: ge_collect target: grand-exchange params: deposit: "coins to bank" - log: "RESULT item, qty, net gp per slot" + reconcile: "inventory empty of flip items, all GE slots free, per-slot ledger closed" + log: "RESULT item, qty, net gp per slot (floored+capped tax)" on_fail: alert anti_ban: delay: [600, 1400] + - id: a10 + step: take-break + verb: take_break + target: "current location" + params: + duration: "[60, 240] seconds of idle AFK per break (matches run_control.break.for)" + safe: "resting offers persist server-side at their quoted edges — the full state lives in the GE interface plus the per-slot ledger, so a break at any resting-offer point is safe" + resume: "re-open GE (a2), re-check offer state (a6), continue from the current phase (a4/a7/a8/a9) — never break mid-collect (coins in hand) or mid-place (offer half-configured)" + on_fail: skip + run_control: - iteration: "one full buy -> buy-fill -> sell -> sell-fill -> collect rotation across all slots" + iteration: "one full rotation: quote buys -> fills/cancels/requotes -> sell filled units -> sells fill/cancel/requote -> collect + reconcile, across all slots" max_iterations: null break: - every: [6, 10] # rotations + every: [6, 10] # rotations (resting offers persist; state = GE + per-slot ledger) for: [60, 240] # seconds of idle AFK stop_conditions: - "session GP target reached" @@ -254,12 +338,58 @@ run_control: - "no net-positive candidates on 3 consecutive scans" - "3 consecutive aborted offers (client issue — do not loop)" + # ================= WORKED EXAMPLE (pinned, deterministic — owner addendum 2026-08-28) ================= + # Members account, 8 GE slots, capital 22,500,000 gp. Snapshot prices 2026-08-27 + # (buy/sell = low/high edge; tax = min(floor(0.02 x sell), 5,000,000)). + # + # Step 0 — preparation and capital allocation: capital at the bank, GE-adjacent. + # Scan bands (a3): only net-positive slots are quoted. Per-slot capital needs: + # arrowtips 223x10,000 = 2.23M; iron bar 145x10,000 = 1.45M; cosmic 122x18,000 = + # 2.196M; silver ore 73x13,000 = 0.949M; swordfish 206x15,000 = 3.09M; lobster + # 106x15,000 = 1.59M; magic logs 772x12,000 = 9.264M; mud 96x18,000 = 1.728M + # (total 22.497M <= 22.5M). Ledger: quoted=filled=sold=collected=0 per slot. + # Step 1 — place buys (a4): quote all 8 slots at the low edges (qty = 4h limit). + # wait_buy_fill (a5/a6). + # Step 2 — PARTIAL FILL: arrowtips fills 4,000 of 10,000 after ~18 min -> check-fills + # (a6) verdict PARTIAL: ledger arrowtips.filled = 4,000. The offer KEEPS resting + # (acquired units stay attached to the resting offer; nothing is stranded). + # Step 3 — FULL FILL: iron bar fills all 10,000 -> transition to sell (a7): place + # sell 10,000 @ 157 (high edge). wait_sell_fill -> fills -> collect (a9): + # proceeds 1,570,000; tax floor(157 x 0.02) = 3/item -> net = (157-3-145) x 10,000 + # = 90,000. Reconcile: inventory empty, slot free, ledger closed. + # Step 4 — NO-FILL / STALE recovery on the buy side: cosmic 18,000 @ 122 is unfilled + # approaching the 4h lapse -> cancel_requote (a8, ge_cancel): 0 units return, + # 2,196,000 cash refunds, slot freed; re-scan (a3): cosmic still net-positive -> + # requote 18,000 @ 122 on the fresh window. (If the buy margin had vanished the + # slot is freed on the buy side; any units acquired from a cancelled offer still + # sell at the current high edge.) + # Step 5 — PARTIAL matures at lapse: arrowtips still 4,000/10,000 -> ge_cancel: + # 4,000 units return to inventory, 6,000 x 223 = 1,338,000 refunded -> sell (a7): + # 4,000 @ 244 -> tax floor(244 x 0.02) = 4/item -> net = (244-4-223) x 4,000 = + # 68,000. Collect (a9) + reconcile. + # Step 6 — FIRST SCHEDULED BREAK after 6-10 rotations (midpoint 8): execution is at + # a safe point — every slot is either collected or resting at its quoted edge; the + # state (offers + per-slot ledger) persists server-side. take-break 60-240 s + # (a10); RESUME at a2 (re-open GE) -> a6 (check-fills) -> continue the current + # phase (a4 buys / a7 sells / a8 cancel-requote / a9 collect). Breaks never strand + # an offer and never interrupt a collect/place in progress. + # Step 7 — STOP: session target (e.g. 900,000 net) -> collect -> complete; capital + # fell below floor -> idle -> complete; 3 consecutive aborted offers -> failed. + # Rate qualification: the 149,500 gp/h figure is the 4h buy-limit CEILING (8 slots, + # full fills, zero overhead). Realized midpoint ~ 149,500 x 0.70 (fill factor) x + # 0.92 (duty cycle incl. scan/place/collect + breaks) ~ 96,300 gp/h — the entry's + # low bound 74,750 (50% ceiling) sits under that; the ceiling is never presented + # as an achieved runtime rate. + # ===================================================================================================== + risk: ban_level: low notes: - "Flipping is standard gameplay; the detectable signal is quote churn — keep per-offer pacing humanised, never instant-buy/sell loops." - "The 2% fee (since 2025-05-29) and 5M/item cap make sub-2%-spread staples unprofitable at band edges; re-scan before every rotation." - - "Thin/volatile items: a resting offer can sit for hours — cap quote lifetime to the 4h window and re-quote rather than chase." + - "Thin/volatile items: a resting offer can sit for hours — cap quote lifetime to the 4h window and re-quote (ge_cancel + fresh edge) rather than chase." + - "Partial fills are normal; never cancel-and-replace a partially-filled offer mid-window just to churn — the ledger keeps the filled qty attached to the resting offer until full/lapse." + - "Breaks are safe only at resting-offer or post-collect points (see a10); state = GE offers + the per-slot ledger, which survive the pause." sources: - "OSRS wiki — Grand Exchange (2% convenience fee since 2025-05-29, capped 5M/item, sub-50gp effectively untaxed, tax-exempt low-value items; buying rate restricted per 4h; connected limits; verified 2026-08-27)" @@ -267,7 +397,8 @@ sources: - "OSRS wiki — Merchanting (flipping = spread exploitation; high trade volume = safety; bulk flipping needs ~20M+ cash; avoid static-price items; offer matching at or better than your price)" - "prices.runescape.wiki/api/v1/osrs/mapping (item ids, members flags, limits — limits cross-checked against Module:Exchange/, all agree)" - "prices.runescape.wiki/api/v1/osrs/latest (high/low price band snapshot 2026-08-27)" -verified: "2026-08-27" # keep quoted (YAML 1.1 date parsing) + - "docs/action-grammar.md (ge_cancel verb added 2026-08-28: cancel a pending offer — bought units return to inventory, unspent cash refunds) + schemas/entry.schema.json verb enum; owner lifecycle addendum 2026-08-28 (complete runnable flow, worked example, realized rates)" +verified: "2026-08-27" # keep quoted (YAML 1.1 date parsing); prices last re-fetched live 2026-08-27 related: - low-alch-f2p diff --git a/docs/action-grammar.md b/docs/action-grammar.md index 234e520..2d29fa9 100644 --- a/docs/action-grammar.md +++ b/docs/action-grammar.md @@ -68,6 +68,7 @@ Legend for the mapping table: | `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` | cancel a pending offer: bought units return to inventory, unspent cash refunds | — | — | — | | `ge_offers_done` | predicate: no pending buy/sell offers | — | — | — | | `ge_collect` | collect finished GE transactions | — | — | — | | `ge_check_price` | read current buy/sell price of an item | — | — | — | diff --git a/schemas/entry.schema.json b/schemas/entry.schema.json index c50ce9b..69df417 100644 --- a/schemas/entry.schema.json +++ b/schemas/entry.schema.json @@ -155,7 +155,7 @@ "click_button", "menu_option", "bank_inventory", "deposit_all", "withdraw", "has_item", "count_item", "move_to_inv", "sort_inventory", - "ge_open", "ge_buy", "ge_sell", "ge_offers_done", "ge_collect", + "ge_open", "ge_buy", "ge_sell", "ge_cancel", "ge_offers_done", "ge_collect", "ge_check_price", "attack", "prayer", "buff", "eat", "retreat", "is_dead", "respawn", "is_at", "item_count", "level_is", "xp_is", "hp_is",