ship one record per function: merge the release set, gen reads it, descriptions as doc comments, gates for what was only claimed; v3.0
Some checks failed
CI / fuzz (push) Successful in 2m2s
CI / lint (push) Successful in 15s
CI / test (push) Failing after 18s

This commit is contained in:
Kamal Tufekcic 2026-08-02 22:01:36 +03:00
commit 3410a79b6a
28 changed files with 30596 additions and 955 deletions

View file

@ -56,7 +56,13 @@ impl LaunchSpec {
pub struct PawnAnchor {
pub pawn_class: &'static str, // player-pawn RTTI class — the live-oracle instance anchor
pub health_field: &'static str, // a reliable "is this instance alive" netvar
pub is_player_pawn_slot: u64, // gamedata vtable offset of IsPlayerPawn (call-live smoke test)
/// A RECORDED REFERENCE value for `IsPlayerPawn`'s vtable slot — cross-checked against, never called.
///
/// The live CALL test uses the slot THIS build derived and skips entirely when the build derived none;
/// this constant only decides whether that run prints a "the slot moved, update me" note. It is not a
/// fallback, and must not become one: the slot has taken six distinct values in ten months, and calling
/// a stale index would inject a call to whatever now occupies it. A new game may record 0 until measured.
pub is_player_pawn_slot: u64,
}
pub struct GameProfile {
@ -114,12 +120,55 @@ pub struct GameProfile {
/// test from the command one — convergence of registrar wrappers on a shared core, not a sentinel in the
/// callee — so it can fail while commands keep working.
pub min_convars: usize,
/// Floor on VScript bindings. Its own floor for the usual reason — a THIRD identification test,
/// distinct from both the command sentinel and the convar convergence: a record base computed by the
/// initialiser's own `idx*5 << 4 + [class+0x28]`. A codegen change that reshapes that arithmetic
/// yields zero bindings while every other surface keeps reading perfectly.
///
/// Set well under the observed count, which is the house rule, but the margin here is deliberately
/// wide: the reader recovers three distinct registration forms (the packed name pair, the
/// `movddup` single-string form, and a base copied between registers), and losing any ONE of them
/// would still clear a tight floor while quietly dropping a third of the surface.
pub min_vscript: usize,
/// Floor on VScript bindings attributed to an OWNING CLASS — and the only floor here that a full run
/// checks and an offline one skips, because zero is correct by construction offline: the descriptor
/// reaches its class through a register loaded from memory, so nothing static recovers it.
///
/// Separate from `min_vscript` because it fails independently and in the opposite direction. That floor
/// guards the offline READER against a Valve reshape; this one guards the LIVE WALK — the string-anchor
/// instance search, the owner read at the record's `+0x30`, the class-name read behind it. Any of those
/// breaking leaves every binding recovered, described and located, with no class on any of them: a
/// release that clears every other gate. It is `class` that `gen`'s `moddota` format GROUPS BY, so
/// the artifact would ship intact while both of the files it writes came out empty.
pub min_vscript_classed: usize,
pub min_schema_enums: usize,
/// Collapse floor for the recovered schema CLASS table — the largest table the deriver reads, and the
/// one every other schema claim rests on: the artifact's whole `schema` section, the entity-output and
/// datadesc joins, the derived type layouts, and `Identity::class_size`, which is half the identity
/// check's conjunction.
///
/// It needs its own floor because nothing else covers it. `min_schema_enums` does not — `enumerate_enums`
/// uses classes only to exclude field arrays, so it keeps passing at zero classes. The live oracle's
/// class gate does not either: it is SKIPPED below `ORACLE_MIN_SAMPLE` checked classes, and the sample
/// IS the class count, so a collapse into that range disables the check that would catch it. And the
/// offline/live layout comparison reads the same bytes through the same `CI_*` constants, so whatever
/// survives a reshape agrees with itself.
pub min_schema_classes: usize,
/// Collapse floor for the DERIVED function tiers — `core + high_confidence`.
///
/// Every table read out of the binary has one of these; the tool's headline product did not, and the
/// gap is structural rather than an oversight of one number: the live oracle gates a PASS RATE over
/// entries that reached the gamedata document, and a signature that failed to resolve never enters it.
/// So a derive that emits forty functions instead of four thousand passes at 100% — a stale corpus
/// model, a `--target` from the wrong branch or a missing secondary library all land there.
///
/// A collapse detector, not a tight bound: set well below the observed count, like every sibling floor.
pub min_core_functions: usize,
/// Output game-key the game-keyed emitters use (Metamod `Games { <key> {..} }`, Plugify `{ "<key>": {..} }`).
pub game_key: &'static str,
/// The `--game` CLI token / per-release filename suffix (`cs2`, `dota2`) — distinct from `game_key` (the
/// content-dir token `csgo`/`dota` that framework formats key on). Names the artifacts
/// `gamedata-<token>.json` / `model-<token>.json` / `netvars-<token>.json`.
/// `rosetta-<token>.json` / `model-<token>.json`.
pub token: &'static str,
/// Dedicated-server launcher binary under `bin/linuxsteamrt64/` (CS2: `cs2`).
pub executable: &'static str,
@ -199,7 +248,15 @@ pub const CS2: GameProfile = GameProfile {
min_entity_classes: 200,
min_commands: 400,
min_convars: 900,
min_vscript: 180,
// observed live: 271 of 300 bindings attributed across 24 classes
min_vscript_classed: 150,
min_schema_enums: 250,
// CS2 recovers 1,899. A floor at 1,200 is well clear of build-to-build drift and nowhere near
// the range a `SchemaClassInfoData_t` reshape would leave.
min_schema_classes: 1_200,
// CS2 ships 1,086 core + 2,899 high-confidence = 3,985.
min_core_functions: 2_500,
game_key: "csgo",
token: "cs2",
executable: "cs2",
@ -304,7 +361,14 @@ pub const DOTA: GameProfile = GameProfile {
min_entity_classes: 1000,
min_commands: 400,
min_convars: 600,
min_vscript: 1200,
// observed live: 1,638 of 1,841 bindings attributed across 63 classes
min_vscript_classed: 900,
min_schema_enums: 350,
// Dota recovers 2,962.
min_schema_classes: 2_000,
// Dota ships 1,096 + 4,047 = 5,143.
min_core_functions: 3_000,
game_key: "dota",
token: "dota2",
executable: "dota2", // bin/linuxsteamrt64/dota2