Skip to main content

SECS — Scripting Engine C Sharp

A game-agnostic scripting and modding engine inspired by Paradox games (CK3, EU4, Victoria 3). SECS uses modified C# as its scripting language — .secs files are real C# with extensions for game scripting. The SECS compiler transpiles them to standard C# that integrates with the engine runtime.

Status: The v2 runtime is built and tested (SECS.Core, SECS.Native, SECS.Schema, SECS.Kernel, SECS.Runtime, SECS.Adapters.Standalone, SECS.Compiler.Contracts — per AD-0006). The 6-phase HardOverride channel pipeline and activity/policy mod finalization are implemented. The Roslyn fork is present as secs-roslyn/; Phase 1 ships the current backed .secs compiler slice and emits schema-owned generated output for the active examples. Broader language lowering remains future work. See TASKS.md for current status.

The v2 kernel / runtime / schema / native / standalone assemblies are the active architecture; examples/valenar-v2/Server is an ASP.NET Core SignalR hub at /gamehub wrapping the v2 runtime, and examples/valenar-v2/Client is the React/SignalR Valenar frontend pointed at that hub through @microsoft/signalr + zustand. Implemented v2 domains include shell, character sheet, skills, inventory starter/equip/use/move/static item definitions, retained policy catalog/rule dispatch, activity catalog/runs/queue, pending choices, tooltip, time-bank and game speed, graph travel, map geometry/biomes/hierarchy, Territory knowledge, source-authored forced Feature follow-through, Stage-0 objectives, session milestone journal, MakeCamp-created camp state plus Rest, direct combat preview/resolve plus auto-resolved travel encounters, bootstrapped settlement/building, and retained economy systems through market scaffold. Retired deletion-target surfaces are recorded in the v1 deletion gate.

Active v2 work lives at top-level src/, tests/, examples/, and unity/. Unity-hosted game packages under unity/ are adapters/examples around the deterministic SECS engine; engine authority remains in src/SECS.*. New work targets v2 — see docs/adr/ad-0006-secs-v2-kernel-rewrite.md.

Architecture

src/
SECS.Core/ Typed IDs, FNV-1a hash, shared types — netstandard2.1
SECS.Native/ SECS-owned native collections (managed-backed initially) — netstandard2.1
SECS.Schema/ WorldSchema and schema row types — netstandard2.1
SECS.Kernel/ Deterministic semantic kernel (entity table, relations, modifier indexes,
channel snapshots, command journal, save sections) — netstandard2.1
SECS.Runtime/ Runtime coordinator (tick pipeline, channel resolver, event/activity/policy
dispatch, mod registry) — netstandard2.1
SECS.Adapters.Standalone/ Reference adapter for standalone C#/ASP.NET Core — net8.0
SECS.Compiler.Contracts/ Compiler-emit types (WorldSchema, QueryPlan, ContentManifest,
ExecutionLane, CommandJournal) — netstandard2.1

examples/
minimal-v2/ Minimal v2 standalone example
character-trainer-v2/ v2 character-trainer host
valenar-v2/ v2 Valenar host (active compiler oracle and runtime target)
endgate/ Focused v2 prototype (SignalR server, React/Vite client, benchmarks)
map/ Map-generation prototypes (mapv10 is the active continent-scale direction)

unity/
combat-slice/ Self-contained Unity-hosted combat prototype package
ark-extraction/ Self-contained Unity-hosted ark extraction prototype package
packages/ Shared game-neutral Unity packages

The engine is game-agnostic. Channels, modifiers, contracts, scopes, and templates are all defined by the game — SECS provides the mechanisms.

Documentation

Start with the Design Reading Guide. That is the entry point for the live SECS docs and sends first-pass readers on to 00 — Overview. Historical, audit, and backlog material remains available under docs/, but the live design path is the authoritative reading route.

For a local docs portal, install the Docusaurus dependencies once:

npm install --prefix docs-site

Live authoring stays on a fixed loopback-only dev server:

npm run dev --prefix docs-site

That serves the portal at http://127.0.0.1:4174/secs/.

The stable personal-portal mode is build-first preview on loopback:

bash scripts/run-docs-portal.sh

That rebuilds the site, serves the built docs at http://127.0.0.1:4173/secs/, and starts a small loopback landing page plus zellij proxy at http://127.0.0.1:4180/. The landing page links to the docs portal and proxies non-root requests to the existing zellij web client on http://127.0.0.1:8082, with /zellij as the stable entry path. The underlying manual commands are npm run build --prefix docs-site, npm run serve --prefix docs-site, and npm run check --prefix docs-site.

The Docusaurus portal is built from generated publish content under docs-site/content/. Edit root SECS docs in docs/, Valenar docs in docs-site/content/valenar/, map docs in examples/map/mapv10/, and governance docs in .claude/rules/ or .github/, then rerun npm run check --prefix docs-site.

The portal syncs every Markdown file under docs/ and preserves the Valenar publish tree under docs-site/content/valenar/. For mapv10, it syncs the top-level mapv10 Markdown files plus the documentation-bearing subtrees (docs/, generator/, viewer/, schema/, viewer/src/{data,events,renderer,ui}/, prompts/, and verification/visual-foundation-audit/) without crawling generated map artifacts or dependency folders. npm run dev --prefix docs-site starts a watcher that resyncs source-doc changes while Docusaurus is running, so edits and newly added pages reload without restarting the dev server. npm run build --prefix docs-site and npm run check --prefix docs-site perform a fresh sync before building. For one-off manual syncs, run npm run sync --prefix docs-site.

Sidebars are generated from the synced doc tree by docs-site/sidebars/auto.js. Keep only high-level grouping rules there; do not hand-maintain leaf pages in the sidebars. New docs automatically appear in the left menu under their source-tree group, with unknown paths falling into an Other section until the grouping rules are intentionally refined.

On Linux, install the systemd user service for login-time autostart with:

bash scripts/install-docs-portal-user-service.sh
systemctl --user enable --now secs-docs-portal.service
systemctl --user stop secs-docs-portal.service
systemctl --user status secs-docs-portal.service

Use systemctl --user start secs-docs-portal.service for a one-shot manual start after installation. The installer writes ~/.config/systemd/user/secs-docs-portal.service with absolute paths for this checkout and the current npm and Node binaries; rerun it if the repo path or Node install changes. While the user service is running, its lifecycle hook syncs the /secs mount via a shim to dev-setup (scripts/docs-portal-tailscale.sh). The landing menu script lives in dev-setup/machines/herki-pc-ubuntu/tailnet/landing.js and is started by scripts/run-docs-portal.sh. If Tailscale is missing, the loopback docs portal still starts and only route sync is skipped. Enable linger with loginctl enable-linger "$USER" if you need the user service without an interactive login.

Machine-wide routing (root menu, Endgate, Valenar, WebEngine dashboard, DMS/buildlog) is documented in dev-setup/shared/projects/dev-surfaces.md. Canonical manifest: dev-setup/machines/herki-pc-ubuntu/tailnet/manifest.json.

bash scripts/host-tailscale.sh apply # all projects (shim)
bash scripts/docs-portal-tailscale.sh enable # /secs only
bash scripts/run-docs-portal.sh run # local :4173, menu :4180

Private docs URL: https://<host>.ts.net/secs/docs/ (Docusaurus under /secs/). See dev-host/README.md and docs/project/pr-tailscale-host-routing.md.

#DocumentWhat it covers
00OverviewLowering-contract entry point, glossary, reading order, diagnostic map
01World ShapeScope declarations, contracts, top-level channel declarations, the H.* hash convention
02Templatestemplate<Contract> Name { }, fields, intrinsic/dynamic channels in templates, CanBuild, lifecycle methods, bare templates
03Channels and ModifiersModifiers, formulas, triggers, 6-phase target resolution recap, reads {}, ValidateDependencies()
04BehaviorSystems, events (pulse + player choices), on-actions, activities, policies
05ExpressionsScope sigils (@this/@root/…), resolve/increment/add_modifier/fire/save_scope_as, foreach, query keywords (any/every/count/random/first)
06Mod Operations and Moddinginject / replace operation model, load order, typed identity, FNV-1a identity, slot schema, AST-level merger, conflict detection
07Structured Template Data and CallablesC# source type binding, generated SecsTypeRef metadata, structured template fields, typed query returns, feature placement query contract
08Collections and PropagationScopedList<T>, ScopedDictionary<TKey,T>, TemplateId, tags, modifier propagation, previous-tick bridge reads, aggregate channels, system phase/frequency slots, registry-only recipes
09AI Policies and ActivitiesPolicies, utility-AI scoring, activities, runtime player slots, mod injection examples
10Host <-> SECS execution boundaryBoundary classification + assembly placement
v2SECS v2 kernel rewrite ADRAccepts the v2 architecture (Decisions 1–4, seven new assemblies)
v2Kernel + runtime layer architectureFour-layer diagram (L1 SECS source → L4 kernel → L5 adapters)
v2Kernel contractSecsKernel API, seven required relation kinds, determinism spec
v2WorldSchema contractWorldSchema struct, every required row type, compiler-emit and kernel-consume contracts
v2Native collections and typesSECS.Native collection types; managed-backed initially; no Unity references
v2Save / load and determinismSecsSavePayload, PortableRandom (xoshiro256**), golden replay test
v2External engine adapter contractAdapter contract; Unity-hosted examples are adapters; six split bridges
Fork DecisionRoslyn fork vs source generator strategy
ADRs under docs/decisions/ and docs/adr/Architectural decisions that explain why the live design contract looks the way it does. Use alongside the numbered design docs when you need rationale rather than lowering detail.

Key Concepts

  • Templates define what entities ARE (static, contribute channels, lifecycle methods)
  • Systems define what HAPPENS each tick (non-static, frequency-gated, phased)
  • Events define what happens WHEN (pulse triggers, on_action hooks, player choices)
  • Modifiers are reusable effect bundles that modify channel values
  • Channels resolve through the implemented 6-phase target pipeline: base, additive, multiplicative, HardOverride, clamp, return.
  • Formulas are dynamic channel contributions and modifier effects evaluated at resolution time
  • Mod operations let layered content use inject, replace, try inject, try replace, inject_or_create, and replace_or_create against semantic slots. Activity/policy mods finalize at runtime startup; the full source-set merger for all declaration kinds is Phase 3 compiler work. Later writes win by load order, with conflicts reported for tooling.

Valenar Examples

The active Valenar track is Valenar v2, backed by examples/valenar-v2/Content, compiler-owned schema output under examples/valenar-v2/Generated/obj/**/SecsGenerated, retained explicit host-owned helpers, a v2 host/server, and the React/SignalR frontend. Missing or retired-empty v2 domains surface as empty/unavailable rather than faked; backed domains project real v2 host/runtime data. The map domain ships geometry + biomes + hierarchy from authored WorldData fixtures, authored forced Feature anchors materialize as real Feature entities, and ordinary score-and-budget Feature placement is retired by ADR. See examples/valenar-v2/README.md for the implementation status matrix.

Endgate Prototype

Endgate is a focused v2 prototype for host authority, deterministic map pressure, SignalR transport, a small React/Vite client, and benchmark coverage. It lives under examples/endgate/ with committed .secs content in Content/, compiler-owned schema output, and retained explicit host/catalog helpers under Generated/.

Building

dotnet build SECS.sln

Targets: netstandard2.1 (engine libraries, Unity-compatible), net8.0 (examples), and net10.0 for the Phase 1 compiler smoke. v2 test projects live at top-level tests/ (SECS.Core.Tests, SECS.Kernel.Tests, SECS.Native.Tests, SECS.Runtime.Tests, SECS.Schema.Tests, SECS.Standalone.Tests, SECS.Compiler.Smoke, Valenar.V2.Server.Tests, Endgate.Server.Tests); run SECS.Compiler.Smoke directly after building the Roslyn fork and tools/secsc.

For the production-core spine, run:

bash scripts/validate-production-core-spine.sh

That script runs runtime tests, Valenar server tests, Endgate server tests, and a full solution build. It supports split dotnet command selection through DOTNET_TEST and DOTNET_BUILD.

Running Valenar v2 (SignalR + React frontend)

examples/valenar-v2/Server is an ASP.NET Core SignalR hub at /gamehub wrapping the v2 runtime, and examples/valenar-v2/Client is the React/SignalR Valenar frontend pointed at that hub. Implementation status is matrix-tracked in examples/valenar-v2/README.md; empty domains stay empty rather than faked.

Server (SignalR hub on port 5063):

dotnet run --project examples/valenar-v2/Server

Client (Vite dev server on port 5173 with base: '/valenar/'; proxies /valenar/gamehub to the v2 server with WebSocket upgrade):

cd examples/valenar-v2/Client && npm install && npm run dev

Open http://localhost:5173/valenar/ in your browser.

Running Endgate

See examples/endgate/README.md for the subproject map, current prototype scope, server/client commands, the /gamehub SignalR endpoint, tests, benchmarks, and the Content/Generated provenance model.