OPENHOOPS / 2K14Final team archive · November 9, 2026Reference libraryChecksums

Dated source reference. Current release status: handoff state. Full original relative paths are in the developer archive.

OpenHoops API — private broker58 / HTTP v1

Visiting crowd artwork adds independent 0–100 crowd.away_percent, crowd.appearance.set/reset, provenance/readback at GET /v1/crowd/appearance, and Python/TypeScript helpers. This hook-only candidate uses actual selected team clothing and separate close/distant resources with global row placement. Private dev58 passes original/college production matches and separately reviewed native crowd images. Exact builds, scope and restoration receipts are in work78; the accepted dev57 bundle remains unchanged.

Dynamic crowd attendance uses 0–100 percentages for per-launch crowd.fill, live crowd.set/crowd.reset, native readback through GET /v1/crowd, and Python/TypeScript helpers. The crowd-enabled hook uses a separate Crowd.1 mapping while retaining main ABI26. The work76 record tracks native verification and binary identity; the percent follow-up records the API/SDK conversion. Public crowd contract version2 declares percent units; native Crowd.1 remains unchanged.

October20 team delivery71 now publishes accepted API70e/native70d together with the bundled runtime/writer, SDKs and curated app-owned launch/result guides.634 tests/126 schemas pass against the packaged API. Use that complete team bundle for the current integration; public preview2 below remains immutable history. Runtime API/native code is unchanged and presentation remains unfinished.

Current work70 retains API0.2.0.dev55/HTTPv1 and existing transports. API70e passes634 Windows tests/126 schemas; effective college overtime accepts matching frozen authority while invalid/missing/mismatched authority still refuses. Unchanged native70d/DLL5cf76196 passes original70liveo/API70c natural9–6 and college70liveq/API70e natural6–3, with strict native C metadata, selected IFF reads, forced-two-point classification and independent immutable results/repeated ACK. Both close/restore98 baseline files/DLL50/INI; final preservation passes and custody is released. Changed free-throw counts retain instruction/headless proof, with only baseline2→2 queried in original and no college FT query. Historical result compatibility and inherited TypeScript compilation retain their scope. Closeout.

Developer kit64 adds read-only CLI/HTTP compatibility reports, a strict TypeScript client and eight game-free integration scenarios. Exact source64f passes628 Windows API tests/125 schemas and eight independent Node/HTTP/SQLite/SSE scenarios (63 checks/18 schema responses). Source-matched64c compilation passes25 client runtime cases. MainABI26/event4/profile4/court3 and native63i are unchanged. Native work63 still needs its separate live-game acceptance; public packages/stable installations remain separate. Earlier checkpoints below retain their source scopes.

Extension-platform work63 is the private API54 candidate: frozen timing/reset/college-bonus configuration, FT/classification transactions, pre-reveal copied native metadata and immutable match assets.595 Windows API tests/122 schemas pass; the full native DLL builds with warnings-as-errors. Headless/native-instruction evidence is separate from final game acceptance, which is waiting for the user’s explicit Dell-safe notification. The stable game, public packages and source62 live baseline remain preserved.

Development53 adds accepted-transition legal state and native rule extensions. Read /v1/rules for the supported configuration/permission masks and /v1/ball-state for validity-qualified state. The native C SDK is experimental; main snapshot ABI26/event ABI4 and public HTTPv1 remain unchanged.

Previous roster metadata52 connects optional roster metadata to any external client. Private API0.2.0.dev52/HTTPv1 keeps ABI26/event4/profile4/court3 and all67 native inputs unchanged. Its539-test/98-schema source now has real native61a acceptance: the last two teams of the hosted905-team export bind24 players at phase4, retain six metadata-only entries, expose standard/custom fields and overrides to an independent live scorebug consumer, and finish naturally4–3 with identical frozen context in reconciled independent deliveries. Reopening the persisted real-game database retains context/ACKs and delivers to a third consumer. The broker reads companions; the DLL does not parse or render them. No new DLL or public Windows package.

Previous51 source retains the completed external match lifecycle and adds match controls51: clock-mark rotation plans with separately observed native entry, original timeout calls, connected-input discovery and startup team assignments.510 Windows API tests/84 schemas pass. Live college/original control checks and actual keyboard assignment pass; physical gamepad multiplayer remains unverified. Public preview2/API36/editor dev7 and stable35 remain preserved; no new package is published.

Previous50 adds optional per-opponent defensive presets before reveal, substitution.queue/substitution.cancel, durable separately observed entry tracking and the portable game_flow.ResultInbox helper for store-before-ACK/recovery/explicit owned completion. Availability2/PE substitution version2 exclude the failed queue-only prototype. Live51w verifies both native entries; full flow and preservation pass; see the external-flow ledger. Existing paused coaching/defense and expiring inputless pause/resume remain. Preferred defender is configuration; native queue acceptance is not completed entry. See the client guide and prior coaching evidence.

Current scope (October13,2026): Windows-first deep editing and a public extension API; Mac/Linux compatibility follows later. Earlier native-port goals and next-step proposals in this evidence history are superseded. Technical observations and verification limits remain as recorded.

Current documentation: October19,2026 UTC. Source broker 0.2.0.dev55, snapshot ABI26, event ABI4, college profile4 and court definition3. The original x86 game runs on Windows11 x64 with an x86 adapter and x64 broker. See versions, evidence and verification-field meanings, canonical OpenAPI and examples.

Native startup skips opening/title waits and opens Quick on normal EXE launch. Managed launch keeps preparation at Home under neutral/app-configurable loading and reveals only the requested native match, with no generated input. Roster replacement at Quick is refused because its preview objects are unsafe across expanded replacement. Earlier development39 startup (355 tests),38 load/Start (345) and37 preparation (307) remain scoped evidence. Current expansion is isolated from stable35 and immutable public preview2/editor dev7. Existing regulation/OT/court/ultrawide evidence and rare-rule/full-game deferrals retain their stated scope. A game adapter and a local companion API for independent scoreboard, presentation and season-manager clients. The original Windows x86 game still runs the simulation. The current goal is Windows-first deep editing, with Mac/Linux compatibility later. A full native engine port is not required. This remains a 32-bit game. The native rule SDK is experimental and exposes only the explicitly supported decision points.

Read /v1/session before relying on a capability. Unavailable capabilities return explicit errors; unknown basketball meanings remain null. The implementation exposes sampled state and observed changes, not a lossless authoritative play-by-play feed.

The implementation/evidence ledger and native SDK guide define the current experimental Windows contract. Main snapshot ABI26/event ABI4 are unchanged; rule state uses a separate version1 mapping. Use the exact matching broker, hook and C header. Historical preview2 does not include this work.

GET /v1/ball-state exposes player control, team control, NBA possession, live/alive status, restart entitlement, pending attempts and partial free-throw/restart transactions. Each family is known, unknown or inapplicable with revision/reason/evidence. These are accepted native-transition interpretations, with profile-specific applicability. Physical attachment, clocks and presentation phases do not establish legal status. Uncovered changes invalidate affected fields. College alive and separate NBA possession are inapplicable. Inspect nested validity masks before using attempt, restart or FT details; a known award does not imply a known ordinal or retained possession.

GET /v1/rules exposes supported decision masks, module/configuration hashes, ownership, frozen configuration, callback faults and integrity. The same data appears additively as snapshot legal_ball/rule_runtime; legacy ball.live and ball.legal_possession retain null semantics. Main and rule mappings are sampled independently and are not one atomic game transaction. Synchronous native callbacks receive copied context at their boundary; committed rule events carry the semantic revision.

A match request can select up to eight trusted, self-contained Windows x86 DLLs under launch_configuration.extensions. Registration is transactional and exclusive per mutable decision. Supported configuration points are full/minimum shot-clock values and foul threshold5/6; nineteen mapped permission queries support stable decisions per simulation step. College retains ownership of its bonus policy and two conflicting permission slots. Inspect capabilities rather than assuming every SDK enum is callable. FT-count, shot-classification, arbitrary bonus, backcourt, period/OT and separate-rim callbacks are unavailable. The independent C example uses the same interface as third-party modules.

A valid slow answer applies to its current decision, then future callbacks are disabled. Optional runtime faults continue with explicit degraded provenance and retain already frozen constants. Required runtime faults suspend further simulation, persist review-required failure and close only a broker-owned game; no ordinary successful result is emitted. Admission/init failures refuse startup with a typed child-specific receipt. Modules are trusted native code; this is not sandboxing or preemption of hung DLLs.

The ordinary durable stream adds rules.ball_state, rules.decision, rules.lifecycle and correlation-only rules.observation_context. Do not count correlated native-stat observations as additional statistical credits. Final results freeze rule identity/configuration/faults/gaps, clear inherited stock verification for modified profiles and preserve independent-consumer/idempotent-ACK semantics. Summary receipts are bounded with explicit omitted counts; the durable event log retains the full retained delivery stream.

Ten original foul/violation record names are connected, adding double dribble and kicked ball. Roles are scoped to verified original handler-credit arguments: violating player for those two, committer/fouled player for reaching, blocking and shooting. Out-of-bounds actor roles and other kinds remain unresolved. Original-game detection is not independently certified by naming its record. Native consumers have matching local name/role helpers in the SDK header.

Current verification

The agreed college mechanics are implemented: two halves, scaled overtime, clock/reset/bonus/arrow/timeout policies and measured court geometry. Latest36ct naturally finishedMiami4–Spurs0 in overtime; player/team totals, logical-half/OT ledger, independent-consumer delivery, duplicate acknowledgment and result immutability passed. Earlier36bl natural10-minute halves exercised four automatic TV returns. All18 controlled final-release contact/scoring cases at both baskets passed. Native and prior271-test Windows API evidence, exact DLL hashes, instrumentation differences and deferred checks are in the verification ledger.

Existing controls include118 user/CPU slider combinations,39 gameplay/presentation/rule options,130 controller preference/slot combinations,26 camera configurations (17 selectable), and13 pregame controls, including all nine Game Options entries and both teams/uniforms. Source-only roster authoring also prepares starting order/native minute preferences. Their original development35 live checks remain evidence for those unchanged interfaces, not new current-platform tests. Game integration is Windows only. Development53 adds per-field legal state and a native rule SDK with explicit supported masks. Universal named events, uncovered legal transitions, additional rule mutation points, block-retraction live proof and safe asset replacement remain open. See remaining scope.

Start

  1. Use the supported executable SHA-256 7cb5fdaa30586558a3146dcf9023880b1cceeaabfe0f92f967f461c4644f3704 in a working game copy. Preserve the original corpus.
  2. Use a matching API-enabled dinput8.dll in that working copy; build instructions are in native/api. It includes external-mode onboarding removal and portable saves. Do not overwrite another mod loader.
  3. Start the game, or use the opt-in --launch-game workflow in the launch guide. Run the broker in the same Windows login session as the game; its shared-memory mapping is session-local. A regular SSH service session cannot see the interactive game's mapping.
  4. With Python3.9+ (current Windows tests use3.13.16) and the matching x64 Windows _atomic.dll beside source.py, run from this directory:

powershell python -m openhoops_api --pid <game-process-id> --state <private-state-directory>

The broker prints its loopback URL and token-file path, never the token. Supply Authorization: Bearer <token-file-content> on every request. Keep the state directory private; it contains durable results, identifiers and command requests. One broker owns a game and one process owns a state directory. No game code runs in HTTP threads.

Mac/Linux clients can connect through an SSH tunnel using the same local port:

ssh -N -L 127.0.0.1:27614:127.0.0.1:27614 optiplex

Copy the token privately using your existing authenticated connection. Never put it in a query string, browser URL or public repository. The broker deliberately rejects non-loopback Host headers and cross-origin browser requests. Browser scoreboards should use their own local backend to talk to this API; native clients and Node/Python companions can connect directly. All authenticated clients are trusted peers: client_id is an ownership convention, not a separate security principal.

Replay a JSONL snapshot fixture on any Python-supported platform:

python -m openhoops_api --replay snapshots.jsonl --state ./private-replay-state

Replay cannot mutate a game. Broker portability does not establish that the injected game adapter works in Wine/macOS/Linux.

Routes

Responses are JSON except SSE and registered-ROS binary content. POST bodies must be finite UTF-8 JSON objects, content type application/json, with one Content-Length and at most 65,536 bytes. IDs use 1–96 letters/digits/underscore/dot/colon/hyphen, starting with a letter/digit. Errors have { "error": { "code", "message", "details" } }.

Method / path Contract
GET /v1/session Versions, stream identity, capability limits and supported EXE hash
GET /v1/health Source freshness; never use a stale snapshot as live
GET /v1/snapshot Latest snapshot, health, age, optional managed identity
GET /v1/ball-state Per-field legal-state validity, profile, revisions and evidence
GET /v1/rules Supported rule decisions, modules, frozen values and integrity/fault status
GET /v1/crowd Current native attendance, scene/revision guards, startup verification and supported limits
GET /v1/crowd/appearance Away artwork share, selected source identities and native rendering diagnostics
GET /v1/settings Named slider, option, controller and camera catalogs/readback; inspect per-setting bounds
GET /v1/preparation Pregame controls/revisions, selected teams/uniforms and arena/playbook catalogs
GET /v1/launch Fresh load/Start state, requested/effective rules, startup/preset/camera/participation status and desktop-bootstrap outcome
GET /v1/launch/settings Per-launch catalogs/request and independent preset/camera status
GET /v1/launch/request?request_id=ID Current or named durable app request status; no replay
GET /v1/lifecycle Broker-owned child identity/running status; attached games remain separate
POST /v1/rosters / PUT /v1/rosters/<SHA256> Admit/copy a hash-bound local or uploaded standalone ROS; separate from native load
GET /v1/rosters/<SHA256> Read immutable intake metadata
GET /v1/rosters/<SHA256>/content Authenticated verified ROS bytes, SHA ETag and download filename
GET /v1/roster-tools / /v1/roster-tools/fields Optional shared-writer inventory and paged named field catalog
POST /v1/rosters/query, /v1/rosters/edit, /v1/rosters/prepare Immutable named field queries, edits and starting order/minute preparation
GET /v1/preparation/catalog?kind=teams&start=N&catalog_id=ID At most64 loaded rows; kind is teams or uniforms; ABI15 required
GET /v1/events?after=CURSOR&limit=100 Durable observed-event page; limit clamped 1–1000
GET /v1/stream?after=CURSOR SSE, or Last-Event-ID; reconnect after bounded 25-second responses
POST /v1/matches Bind phase10 or a verified managed zero-stat opening scene to external IDs
GET /v1/matches/ID Managed match status and timeline revision
POST /v1/matches/ID/resume Explicitly accept a reviewed continuation as a new timeline
POST /v1/matches/ID/abandon Mark incomplete, suppress automatic result export
GET /v1/results?consumer_id=ID Unacknowledged immutable result revisions for this consumer
POST /v1/results/ack Acknowledge one revision after your own database transaction commits
POST /v1/control/lease Exclusive mutation lease, TTL 1–60 seconds
POST /v1/control/release Release using its lease token
POST /v1/commands Guarded clocks/settings/preparation/load/Start/owned stop commands; no arbitrary memory access
GET /v1/commands/ID Durable command receipt

App-owned launch and file authoring

The match-request guide supplies the single-document workflow: --launch-game EXE --state PRIVATE_STATE --match-request REQUEST.json, optionally --roster-tools COMPONENT_DIRECTORY. A third-party app owns request/match/team/player IDs and can observe /v1/launch/request. The broker executes the public SDK and native handlers; it embeds no dynasty database. Omitted choices retain fresh defaults, so supply all applicable settings for repeatability.

launch_configuration version1 accepts original rules or college half length1–20, media0/3/4 and scaled OT; settings supplies startup options, user/CPU sliders, stored controller preferences and an eligible exhibition camera. Optional participation.mode is cpu_vs_cpu, primary_home or primary_away (ABI21). It addresses the existing primary logical input; physical device choice, key remapping and multiple humans are separate. Native control-role/current-saved input records must match before reveal. The participation field records startup verification, not continuous legal or input authority. Rules are frozen before creating the child; the exe-local INI is preserved. NBA quarter length and college half length remain distinct fields.

With the optional shared writer, query up to128 named rows/32 fields, edit up to512 unique named cells, and prepare complete roster order/native minute preferences. The factual catalog exposes39 named tables; no proprietary editor is executed and private bit coordinates are omitted. Editing/preparation produces new admitted ROS IDs and repeatable authoring receipts. No game state changes until explicit roster.load. Prepared IDs work with launch_registered_match without reupload. This does not promise exact substitution times, game-mode/asset compatibility or all proprietary-editor workflows.

Client.download_roster(roster_id, NEW_PATH.ros) fetches verified binary content, checks headers/size/format/SHA locally and atomically creates a new file. Existing destinations are refused, including concurrent creation. The content endpoint accepts only an existing registered SHA and no query parameters; it does not export arbitrary local paths. Metadata native_loaded:false describes admission/export, independently of current game state.

The optional identity plan binds every instantiated player by exact slot/name and supplies finite match metadata up to8KiB. That metadata survives managed results for app-owned season/round/presentation context; it does not apply native UI or rule changes. Stored ROS entries that were not instantiated are reported separately, without invented stats or inactive/injury status. session.stop requires the owned child, lease/run/current match and owner: cancellation abandons without a result; finished requires an already finalized reconciled result. The broker can keep serving durable results/receipts after the game exits. Unknown Start outcomes stay nullable and are never blindly retried.

Snapshot interpretation

Snapshots are taken at the application's dispatcher entry, at most 10 Hz. A sequence lock protects transport copies. Other engine worker writes are not excluded; no claim of a globally atomic physics frame is made. Invalid pointer/transitional reads produce invalid snapshots. This boundary is not a verified basketball-event commit boundary.

  • run_id is a random process-launch identity. source_sequence counts samples in that run. It is not an event number or match ID.
  • phase_code and raw_period preserve engine values. Phase10 is playing, phase19 is observed postgame. Raw period5 can mean finished regulation; it does not alone mean overtime.
  • clocks: game/shot/backcourt values in seconds, plus raw timer flags. private adapter v2 reports paused from the actual simulation pause counter and replay_active from a separate engine replay gate. Legacy v1 and inactive/invalid simulation states report null. The replay gate also appears in pregame/cinematics; it is not an exclusive Instant Replay label. Neither value establishes legal dead-ball status.
  • teams.home/away.stats: points, FT/2PT/3PT makes/attempts, derived FG totals, OR/DR/total rebounds, assists, steals, blocks, turnovers and fouls. The separate box_score_team_fouls, team_only_turnovers, qualification counters and timeout pools must not be collapsed into one quantity. Team turnovers can lag player credit in the original engine.
  • scoring_buckets: total, four regulation buckets, one combined overtime bucket. The original record does not separate multiple OTs; the captured-point ledger can provide reconciled logical splits when its continuity requirements hold.
  • bonus_threshold_reached derives the recovered numeric threshold from qualification counters. It is not a guarantee that the next foul awards free throws; foul exclusions and shooting overrides still matter.
  • players: roster slot keys, display names, active status, live box-score stats, signed plus/minus, seconds played and active position. Positions use unconverted engine coordinates. Bench positions are null. Slot keys and names are not durable roster/database IDs.
  • ball.attached_player_key is physical attachment evidence, not legal possession. Legacy ball.legal_possession and ball.live remain null; use the separate, validity-qualified legal_ball surface.
  • free_throws contains engine total/remaining counters. A remaining count may reach zero before points are credited.
  • roster_fingerprint hashes slot/name pairs only. It detects ordinary roster changes but cannot establish identity across same-name replacement, reload or rematch. External tools must supply durable IDs and explicitly manage boundaries.

Never display stale values without a visible stale indicator. No automatic success/result follows a crash, disconnect, invalid sample or abandoned match.

Managed matches and exports

An external runner owns its IDs and metadata. Bind only after verifying the selected teams/roster in the current phase10 game:

from openhoops_api.client import Client
c = Client('/private/path/token')
s = c.request('/v1/snapshot')
binding = {
    'match_id': 'season-2026-game-42', 'client_id': 'my-dynasty-tool',
    'run_id': s['run_id'], 'roster_fingerprint': s['roster_fingerprint'],
    'teams': {'home': 'my-team-h', 'away': 'my-team-a'},
    'players': {p['key']: YOUR_ROSTER_IDS[p['key']] for p in s['players']},
    'ruleset': {'id': 'my-ruleset', 'version': '1'}
}
c.request('/v1/matches', binding)

ruleset is provenance metadata; binding does not apply those rules. Repeating an identical binding is idempotent; reusing the ID with different content returns409. For roster intake/native loading and direct Start use the separate ABI16 launch workflow; binding still begins at phase10.

Process changes, roster changes, period rollback, finish reset and suspicious clock increases place a managed match into review_required. This is conservative detection, not complete checkpoint/abort detection. Resume with {client_id, run_id, expected_revision} only after deciding this is the same external match; a new timeline revision invalidates assumptions based on the old history. Abandon with {client_id} when it is not. Once finalized, a subsequent process/roster/reset boundary detaches the live binding (match.detached) while preserving the completed match and immutable results; the next game can receive a fresh binding.

A result requires a bound match, valid phase19, finish latch, a higher-scoring winner, reconciled additive player/team box-score totals, and two distinct stable snapshots. Results include full available team/player statistics, external IDs, source EXE, ruleset metadata and explicit completeness flags. Whole-match event completeness is always false. Binding may have occurred midgame. Stable finish is observed engine finality, not a mathematical guarantee against all future engine corrections.

Results are durable immutable revisions. Later changed settled totals create another revision. Consume /v1/results?consumer_id=your-tool, commit each (match_id,result_revision) transaction idempotently, then POST /v1/results/ack with {consumer_id,match_id,revision}. A crash between commit and ACK repeats delivery safely. Other consumers have independent acknowledgements. Do not add totals twice when a corrected revision arrives: replace/reconcile the prior result in your own database.

Events and reconnects

event_id/cursor is stream-id:durable-sequence. Persist it only after consuming the event. Replay is bounded to10,000 events;409 cursor_gap provides a latest_cursor. Fetch a snapshot and resume at that cursor, explicitly marking lost history. A different state database has a different stream ID. Never silently skip a gap.

Types: source.started, source.samples_skipped, snapshot.observed, stats.decreased, match.bound, match.review_required, timeline.revised, match.abandoned, command.resolved, result.available. stats.decreased deliberately has unknown cause; it is not a verified named correction. A polled delta may combine several plays. SSE is at-least-once across reconnection; clients deduplicate by event ID. The Python SDK parses SSE and raises structured HTTP errors; the caller owns reconnect/backoff and reconciliation policy.

Development engine records

engine_records.declared_capture_paths reports the paths advertised by the attached producer. An empty legacy declaration does not prove that all hooks are absent. Declarations describe installed capture paths, not comprehensive semantic coverage.

  • engine.record_stored copies an original record after storage succeeds. Category12 exposes numeric violation kind, privately resolved actor slots, position and direction. Kinds0/1 are eight_second_backcourt_violation / ten_second_backcourt_violation, verified by exact caller execution and controlled live expiry/UI calls. Kind13 is shot_clock_violation, supported by caller code, controlled expiry and a natural record/team-counter transition. Names describe the engine’s recorded call, not elapsed seconds inferred from a clock. Additional current names and actor limits are documented below; unsupported kinds remain unnamed. Storage completion still precedes completion of the surrounding handler.
  • stats.counter_changed / stats.counter_unchanged / stats.counter_unavailable report actual player-counter before/after values on installed paths. Stats include points, makes/attempts, rebounds, assists, steals, blocks, personal fouls and turnovers. A zero-count retraction is not a correction. Arithmetic wrap is explicit and is not named a basketball event. Credit/retraction does not identify a complete surrounding play or its causal correction target.
  • stats.team_counter_changed and corresponding unchanged/unavailable types report the separate team-only turnover counter. Do not assign it to a player or add it to an already inclusive total without checking your consumer's definition.
  • game.phase_changed and game.phase_reentered report committed phase-history changes. Codes remain numeric; phase is distinct from legal ball state.
  • engine.records_lost, engine.record_capture_failed and engine.capture_faults expose producer overflow or incomplete capture. A1,024-record source ring and10,000-event durable transport window are separate retention limits.

Every captured source record has a stable source_event_id within its process run. Public event IDs additionally identify durable delivery. home:slot and away:slot are not external player IDs; event-to-managed-timeline binding uses the ordered snapshot boundary; uncertain checkpoint/rematch intervals stay unbound or require review. Do not reuse a later roster mapping to reinterpret old events automatically. Before/after counter values are read at that counter's write boundary; team aggregates and other parts of the surrounding engine operation may still be pending. Points are read directly, not inferred as two/three times makes.

Experimental mutations

Supported commands include clock.set, shot_clock.set, slider.set, option.set, controller.set, camera.select, camera.set, preparation.set, roster.load, match.start, session.stop, coaching.set, defense.set, simulation.pause and simulation.resume. The following example is for clock commands; settings, coaching and launch have their own fields and guards. Acquire {client_id,ttl_seconds}; renew with the same client and returned lease token. Commands need:

{"command_id":"unique-command-1","client_id":"my-tool","lease_token":"...","run_id":"...","type":"clock.set","expected_period":1,"expected_value":120.0,"value":60.0}

The adapter requires private ABI v2 or newer and rechecks actual simulation pause, inactive replay gate, active simulation, phase10, raw period, exact current float, and an unchanged game clock for at least750ms. It writes once on the game thread and reads back. Bounds: game0–3600, shot0–120 seconds. Clock writes do not rewrite dependent rule state, rounded display caches, AI decisions or authoritative pause state. Use controlled test sessions. A frozen clock is not proof of a paused game.

Receipts are applied, rejected or indeterminate; applied means written/read back, not an entire rule transition validated. Accepted requests survive a crash, but unresolved ones become indeterminate and are never automatically replayed. Retry with the same command ID and identical body to retrieve its prior receipt. A changed body using that ID returns409. Never assume an indeterminate command failed or blindly retry under a new ID.

Scope still unavailable

Complete violation/correction coverage, uncovered legal transitions, unsupported custom-rule decision points and safe asset replacement remain unavailable. The implemented development53 interpreter and native SDK expose their supported scope through /v1/ball-state, /v1/rules and capability masks. Unsupported commands return422. These are explicit remaining engineering/research tasks, not features hidden behind an undocumented endpoint.

Verification

Run python -m unittest discover -s tests -v with this directory explicitly on sys.path on the Dell. Embedded Windows Python ignores ordinary PYTHONPATH; use the existing staged runner. Validate the canonical schema with schema/build_schema.py; see schema notes. Exact real-game evidence, compiler versions, platform coverage and failures are tracked in ../knowledge-base/API.md and ../analysis/api/. Tests with synthetic fixtures are distinguished from live Windows integration checks.

Ordered event identity (development adapter v3)

Each snapshot carries engine_event_boundary with the highest event sequence copied at the same game-thread publication boundary. Older adapters expose null. The broker defers newer events until their corresponding snapshot bracket arrives. Durable interval records bind eligible events to an explicit match and timeline revision, preserving the association across broker restarts and delayed delivery. This does not establish an engine-owned match ID or legal-ball state.

payload.context reports bound or unbound, match ID, timeline revision and reason. Bound actors carry external_player_id and external_team_id; team-only counters carry external_team_id. Events before binding, across an invalid/changed roster sample, after a reset requiring review, during pregame phases or without an ordered boundary remain unbound. Do not attach the current roster's IDs to those records. A consumer must still handle capture faults, ring overflow, cursor expiry and explicit timeline revisions. A recorded correction does not yet identify the earlier event it retracts.

The association is conservative: it can omit external IDs for valid plays around an uncertain boundary. It never retroactively turns an older unbound event into a bound event. Source event IDs remain stable within a process run; durable HTTP event cursors belong to one broker database.

Captured scoring by period

GET /v1/matches/{id} now exposes scoring_ledger; final results retain the reconciled ledger. This separates individual overtime periods using captured point-counter writes. It does not infer scoring periods from when HTTP requests arrive. A zero-score period-one binding with ABI3, continuous per-player counter chains, and agreement with player totals, regulation buckets and the engine's combined overtime bucket is required for status: reconciled. A late binding, missing point write, unknown correction, or inconsistent totals produces status: partial with explicit issues. Partial period sums must not be treated as complete score exports.

Each timeline revision starts its own ledger. Public event retention does not discard the ledger. Broker restart retains it; transaction rollback cannot double-count a credit. Finalization waits until ordered records have caught up to the snapshot watermark, then requires two stable final samples. These are observational splits; unsupported rule mutation points and authoritative correction lineage remain separate unfinished capabilities.

Free-throw schedule (corrected adapter v5)

During phase14 with attempts remaining, free_throws.award identifies the engine's scheduled shooter by shooter_player_key and the award code. Code1 is shooting; code4 is non_shooting_bonus, based on captured execution of8BDEB0. Other codes stay unnamed. This is an engine schedule observation, not legal live-ball state or proof of the original foul. Outside that phase, after the attempts finish, or with an older adapter, the award is null. Resolve external identity through the snapshot's player list. Build16 live testing exposed an incorrect phase8 gate; corrected to observed FT-administration phase14 in development17b. The corrected build passed a natural two-attempt shooting sequence: shooter identity, two FTM/FTA increments, and phase14→10 completion timing agree. Other award types still need live verification.

Engine parameter observations (private adapter v5)

rules.parameters reads the engine's period-duration parameter, full shot-clock reset parameter, conditional shot-clock minimum, raw backcourt/three-point selectors, and selected three-point geometry bank. Coordinates are in game_units, with oriented Z measured along the attacking direction. Selector names and league identities are intentionally not inferred. The four-point predicate's arc, corner and basket parameters were recovered separately; these values do not prove every shot/foul/AI/rendering path uses them. The conditional minimum is not a claim of a 14-second offensive-rebound rule. This is read-only; binding ruleset metadata does not modify these values. Legacy, unavailable or invalid snapshots return null parameters; individual nonfinite values are null. Native v5 default values passed nine independent live memory comparisons. A natural two-attempt shooting schedule passed 242 award-sample and five committed-counter checks; other original-game award paths retain their own limits; enabled college bonus/reset enforcement is documented separately below. /v1/session reports these read-only observation capabilities separately from rule mutation. snapshot.observed includes rule-parameter changes.

Named category12 records now include blocking_foul (kind19), corroborated by the original7A02A0 handler and exact live BLOCKING FOUL display in run17b, OT6.2s. The historical field name violation_record also contains foul records; clients must use kind_name, not infer a violation from the container name. The two actors on this proven path are the committing player and the affected player, respectively.

Rebound provenance in development18

Event mapping v2 adds category112 rebound-context records with resolved player slot, offensive/defensive classification, engine XYZ and offensive direction. These are context records, not additional rebound stat credits. Consume the committed stats.counter_changed event for a box-score change. Legacy mappings may supply a context with an unknown player; no identity is guessed.

For an observed negative rebound counter change, stat_change.correction_of_record_id can reference the earlier engine context selected by the original correction routine. Its format is run_id:source_event_sequence, matching payload.source_event_id on that context record. It is not a public HTTP stream cursor. Without the separately advertised original-credit linkage, correction_of_event_id remains null because context alone does not prove the original stat-credit event. With that linkage, use the distinct references documented below. No-op, wrapped, mismatched, stale/reused or uncaptured contexts receive no correction reference. A reference may precede client binding or event retention; use the referenced record's own context before associating external IDs. It does not establish whole-match event completeness.

Compiled synthetic tests execute the original history search, correction branches and counter arithmetic together with the new hooks. They do not establish natural live retraction coverage. Current evidence includes natural OR and controlled OR/DR retractions; the development18 boot/connectivity incident is retained in the historical integration log. Full causal basketball meanings and all correction paths are not inferred.

Original rebound-credit linkage in development20

Private event ABI3 appends the original counter source sequence to a rebound context only when the guarded original 796D50 owner observed exactly one nonwrapped unit credit for the same actor and OR/DR classification. The correction's original history lookup then selects that context. Public correction_of_record_id identifies the context; correction_of_stat_record_id identifies its original credit; correction_of_event_id identifies that credit's durable HTTP event when still retained. These IDs have different meanings. A missing/expired credit keeps its observed source reference without manufacturing a cursor. References can predate a match binding. Clients must retain their own replay history.

rebound_credit_linkage is separately capability-gated. Only OR/DR paths are covered. Compiled synthetic comparisons preserve the original credit-owner/counter/constructor execution, with game notifications and storage sink mocked; natural OR original-credit lineage and controlled OR/DR retractions are verified in the retained integration evidence; other paths have their own limits. Research19 independently demonstrated a controlled original defensive-rebound retraction from1 to0 with correct context/external actor, unchanged game clock, and the engine's shot-clock restoration. This forced original-routine fixture is not a natural officiating correction or a public mutation endpoint.

Development22 extends original-credit linkage to the instrumented block credit/retraction path (private event ABI4). The adapter requires matching remembered engine context, actor, counter preimage and period; changed or consumed context has no link. correction_of_stat_record_id references the original block counter source, while correction_of_event_id exists only if that credit remains in broker retention. Block corrections do not fabricate a rebound context (correction_of_record_id stays null). Capability discovery reports this separately. Synthetic original-path and broker tests pass; live block validation is pending. Natural OR and controlled OR/DR retractions have been observed, with original-credit linkage currently live-verified for OR.

Development24 additionally names category12 kind25 as shooting_foul. Actor0 is the committing player and actor1 the shooter on the verified original handler. Live23 record1944 matches the SHOOTING FOUL banner observed in the remote-desktop tool at Q4 43.8 seconds, Spurs17–Heat13; the following saved screenshot shows the made basket and substitution presentation, not that banner. Handler7A05F0 has28 captured-execution cases. The initial two-attempt schedule changed to one after Bosh's basket was credited: clients must not infer final attempt count from the foul record or phase18 provisional counters. Phase14 exposes the actual scheduled award; the final FT credit can occur after phase14 ends. This names a stored call, not a rule command or a causal foul-to-shot ID.

Experimental presentation and ball holder (development28a)

Snapshot presentation.state exposes observed pregame, inbound, play, period_ending, between_periods, halftime, free_throw, timeout, stoppage, or postgame; unsupported phases return null. Authority is observed_engine_phase, scope four_quarter_exhibition for the original profile or college_research_exhibition for a declared college profile. This is presentation evidence, not legal ball state. Pause and replay are separate fields. Timeout phase17 is named on the current implementation. Changes appear in existing snapshot.observed deltas. Clients should gate cues on fresh healthy snapshots and handle reconnects without replaying old sounds.

ball.holder is null or {player_key, team, authority: "physical_ball_attachment"} for an attached on-court roster player. It clears during flight and does not imply legal possession. Legacy legal ball.live and ball.legal_possession remain null. The new legal_ball surface has separate field validity and profile applicability.

Category12kind18 is reach_in_foul; kind7 is out_of_bounds. Their raw stop reasons are a different domain. Reach-in actors are committer then victim. An out-of-bounds record's first actor is selected by original handler logic, not guaranteed last toucher. These names retain their original-handler and live-record evidence from development28a; use the current verification ledger for the current API suite. Unknown kinds and universal actor roles are not inferred.

Settings development29 (experimental)

GET /v1/settings returns run_id, health, current settings (null when unavailable), and a catalog with stable IDs, labels, groups, ranges and write_supported. There are59 named sliders for user and CPU. All59 named sliders support slider.set on both sides; other settings are unfinished. Submit setting_id, side (user/cpu), integer value and expected_value (0–100), plus the standard command identity, client lease, run and expected period. Game must be paused in active non-replay play phase with frozen clocks. Commands invoke the original setter, report readback and reject stale preimages. They update the runtime profile; no explicit disk persistence guarantee. Changes appear in snapshot observations. Research30 passed all118 live user/CPU write/readback, duplicate identity, stale-preimage rejection and full-bank restoration cases. Six foul labels also have independent original-menu UI checks. Other labels retain community attribution and original-code evidence; individual UI checks and upstream gameplay effects are not all verified. No release or disk-persistence claim.

Gameplay and presentation options (development31, experimental)

GET /v1/settings also returns options and options_catalog. Snapshot options and snapshot.observed.changes.options contain current-game values. The catalog lists20 controls: difficulty, game speed, fatigue, injuries, shooting/FT timing mode, FT difficulty, six audio volumes, replay/camera-cut frequency, ball-handler text, FT help/routines, shot feedback and pick-and-roll overlay. Enum values have exact English labels in choices; ranges and steps are in menu units. A null value is unavailable, not zero. Older adapters return null options.

Use option.set with setting_id, integer expected_value and value, plus standard command ID, client ID, lease token, run ID and expected period. No user/CPU side applies to these global game settings. Commands require a paused, non-replay active play phase and750ms frozen clock, invoke original menu handlers on the game thread, and acknowledge readback. Poll the observed snapshot for convergence after acknowledgement. Writes affect this game only; there is no explicit saved-defaults command.

Example command fields, alongside the standard identity/lease/run fields: {"type":"option.set","setting_id":"commentary_volume","expected_value":100,"value":0,"expected_period":1}. A fresh snapshot supplies preconditions. An ambiguous receipt must be queried by the same command ID; never retry with a new ID blindly.

Startup presets and per-team coaching have their documented controls; live bulk presets, video settings, physical control bindings, exact rotation schedules and explicit settings persistence remain unfinished. Controller preferences have the separate capability described below. This is not the complete in-game settings API. Live verification is recorded in the project work log.

NBA Rules switches in development32

ABI8 extends the option catalog to39 controls, including all19 switches in the NBA Rules menu (the rule_ IDs). They use the same option.set command and guards, with values0=Off and1=On. Older adapters advertise these writes as unsupported. All39 controls passed live public write/readback, duplicate identity, stale-preimage rejection and restoration on Windows; all19 rule labels also matched the original menu after API changes.

Re-enabling the shot-clock switch invokes the original timer reset: in the live fixture it changed16.3547→24 seconds while the paused game clock stayed112.3547. This is an intentional side effect. These switches are current-game controls, not a complete configurable rules engine. No guarantee of disk persistence or every downstream call/AI effect is made.

Controller preferences (development33)

GET /v1/settings adds controllers and controllers_catalog. Snapshots/deltas include the same controller state. Each of ten stored preference slots has13 named settings. player_slot is0..9, corresponding to the game's stored controller configuration; it is not a roster player, team side, device identifier or proof that a controller is connected. The catalog supplies menu labels, integer choices and steps. Defensive assist uses0..100 in steps of5.

controller.set uses player_slot, setting_id, expected_value, value and the standard command/client/lease/run/period fields. For example, the setting-specific fields are {"type":"controller.set","player_slot":0,"setting_id":"automatic_shot_contest","expected_value":0,"value":2}. The same paused active-play/nonreplay/frozen-clock gates apply. Commands call the original setter on the game thread and verify readback; wait for the next observed snapshot after acknowledgement. Writes affect the loaded runtime profile; explicit disk persistence is not implemented. ABI8 and older advertise these writes as unsupported. Invalid or unavailable stored values are null.

All13 labels were independently mapped through the Player1 menu; original setters and compiled adapter tests cover ten slots. All130 setting/slot combinations passed live public writes, readback, duplicate identity, stale-preimage rejection and whole-bank restoration. A separate all13-value Player1 test matched the original menu; values were restored afterward. These checks do not establish device behavior or disk persistence. Camera/video/presets, control bindings and coaching settings are not covered by this controller capability.

Camera reads and controls (development34)

GET /v1/settings includes cameras_catalog for all26 original types, including Turbo, Showtime, Dunk Cam, Broadcast Dynamic, Drill High, Drill2K, Bench, Horse and Training Camp. These nine internal types are not in the ordinary exhibition selector and remain read-only. Catalog defaults are original descriptor defaults, not current values. Snapshot/settings cameras carries active_camera_id, menu_open, and runtime values keyed by stable camera/control IDs. Unsupported adapters return null. Engine indices and addresses remain private.

camera.select takes camera_id and expected_camera_id. camera.set takes camera_id, setting_id, expected_value and value. Both require the standard command/client/lease/run/expected_period fields. Example selection fields: {"type":"camera.select","camera_id":"2k","expected_camera_id":"broadcast_stadium"}. Example control fields: {"type":"camera.set","camera_id":"2k","setting_id":"zoom","expected_value":3,"value":4}.

Selection is restricted to the17 exhibition types and the original eligibility check. A control must be configurable for that camera and the camera must currently be active. Commands require paused phase10, nonreplay, a750ms frozen game clock, Player1 input ownership and the camera menu closed. Commands on inactive/internal types are refused. All six control IDs are zoom, height, key_zoom, reverse_angle, auto_flip, fixed_height; consult each entry's ranges. No arbitrary camera transforms or renderer internals are exposed.

Live HTTP verification covers17 selections and63 configurable camera/control combinations, duplicate identity, stale rejection and restoration of the entire bank. All six2K values matched the original menu and resumed play rendered that view. This is not independent visual validation of every effect on every camera/mode. Changes are runtime only; acknowledgement can precede the next snapshot.

Timeout context and five-second inbound violation (development34)

During valid phase17, snapshot/deltas expose timeout with team, kind, seconds_remaining and engine-context authority. Normal kinds are short/full; unknown kinds remain null, including the observed internal kind2 transition. The kind describes the current engine timeout context, not which timeout pool was charged. A late-Q4 live fixture consumed the short pool while later reporting full with a60-second countdown. Pool deductions can lag entry; clients must observe the separate team counters. This is the original countdown, not a promise of frame-exact synchronization with a remote screen. Null team/type/timer is unavailable, never inferred. Outside timeout phase the context is null. This does not establish legal ball state or who originally pressed a timeout button.

Category12kind8 is five_second_inbound_violation. Four live records were corroborated by 5-Sec Violation property/localization requests, reason20 and the original79D360 handler. Actor0 is its input actor (away in the recorded fixtures); actor1 is null. Do not relabel this as closely guarded or back-to-basket five seconds. Original-handler tests exercise record/turnover/phase behavior with downstream mocks; they do not establish every upstream timer exemption.

Pregame match configuration — development37 / ABI15

GET /v1/preparation is separate from live-game snapshots. Its health can be ready while the inactive game snapshot is invalid. For the legacy preparation-only workflow, open Quick Game before applying; entering Quick from Home can reset native defaults. ABI16 load/Start clients can prepare directly from Home after guarded roster loading. Current ABI15 responses add both team/uniform row selections, Game Style, counts and catalog generation. Older ABI11–14 adapters retain the original eight controls.

Setting ID Values
difficulty 0 Rookie,1 Pro,2 All-Star,3 Superstar,4 Hall of Fame
game_style 0 Default,1 Simulation,2 Casual,3 Custom; original preset transition applies both slider banks
game_speed Integer0–100
quarter_length_minutes Integer1–12; original quarter setting, not college half duration
fatigue, injuries Integer0/1
arena Current writable arena:N choice
home_playbook, away_playbook Current writable playbook:N choice
home_team, away_team Writable team-row:N from loaded catalog
home_uniform, away_uniform Writable uniform-row:N matching that team's graphics set

Read paged choices with GET /v1/preparation/catalog?kind=teams&start=0&catalog_id=<current-id> (or kind=uniforms). Pages include run/revision/catalog identity, total, items and next_start; at most64 rows. Items supply id, row, record_id, graphics_id, writable, away, label and resource. Uniform labels/resources come from loaded texture names, not a curated alternate-name database. Follow next_start until null. Refuse stale catalog/run contexts and re-enumerate after changes. Counts are bounded at2048 teams/65535 uniforms in this extension; these bounds are not a verified maximum playable roster.

Rows identify the current physical native table, not durable external IDs. teams.side.row_id is the team selection identity; legacy teams.side.id encodes graphics-set ID and remains for compatibility. game_style_code is deprecated raw options data, not the menu preset; use values.game_style. Catalog generation detects loaded team/uniform bank changes within a run, not cryptographic identity of the on-disk ROS. Existing arena/playbook IDs/labels also belong to that roster. Stock provides102 arenas/45 writable and69 books/67 writable. The inherited arena/book catalogs each admit at most128 rows; exceeding either makes preparation unavailable. Expanded-team acceptance reuses those compatible catalogs. Inspect writable rather than assuming all records are eligible.

Acquire /v1/control/lease, then POST /v1/commands with type: preparation.set, unique command/client/lease IDs, current run, expected_revision, setting_id, expected_value and value. Original handlers execute on the game thread, guarded by code bytes, valid exhibition setup, inactive simulation, expiry, exact revision/preimage and choice eligibility. Team setters resolve default uniforms, so apply both teams before explicit uniforms and arena/playbooks. CAT uniform entries and foreign graphics sets are refused. Team selection supports regular exhibition records with five valid distinct starters. The complete SDK plan requires two distinct teams; single setters permit temporary mirrored selections during swaps.

Wait for fresh readback between commands. Identical command ID/body returns its original receipt; do not blindly reissue an indeterminate command under a new ID. Commands are sequential: earlier successes can remain after later failure. Configuration is runtime-only; no save or automatic rollback is promised. Active simulation refuses preparation writes.

Independent examples/prepare_matchup.py and openhoops_api.match_plan export, preflight and apply versioned plans using public endpoints only. Plans contain format/version/run/catalog identity and values; unknown members, duplicate JSON and nonfinite numbers refuse validation. Preflight checks every requested choice before writes, then runtime context is rechecked throughout:

python examples/prepare_matchup.py --token-file <private-token-file> --export matchup.json
# Edit values using current catalog choices.
python examples/prepare_matchup.py --token-file <private-token-file> --validate matchup.json
python examples/prepare_matchup.py --token-file <private-token-file> --apply matchup.json

Failures preserve completed receipts; successful output reports lease release and launch_supported:false. That helper does not load or Start; use the separate ABI16 launch_match SDK for the complete flow. The older prepare_match.py retains its eight-control compatibility workflow. For working-copy starting order/native minutes, use the separate roster preparation writer before loading. Native minute preferences do not guarantee substitutions. Quick Game3D uniform previews can lag API selection; actual alternates loaded correctly in44c. Native extra-field consumption remains unfinished; phase4 binding now has separate managed-start guards in the request workflow; ABI16 direct launch is separate from this preparation-only helper.

Current verification:307 API tests,30 compiled preparation/catalog cases,116 writer tests and35 schemas; live stock13-control setup and generated905-team final-participant startup with requested starters/order/minutes. Native Simulation matched all126 profile values. Historical35 evidence retains212 preparation round trips,292 original-handler/80 compiled cases and selected arena/runtime playbook comparisons. Neither this short live check nor preset readback certifies every AI play, full-match stability or exact rotation behavior.

College configuration — development36 / profile4 / ABI14

College hooks require compile-time OPENHOOPS_COLLEGE_RESEARCH and the exe-local file openhoops/college-research.ini:

[CollegeResearch]
Enabled=1
HalfMinutes=20
MediaTimeouts=4

Configure with the game closed and restart. HalfMinutes accepts1–20. OT is1 minute for1–4 minute halves,2 for5–8,3 for9–12,4 for13–16 and5 for17–20; each later OT has the same duration. The generic preparation field quarter_length_minutes does not configure college half length. No college profile-selection/duration-write HTTP command exists yet. Match-binding ruleset is client provenance and does not install rules.

rules.profile is absent on ABI1–11, null when unavailable, original_game for a disabled declared profile and openhoops_college_research when enabled. Revision4 has reference-tested regulation/OT export support; full-rulebook certification remains false. final_exports_verified describes reference-scenario evidence, not the current match's finality or a binary fingerprint. Stored historical results retain their original declarations. Read verification-field meanings.

rules.period supplies logical half/OT and boundary state. Existing raw_period remains1/3 for halves and5+ for OT, with transient end-state increments; it must not be treated as a display period. Native scoring_buckets.regulation still has four entries; additive regulation_periods and ledger logical_periods describe the two halves without phantom quarters. A finished raw6 can describe completedOT1. Some original UI screens still say quarters.

teams.*.bonus.against_team is none, one_and_one at7–9 qualifying fouls, or double_bonus at10+. It describes the penalty reached against that team, not whether every subsequent foul merits FT. Scheduled kind3 is named one_and_one only with a declared college profile; kind4 is double_bonus. No legal ball-state inference follows from bonus, phase or FT schedule.

Media timeouts — ABI13+, current profile4

rules.media_timeouts reports explicit scheduler provenance; do not label unknown stock timeout kind2 as a TV break. active_break.reason is scheduled_mark, first_team_timeout, or profile4 injury_timeout. It includes actual allowance-charge metadata, optional scheduled-mark number and timeout seconds remaining. Ordinary timeout and team allowance pools remain separate observations.

MediaTimeouts=4 uses under16/12/8/4 marks strictly below the starting half clock:10-minute halves use under8/4;8-minute halves use under4. Optional 3 uses under15/10/5;0 disables the scheduler. Revision1 recordings used proportional marks; revisions2+ use shortened_half_policy: fixed_clock_marks. marks_seconds_remaining, scheduled_breaks_per_half, state_raw_period and served_mark_numbers describe the actual configured/served marks. Breaks wait for eligible dead-ball contexts and last60 seconds; they do not forcibly stop live play at a clock threshold.

Four natural uncharged TV breaks in earlier36bl automatically returned to FT/inbound/play. Current ownership/refund code passes10,800 original-state/allowance and compiled cases with documented UI/eligibility/dispatch mocks. Rare live injury/refund integration is unverified. A refunded break updates ownership/allowance metadata; the original engine record still observes its initial charge and is not fabricated into a retraction. complete_rulebook_verified remains false. Older adapters omit the field; unavailable/noncollege state yields null.

Court observations and one-texture authoring — ABI14 / definition3

rules.court shares the measured NCAA2026–27 definition with the compact template. The independently versioned court definition3 keeps revision2 world dimensions and supplies the compact UV mapping; the current rule profile is4. Matching artwork/IFF uses8192×4096 pixels over128×64ft; the94×50ft playing rectangle occupies6016×3200pixels. Court art must use the compatible UV mesh; hooks do not repaint arbitrary legacy floors.

rules.court_observation exposes original boundary dimensions, offensive direction and legacy basket reference. On-court players may expose four transformed contact samples and boundary projections. These are engine observations, not a legal airborne/OOB event or a new shot-value event. Both-end final-release scoring tests passed all18 arc/corner inside/onpaint/outside cases; actual original scoring/stat paths ran after controlled placements, and six makes matched2/3point credits.

The reference compact IFF rendered at8K/11mips.8K needs both [Graphics] MaximumTextureSize=8192 in openhoops/graphics.ini and saved VIDEOSETTING_MAXTEXTURESIZE=8192, ADJUST_VIDEO_SETTINGS=0 in saves/Config.cfg, with backups and restart. Texture/court imports are not HTTP commands. Runtime live_texture_alignment_verified stays false because the API does not identify arbitrary currently loaded art; reference success is recorded in the evidence ledger. Physical basket assets remain unchanged; legacy basket reference differs from diagram nominal center by about¾in. Actor-center, anatomical and airborne boundary conventions are not exhaustively certified.

Current limits and evidence

The agreed college mechanics are in place. Deferred rare live checks and the optional production full-game smoke are verification limits, not declarations that all TV, court or export work is missing. Existing full-rulebook/capability complete flags stay false. Latest36ct had natural clocks/scores/outcomes,46 temporary public settings plus46 restorations and no private actions during the managed match; the subsequent separate unbound fixture is not part of its legitimate export evidence. Original files and95 saves were restored. No public release or additional live run is required for this documentation update. See verification, college implementation and remaining API work.