osrs-codex/schemas/entry.schema.json
Claude 75a9965c9f codex: bounce-fix attempt 2 — additive pacing, cast-unit breaks, concrete SII recipes, validator crash guard (issue #5)
Governor-review (PR #10, attempt 2) findings, same issue-5 branch:

1. Pacing is additive. action-grammar.md defines anti_ban.delay as sleep
   AFTER the action, so a cast takes 1.8s + 1.6-3.4s = 3.4-5.2s (mid
   4.3s), ~837 casts/hr, not 1,400 or 1,800. Both entries now pin the
   midpoint rate with the formula documented: LA 25,953 / SII 44,372 /
   HLA 54,419 xp/hr. low-alch-f2p gp_per_hour bracketed by the delay
   endpoints (-119,000 / -78,000).

2. run_control units agree: schema.md 'every' counts iterations and
   iteration is one cast, so break.every [8, 14] is casts (comment no
   longer claims bank cycles).

3. SII is now a concrete recipe. New top-level recipes: table models all
   eight F2P smithable bars (bronze/iron/silver/steel/gold/mithril/
   adamantite/runite) with every input and quantity (coal 2/4/6/8,
   Smithing gates, bar ids) from the OSRS wiki smelting table. The
   cast-superheat action pins params.recipe (steel-bar anchor) plus a
   recipe_rule: smithing gate + complete input cost + one nature rune <
   bar price; buy/withdraw the exact unnoted inputs; bank the bar.
   entry.schema.json gains the optional 'recipes' section. Validator
   gains recipe/SII checks and a deterministic steel-bar fixture
   (1 iron + 2 coal = 3 inputs; margin 600 - (100 + 2*150 + 145) = 55).

4. Validator no longer crashes on malformed docs: scalar/empty YAML is
   rejected with a normal ERROR (document shape check) and
   supply_limit_conflicts guards non-mapping rows; regression fixtures
   cover (bad.yaml, None), scalar docs, and undeclared recipe ids.

Tests: python3 tools/validate.py -> 2 entries, 0 errors, 0 warnings
(exit 0); --selftest -> 14 PASS; live negatives: scalar + empty docs
error cleanly (exit 1, no traceback), reintroduced 12500 divergence is
caught (supply-fact gate), git diff --check clean.
2026-08-27 17:01:54 -05:00

253 lines
8.8 KiB
JSON

{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "OSRS Codex Entry",
"type": "object",
"additionalProperties": false,
"required": [
"id", "title", "domain", "tags", "status", "version", "updated",
"summary", "accounts", "best_practice", "state_machine", "actions",
"run_control", "risk", "sources", "verified"
],
"properties": {
"id": { "type": "string", "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", "maxLength": 64 },
"title": { "type": "string", "minLength": 3 },
"domain": {
"enum": ["economy", "training", "combat", "combat-slayers", "quests", "transport", "meta"]
},
"tags": { "type": "array", "items": { "type": "string" }, "minItems": 1 },
"status": { "enum": ["draft", "verified", "stale"] },
"version": { "type": "integer", "minimum": 1 },
"updated": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$" },
"summary": { "type": "string", "minLength": 10 },
"accounts": {
"type": "object",
"required": ["membership", "min_level"],
"additionalProperties": false,
"properties": {
"membership": { "enum": ["f2p", "members", "hybrid"] },
"min_level": { "type": "integer", "minimum": 1, "maximum": 126 },
"requires_quest": { "type": "array", "items": { "type": "string" } },
"requires_other": { "type": "array", "items": { "type": "string" } }
}
},
"economy": {
"type": "object",
"additionalProperties": false,
"properties": {
"item": { "type": "string" },
"item_id": { "type": "integer" },
"cost_per_cycle": { "type": "number" },
"income_per_cycle": { "type": "number" },
"net_per_cycle": { "type": "number" },
"gp_per_hour_low": { "type": "number" },
"gp_per_hour_high": { "type": "number" },
"xp_per_hour": { "type": "number" },
"supplies": {
"type": "array",
"items": {
"type": "object",
"required": ["item", "qty_per_cycle", "source"],
"additionalProperties": false,
"properties": {
"item": { "type": "string" },
"qty_per_cycle": { "type": "number", "exclusiveMinimum": 0 },
"source": { "enum": ["ge", "p2p", "drops", "craft", "bank", "npc-shop"] },
"ge_limit": { "type": "integer", "minimum": 1 }
}
}
},
"profit_drivers": { "type": "array", "items": { "type": "string" } }
}
},
"recipes": {
"type": "object",
"minProperties": 1,
"propertyNames": { "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$" },
"additionalProperties": {
"type": "object",
"required": ["bar", "smithing_level", "inputs"],
"additionalProperties": false,
"properties": {
"bar": { "type": "string", "minLength": 2 },
"bar_item_id": { "type": "integer", "minimum": 1 },
"smithing_level": { "type": "integer", "minimum": 1, "maximum": 126 },
"smithing_xp": { "type": "number", "exclusiveMinimum": 0 },
"inputs": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": ["item", "qty", "source"],
"additionalProperties": false,
"properties": {
"item": { "type": "string", "minLength": 2 },
"item_id": { "type": "integer", "minimum": 1 },
"qty": { "type": "integer", "minimum": 1 },
"source": { "enum": ["ge", "p2p", "drops", "craft", "bank", "npc-shop"] }
}
}
}
}
}
},
"best_practice": {
"type": "object",
"required": ["equipment"],
"additionalProperties": false,
"properties": {
"equipment": {
"type": "array",
"items": {
"type": "object",
"required": ["item", "why", "source"],
"additionalProperties": false,
"properties": {
"item": { "type": "string", "minLength": 2 },
"why": { "type": "string", "minLength": 5 },
"source": { "type": "string", "minLength": 5 }
}
}
},
"techniques": {
"type": "array",
"items": {
"type": "object",
"required": ["name", "why", "source"],
"additionalProperties": false,
"properties": {
"name": { "type": "string", "minLength": 2 },
"why": { "type": "string", "minLength": 5 },
"source": { "type": "string", "minLength": 5 }
}
}
}
}
},
"state_machine": {
"type": "object",
"required": ["initial", "terminal", "states"],
"additionalProperties": false,
"properties": {
"initial": { "type": "string" },
"terminal": {
"type": "array",
"items": { "type": "string" },
"minItems": 1,
"contains": { "const": "failed" }
},
"states": {
"type": "object",
"minProperties": 2,
"additionalProperties": {
"type": "object",
"required": ["goal"],
"additionalProperties": false,
"properties": {
"goal": { "type": "string", "minLength": 3 },
"next": { "type": "array", "items": { "type": "string" }, "minItems": 1 }
}
}
},
"transitions": {
"type": "array",
"items": {
"type": "object",
"required": ["from", "when", "to"],
"additionalProperties": false,
"properties": {
"from": { "type": "string" },
"when": { "type": "string", "minLength": 3 },
"to": { "type": "string" }
}
}
}
}
},
"actions": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": ["id", "step", "verb", "on_fail"],
"additionalProperties": false,
"properties": {
"id": { "type": "string", "pattern": "^a[0-9]+$" },
"step": { "type": "string", "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$" },
"verb": {
"enum": [
"login", "select_world", "hop_world", "is_logged_in",
"move_to", "walk_to", "teleport", "enter_region", "open_door",
"use_item_on", "click_object", "right_click", "talk_to",
"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_check_price",
"attack", "prayer", "buff", "eat", "retreat", "is_dead", "respawn",
"is_at", "item_count", "level_is", "xp_is", "hp_is",
"ge_clear", "bank_open", "quest_state", "npc_present",
"log", "alert", "sleep", "human_move", "take_break"
]
},
"target": { "type": "string" },
"params": { "type": "object" },
"on_fail": { "enum": ["retry", "skip", "abort", "alert"] },
"anti_ban": {
"type": "object",
"additionalProperties": false,
"properties": {
"delay": {
"type": "array",
"items": { "type": "number", "minimum": 0 },
"minItems": 2,
"maxItems": 2
},
"mouse": { "type": "string" },
"jitter": { "type": "number", "minimum": 0 }
}
}
}
}
},
"run_control": {
"type": "object",
"required": ["iteration", "stop_conditions"],
"additionalProperties": false,
"properties": {
"iteration": { "type": "string" },
"max_iterations": { "type": ["integer", "null"], "minimum": 1 },
"break": {
"type": "object",
"additionalProperties": false,
"properties": {
"every": { "type": "array", "items": { "type": "number", "minimum": 1 }, "minItems": 2, "maxItems": 2 },
"for": { "type": "array", "items": { "type": "number", "minimum": 1 }, "minItems": 2, "maxItems": 2 }
}
},
"stop_conditions": { "type": "array", "items": { "type": "string" }, "minItems": 1 }
}
},
"risk": {
"type": "object",
"required": ["ban_level"],
"additionalProperties": false,
"properties": {
"ban_level": { "enum": ["low", "medium", "high"] },
"notes": { "type": "array", "items": { "type": "string" } }
}
},
"sources": { "type": "array", "items": { "type": "string" }, "minItems": 1 },
"verified": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$" },
"related": { "type": "array", "items": { "type": "string" } }
}
}