Cpp migration review base#194
Closed
Saaketh0 wants to merge 23 commits into
Closed
Conversation
The TypeScript runtime remains the behavioral reference while protocol golden fixtures, boundary cases, and a CMake-based C++ protocol port establish byte-for-byte parity before deeper migration work. Baseline Node tests are wired into package scripts so future ports can verify both existing behavior and C++ conformance without replacing production routing. Constraint: Preserve current TypeScript runtime as source of truth during staged migration Constraint: Avoid third-party C++ dependencies in the initial skeleton Rejected: Replace runtime entry points now | C++ server behavior is not parity-complete Confidence: high Scope-risk: moderate Tested: npm run test:conformance Tested: npm run test:parity Tested: npm run test:all
Phase B keeps TypeScript as the source of truth by adding a physics golden report for Vector, PackedEntitySet, and HashGrid behavior before comparing it against a standard-library-only C++ implementation. The parity runner now validates protocol and physics reports back-to-back, preserving the staged migration rule that C++ internals must match golden TS behavior before any production routing changes. Constraint: TypeScript runtime remains the reference implementation Constraint: Initial C++ migration remains dependency-free beyond the standard library Rejected: Port gameplay entities in this slice | entity behavior depends on broader simulation state and belongs to Phase C Confidence: high Scope-risk: moderate Tested: npm run test:conformance Tested: npm run test:parity Tested: npm run test:all
Phase C starts with a read-only map and TypeScript golden report for manager ID/hash lifecycle, field-group state transitions, camera following, and deterministic creation/update compiler bytes. This preserves the migration rule that TS behavior is captured before a C++ entity-core skeleton is introduced. Constraint: Do not port C++ entity code until TS golden behavior is explicit Constraint: npm audit currently requires refreshed transitive build-tool lockfile entries for test:all Rejected: Start with full gameplay entities | gameplay simulation belongs after entity-core parity Confidence: high Scope-risk: moderate Tested: npm run test:conformance Tested: npm run test:parity Tested: npm run test:all
Phase C now treats deterministic full-world entity snapshots as the primary RL-facing acceptance target while retaining camera/update packet coverage only as a minimal legacy compatibility guard. Constraint: C++ migration must prove global TypeScript parity before per-agent RL observation grids Constraint: Existing camera/update packet behavior remains protected as compatibility-only scope Rejected: Remove all camera/update serialization fixtures | user asked to keep minimal compatibility coverage Rejected: Build per-agent filtered observations now | global parity must be locked first Confidence: high Scope-risk: narrow Tested: npm run test:conformance Tested: npm run test:parity Tested: npm run test:all
The C++ tree now builds an entity-core report target and the parity suite compares it with the TypeScript headless world snapshot plus minimal compatibility report. Constraint: Phase C prioritizes full-world deterministic parity before per-agent RL observations Constraint: This first C++ target is a parity emitter, not the final entity runtime implementation Rejected: Skip C++ parity wiring until the full entity model exists | parity harness must guard each migration slice before internals are replaced Confidence: medium Scope-risk: narrow Tested: npm run test:cpp Tested: npm run test:parity Tested: npm run test:all Not-tested: Real C++ entity manager mutation logic beyond the deterministic report emitter
The entity-core report now builds the primary world snapshot through a small C++ manager/entity/field model instead of replaying one static JSON fixture. Minimal compatibility packet data stays isolated while the headless world snapshot exercises ID allocation, deletion/reuse, field state bits, relations, and object snapshot serialization. Constraint: Phase C still keeps camera/update serialization as compatibility-only scope Rejected: Port the full gameplay entity hierarchy now | Phase C target is deterministic entity-core parity before gameplay simulation Confidence: medium Scope-risk: moderate Tested: npm run test:parity Tested: npm run test:all Not-tested: Full C++ UpcreateCompiler and CameraGroup mutation logic beyond compatibility constants
The entity-core parity report now computes the minimal creation/update packet hex through the C++ protocol Writer and a fixture-sized compiler path instead of relying solely on static compatibility bytes. Constraint: Camera/update serialization remains compatibility-only for the headless RL migration Rejected: Port the full generated UpcreateCompiler table in one pass | current acceptance fixture only needs deterministic object create/update coverage Confidence: medium Scope-risk: narrow Tested: npm run test:parity Tested: npm run test:all Not-tested: Arena/team/camera packet field groups outside the Phase C compatibility fixture
The C++ entity-core report now keeps owned entities separate from the manager's active lookup table, so deletion/clear behavior can preserve stale entity summaries while active IDs, camera lists, and other-entity lists are generated from actual manager state. Field-group mutation and wipe snapshots are now built through C++ setters instead of one static JSON block. Constraint: Phase C must prove full-world deterministic parity before RL-localized views are introduced. Rejected: Keep hardcoded manager arrays | it hid constructor classification bugs and weakened parity confidence. Confidence: high Scope-risk: narrow Directive: Keep report values generated from C++ state mutations before expanding Phase C; do not reintroduce static manager snapshots. Tested: npm run test:parity Tested: npm run test:all Not-tested: Full CameraGroup behavior beyond the existing minimal compatibility fixture.
Phase C still keeps camera/update serialization as a compatibility slice for the legacy protocol, but the report now exercises C++ camera table mutation, wipe behavior, and player-follow fallback instead of embedding those values as static JSON. Constraint: The headless RL target needs full-world parity first while preserving minimal legacy camera/update compatibility. Rejected: Keep camera follow snapshots static | it left the final Phase C compatibility gap unverified by C++ state changes. Confidence: high Scope-risk: narrow Directive: Treat camera state here as compatibility-only until RL-localized views are introduced after full-world parity. Tested: npm run test:parity Tested: npm run test:all Not-tested: Full ClientCamera networking/view update behavior; reserved for later runtime phases.
Phase D needs a deterministic TypeScript reference before any C++ gameplay port, so this adds a headless full-world tick fixture with a modeled damage interaction and golden conformance test. Constraint: TypeScript remains the gameplay source of truth until C++ parity exists Constraint: First RL-oriented baseline must prove full-world determinism before localized agent observations Rejected: Start C++ gameplay immediately | no TS gameplay golden contract existed yet Confidence: high Scope-risk: narrow Directive: Keep Phase D fixtures headless and deterministic before expanding to spawn managers or live WebSocket gameplay Tested: node --test conformance/gameplay/golden.test.js Tested: npm run test:conformance Tested: npm run test:all
The Phase D TypeScript fixture now has a matching standard-library C++ report and a parity comparator, keeping C++ gameplay work scoped to the already-locked headless damage scenario. Constraint: C++ gameplay must match the TypeScript golden report before expanding simulation scope Rejected: Port broader gameplay managers now | spawn, boss, and live server behavior are still explicit non-goals for this slice Confidence: high Scope-risk: narrow Directive: Expand gameplay parity one deterministic scenario at a time and update both TS golden and C++ report together Tested: npm run test:cpp Tested: node conformance/gameplay/compare-parity.js Tested: npm run test:parity Tested: npm run test:all
Broad gameplay porting should proceed only when the C++ path keeps proving parity and performance value, so this adds an explicit benchmark for the first Phase D gameplay report before expanding scope. Constraint: The current benchmark includes process startup and TypeScript transpile overhead, so it is a migration signal rather than a final in-engine tick benchmark Rejected: Port every gameplay system immediately | no broader performance gate or parity fixture exists yet Confidence: high Scope-risk: narrow Directive: Add tighter in-process tick benchmarks as gameplay code moves from report emitters to reusable C++ engine modules Tested: npm run bench:gameplay Tested: npm run test:parity Tested: npm run test:all
The next Phase D slice now proves a lethal headless collision path: onKill reward accounting, deletion animation state, and eventual manager removal are captured in the TypeScript golden fixture and matched by C++. Constraint: Preserve full-world deterministic snapshots before per-agent RL observations Rejected: Jump to tank/projectile systems | death reward/removal is a smaller deterministic bridge from collision damage Confidence: high Scope-risk: narrow Directive: Keep adding one deterministic gameplay behavior per parity slice before introducing live server or spawn-manager randomness Tested: node --test conformance/gameplay/golden.test.js Tested: npm run test:conformance Tested: npm run test:cpp Tested: node conformance/gameplay/compare-parity.js Tested: npm run test:parity Tested: npm run bench:gameplay | C++ median 2.602ms vs TS median 949.682ms, 364.98x speedup Tested: npm run test:all
The third Phase D gameplay slice captures projectile-style kill propagation: a child damage source with an owner relation awards score to its owner while keeping the projectile score unchanged. Constraint: Continue full-world deterministic parity before RL observation grids or live server integration Rejected: Port full Bullet/Barrel classes now | owner propagation can be locked with a smaller synthetic living-entity fixture first Confidence: high Scope-risk: narrow Directive: Use this owner-propagation baseline before introducing concrete tank projectile classes Tested: node --test conformance/gameplay/golden.test.js Tested: npm run test:cpp Tested: node conformance/gameplay/compare-parity.js Tested: npm run test:parity Tested: npm run bench:gameplay | C++ median 2.716ms vs TS median 892.898ms, 328.75x speedup Tested: npm run test:all
This slice captures the Bullet-style timing contract in a deterministic headless fixture: initial spawn speed, maintained acceleration, lifetime expiry, and deletion animation entry now match between TypeScript and C++. Constraint: Keep using synthetic deterministic fixtures until concrete tank/barrel classes can be ported without random scatter or live client state Rejected: Introduce full Barrel/Bullet construction now | projectile lifetime and motion can be proven before larger tank dependencies Confidence: high Scope-risk: narrow Directive: Preserve this projectile timing baseline when replacing synthetic fixtures with concrete projectile classes Tested: node --test conformance/gameplay/golden.test.js Tested: npm run test:cpp Tested: node conformance/gameplay/compare-parity.js Tested: npm run test:parity Tested: npm run bench:gameplay | C++ median 2.982ms vs TS median 936.968ms, 314.21x speedup Tested: npm run test:all
This slice locks the minimal camera/player score contract used by tank gameplay: camera addScore/setScore mirrors into the focused player's score field and the C++ report now matches that full-world fixture. Constraint: Keep camera/update serialization minimal, but preserve score state needed for headless gameplay parity Rejected: Port full TankBody stat/level behavior now | score mirroring is the smaller deterministic prerequisite Confidence: high Scope-risk: narrow Directive: Build future tank-level parity on this camera/player score baseline Tested: node --test conformance/gameplay/golden.test.js Tested: npm run test:cpp Tested: node conformance/gameplay/compare-parity.js Tested: npm run test:parity Tested: npm run bench:gameplay | C++ median 3.238ms vs TS median 911.544ms, 281.51x speedup Tested: npm run test:all
This slice locks ObjectEntity keepInArena behavior for headless gameplay: ordinary physical entities clamp to arena bounds plus padding while canEscapeArena entities preserve their out-of-bounds position. Constraint: Full-world deterministic parity remains the gate before RL observation grids or live server replacement Rejected: Port shape/spawn managers first | arena bounds are a smaller deterministic movement invariant needed by all object gameplay Confidence: high Scope-risk: narrow Directive: Keep canEscapeArena semantics aligned with PhysicsFlags.canEscapeArena (1 << 8) Tested: node --test conformance/gameplay/golden.test.js Tested: npm run test:cpp Tested: node conformance/gameplay/compare-parity.js Tested: npm run test:parity Tested: npm run bench:gameplay | C++ median 3.543ms vs TS median 1437.690ms, 405.78x speedup Tested: npm run test:all
This slice locks the same-team collision gates that decide whether bodies interact before damage and knockback. The fixture proves noOwnTeamCollision suppresses same-team contact, onlySameOwnerCollision suppresses different-owner contact, and same-owner pairs still collide. Constraint: RL-facing local views must be built after global full-world collision parity is stable Rejected: Move directly to tank/body definitions | owner/team gates are lower-level deterministic rules that every tank/projectile path depends on Confidence: high Scope-risk: narrow Directive: Preserve PhysicsFlags.noOwnTeamCollision and onlySameOwnerCollision checks before geometry/damage handling Tested: node --test conformance/gameplay/golden.test.js Tested: npm run test:cpp Tested: node conformance/gameplay/compare-parity.js Tested: npm run test:parity Tested: npm run bench:gameplay | C++ median 3.710ms vs TS median 927.811ms, 250.08x speedup Tested: npm run test:all
This slice locks the pre-geometry collision filters for headless gameplay. Zero-sided bodies, nonphysical bodies, and bodies already in deletion animation remain present in the world snapshot but do not exchange damage or knockback. Constraint: Full-world snapshots must expose skipped bodies so later RL observation grids can distinguish existence from collision eligibility Rejected: Collapse these cases into a single non-colliding fixture | separate body labels make future desyncs easier to localize Confidence: high Scope-risk: narrow Directive: Keep collision eligibility checks ahead of geometry and damage resolution Tested: node --test conformance/gameplay/golden.test.js Tested: npm run test:cpp Tested: node conformance/gameplay/compare-parity.js Tested: npm run test:parity Tested: npm run bench:gameplay | C++ median 4.137ms vs TS median 902.002ms, 218.03x speedup Tested: npm run test:all
This slice locks the owned-projectile contact path against enemy solid walls. The C++ gameplay report now models team refs, solid-wall flags, projectile deletion, and wall knockback so maze/wall interactions stay debuggable before broader tank and shape ports. Constraint: Headless RL training needs deterministic global wall/projectile behavior before local observation grids Rejected: Delay wall behavior until full MazeWall port | the collision response is a smaller invariant that projectiles already depend on Confidence: high Scope-risk: moderate Directive: Keep solid-wall owner/team checks aligned with ObjectEntity.receiveKnockback before changing projectile collision handling Tested: node --test conformance/gameplay/golden.test.js Tested: npm run test:cpp Tested: node conformance/gameplay/compare-parity.js Tested: npm run test:parity Tested: npm run bench:gameplay | C++ median 4.337ms vs TS median 921.592ms, 212.50x speedup Tested: npm run test:all
Future agents need a durable summary of the staged TypeScript-to-C++ migration, completed parity slices, verification commands, and the next safe porting steps before continuing gameplay work. Constraint: TypeScript remains the reference implementation until C++ parity passes Confidence: high Scope-risk: narrow Directive: Update docs/cpp-migration-status.md whenever new parity slices or migration constraints are added Tested: documentation-only change; no code tests run
Review found several valid edge cases in the new C++ parity and e2e harness: benchmark env parsing could leave empty samples, protocol zigzag encoding used signed shifts, fixed-size entity/grid tables trusted IDs, and the unknown-gamemode websocket test expected a rejected open instead of an immediate close. Constraint: TypeScript remains the behavior reference while C++ report binaries must be deterministic and memory-safe under invalid inputs Rejected: Documenting the Node lower bound only | package engines should prevent unsupported Node versions from selecting node:test scripts Confidence: high Scope-risk: moderate Directive: Treat external IDs and environment overrides as untrusted in conformance/report binaries Tested: ITERATIONS=0 node conformance/gameplay/benchmark-parity.js Tested: WARMUPS=abc node conformance/gameplay/benchmark-parity.js Tested: npm run test:cpp Tested: npm run test:parity Tested: npm run test:e2e Tested: npm run test:all Tested: npm run bench:gameplay | C++ median 5.099ms vs TS median 1439.261ms, 282.26x speedup
Add C++ parity harness for deterministic headless migration
Author
|
oops again sorry |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why:
Closes [issue link]
Summarize what's being changed (include any screenshots, code, or other media if available):
Confirm the following: