Skip to main content

Endgate Prototype

Endgate is a focused SECS v2 prototype for authority, deterministic map pressure, SignalR transport, a small browser client, and benchmark coverage. It is intentionally narrower than Valenar: the goal is to keep a truthful, runnable shell for host/session/router behavior, map snapshots, defender commands, and pressure-wave simulation.

Endgate now uses the SECS compiler for schema-owned generated output. Authored .secs content lives under Content/, and Generated/Endgate.Generated.csproj runs secsc to emit the schema/runtime C# consumed by the host, server, tests, and benchmarks. Retained files under Generated/ are explicit non-schema host/catalog helpers.

Subprojects

  • Content/ contains the committed Endgate .secs surfaces, including run_state.secs, defender_root.secs, base_objective.secs, wave_settings.secs, wave_script_fields.secs, and wave_scripts.secs (the per-wave script catalog).
  • Generated/ builds compiler-owned schema output and retains explicit non-schema catalogs. Wave lookup helpers live in Generated/WaveScripts.cs; the wave script records and settings defaults are compiler-emitted author types.
  • Host/ contains EndgateGameHost and the authority/simulation models that drive runtime state.
  • Server/ hosts the ASP.NET Core SignalR surface and the live session/router services.
  • Client/ is the React/Vite browser shell that connects through @microsoft/signalr.
  • Benchmarks/ contains the BenchmarkDotNet authority benchmarks.

Current Prototype Scope

  • Bootstrap wiring: the compiler-owned host schema, retained catalogs, session, router, and server contracts form a buildable shell.
  • Deterministic map generation: seeded runs produce stable blocked cells, edge spawn arcs, village parcels, roads, and horde routes.
  • Pressure routing: live-state queries, map-snapshot queries, world-space character movement, building/parcel commands, and steady-state ticks run through the host/session/router path.
  • Wave loop: win advances currentWave; loss pays energy, increments waveAttempt, and retries the same saved wave definition.
  • Fatal runtime faults: tick failures mark the session faulted, write a JSON fault report through the shared SECS runtime fault-report projection, and stop the hosted simulation loop.
  • Browser shell coverage: the client is a React/Vite tactical map surface for the Endgate SignalR session.
  • Benchmark coverage: the authority benchmark suite measures live snapshot queries, map snapshot queries, defender assignment, steady-state ticks, and map regeneration.

These slices are backed by the focused Endgate server contract tests under tests/Endgate.Server.Tests/, tests/Endgate.Server.Tests/SignalRWireContractTests.cs, tests/Endgate.Server.Tests/GameSessionRuntimeFailureTests.cs, and examples/endgate/Benchmarks/EndgateAuthorityBenchmarks.cs.

Active Work Loop

Documentation index: docs/README.md.

CategoryDocs
Game systemsdocs/systems/ — wave loop, village building, characters, combat, map, progression
UX screensdocs/ux/ — shell/panels, tactical viewport, HUD
Contractsarchitecture.md, secs-contracts.md

AI / agent testing: use docs/agent-playtest-protocol.md to run window.__endgateCapture.runPlaytestSuite() against the dev client and read ranked recommendations for the next core-loop wave.

The target design is the realtime village loop with wave-reset persistent village. Each system doc under docs/systems/ describes both shipped baseline and target direction. The shipped prototype still uses manual wave start and instant build until RTL waves land.

The current shipped loop is the AAA-quality top-down Three.js village-defense shell: win advances to the next wave; loss pays energy and returns to planning so the same wave can be retried after upgrades, repair, expansion, and character repositioning.

Running

Run the server and client in separate terminals from the workspace root.

Server

dotnet run --project examples/endgate/Server

examples/endgate/Server/Program.cs maps the SignalR hub at /gamehub, exposes a /health endpoint, and defaults to http://localhost:5064 when urls / ASPNETCORE_URLS is not set.

Client

cd examples/endgate/Client && npm install && npm run dev

The client is a React 19 + Vite app that uses @microsoft/signalr to connect to the Endgate server. It serves the app on http://localhost:5178/endgate/ and proxies /endgate/gamehub back to the ASP.NET Core server on http://localhost:5064.

For a persistent dev session, use the Zellij session host-endgate (one full-width tab for the server, one for the client — not split panes):

bash scripts/run-endgate-dev.sh start # create session + tabs if needed
bash scripts/run-endgate-dev.sh attach
bash scripts/run-endgate-dev.sh restart # after crashes or old pane layouts

See docs/project/pr-zellij-dev-sessions.md for session names, ports, and Valenar parity.

Tailnet routing is managed from the workspace host manifest. After run-endgate-dev.sh start:

bash scripts/host-tailscale.sh apply

Open https://herki-pc-ubuntu.taila0ab6f.ts.net/ for the project menu, or /endgate/ for Endgate directly. See docs/project/pr-tailscale-host-routing.md.

Tests and Benchmarks

Server-contract coverage:

dotnet test tests/Endgate.Server.Tests/Endgate.Server.Tests.csproj

Generated provenance and wave-script sync guards:

dotnet test tests/SECS.Standalone.Tests/SECS.Standalone.Tests.csproj --filter FullyQualifiedName~EndgateGeneratedProvenanceGuardTests
dotnet test tests/SECS.Standalone.Tests/SECS.Standalone.Tests.csproj --filter FullyQualifiedName~EndgateWaveScriptSourceSyncGuardTests

Authority benchmarks:

dotnet run --project examples/endgate/Benchmarks/Endgate.Benchmarks.csproj -c Release

Content and Generated

Content/*.secs files are the committed authored inputs for Endgate schema rows. Generated/Endgate.Generated.csproj invokes secsc build --generated-namespace Endgate.Generated, includes the emitted C# from obj/**/SecsGenerated, and exposes Endgate.Generated.SecsModule.BuildSchema().

Only explicit non-schema host/catalog helpers remain hand-maintained under Generated/, currently item definition catalogs and wave-script lookup mappings. Those retained files may reference compiler-emitted IDs, but they must not construct schema row families or replace SecsModule.BuildSchema().