Skip to main content

SECS Design — Reading Guide

This is the live entrypoint for the docs/design/ doc set. Read this first, then continue to 00-overview.md for the lowering-contract glossary and doc map.

For first-pass reading, stay on the live docs/design/ path. Historical, audit, recovery, and backlog material remains available elsewhere in docs/, but it is traceability only; the contract path defined here is the authoritative one.

What is SECS

SECS stands for Scripting Engine C Sharp. It is a data-driven scripting engine inspired by Paradox grand strategy games (CK3, EU4, Victoria 3) — specifically by their script systems that let designers and modders define entities, channels, events, and modifiers without touching engine code.

SECS uses a modified C# as its scripting language. .secs files are real C# with extra keywords. The SECS compiler lowers .secs to standard C# that the runtime engine consumes. The current compiler slice implements the structural shell (scope, contract root_scope, template<Contract>), declared scalar template fields with serialized values, scalar scope fields, explicit walks_to edges, simple top-level channels, and the secsc tooling/cache path; behavior declarations and expression lowering remain future work. The committed declaration keywords are template, channel, field, modifier, system, event, contract, scope, activity, on_action, policy. The committed mod-operation keywords are inject, replace, try inject, try replace, inject_or_create, replace_or_create. A top-level formula keyword is not committed; formula delegates are generated from dynamic channel sources and dynamic modifier effects. See SECS-Compiler-Plan.md § Source keyword whitelist and grammar status for the source/member/runtime split.

The four sub-projects of this workspace

The secs-workspace repo holds four cooperating pieces:

  1. The SECS engine — the runtime library that resolves channels, runs systems, dispatches events, manages modifiers, evaluates policies, executes activities, and accumulates mods. Seven assemblies under src/ — see docs/adr/ad-0006-secs-v2-kernel-rewrite.md for the full list. Engine libraries target netstandard2.1 so they can ship inside managed embedders.

  2. The Valenar example game (examples/valenar-v2/) — a colony builder. The v2 tree is the current runtime target; its .secs Content tree feeds compiler-owned output under the generated project obj/**/SecsGenerated, scoped collection IDs are compiler-owned schema rows, and ValenarHostIds.cs is the only retained checked-in Generated .cs surface. Today only FailureReasons.StaminaExhausted there is a host runtime failure-reason ID; it is true host-owned and not schema/catalog authority. examples/valenar-v2/Server is an ASP.NET Core SignalR hub at /gamehub wrapping the v2 runtime, and examples/valenar-v2/Client is the reused v1 React/SignalR Valenar frontend re-pointed at that hub through @microsoft/signalr + zustand; shell, character, retained inventory, retained policy behavior, activity, travel, map, territory, settlement, economy, force-family empty contracts, Stage-0 objectives, session journal, retained camp behavior, and direct/travel combat slices are now either backed or explicitly retired for the deletion gate. Recent retirement decisions close the v1 character/common registry scaffold, the v1 world pressure/province source shape, the v1 no-op building/settlement/resource lifecycle scaffold, and the v1-only item scaffold from the deletion target. Remaining gate work focuses on remaining partial content decisions — see examples/valenar-v2/README.md and docs/project/pr-valenar-v2-v1-deletion-gate.md for the status matrix and deletion gate.

  3. The forked C# compiler (secs-roslyn/ git submodule) — a fork of dotnet/roslyn with the Phase 1 structural shell, Phase 1.5 tooling/cache path, scalar template-field values, scope fields, walks_to, and simple top-level channels implemented. Valenar catalog/config/helper outputs are emitted by the compiler under the generated project obj/**/SecsGenerated; broader behavior and expression lowering remains future compiler work.

  4. The language specification (docs/) — docs/design/ is the live SECS contract path (this directory). docs/decisions/ records ADRs and docs/research/ holds non-authoritative exploration notes.

Legend

  • Current contract — this README plus 00-overview.md through 10-host-secs-execution-boundary.md.
  • Current Valenar runtime target (v2)examples/valenar-v2/Content/ plus compiler-owned output under examples/valenar-v2/Generated/obj/**/SecsGenerated; scoped collection IDs are compiler-owned schema rows, and ValenarHostIds.cs is the only retained checked-in Generated .cs surface, with only FailureReasons.StaminaExhausted as a host runtime failure-reason ID today. It is true host-owned and not schema/catalog authority.
  • Intended source surfaceexamples/valenar-v2/Content/. Designer-facing source shape for the future compiler.
  • Compiler implementation roadmapSECS-Compiler-Plan.md. Phase 1 structural shell status plus future-phase planning, not first-pass contract reading.
  • History / audit / recoverydocs/archive/RECOVERY_*.md, docs/archive/WAVE_REFACTOR_AUDIT.md, docs/archive/audit-findings.md, docs/archive/mod-coverage-audit.md. Traceability only; they do not override the live contract path.
  • Backlog / proposalsdocs/design/FUTURE_WORK.md and docs/research/. Planning only.

Content / Generated / future compiler

Three surfaces cooperate:

  • examples/valenar-v2/Content/ — v2 intended source surface for designers. Current target for new .secs content.
  • examples/valenar-v2/Generated/obj/**/SecsGenerated — compiler-owned Valenar output compiled by Valenar.V2.Generated.csproj. Checked-in Generated .cs is restricted to ValenarHostIds.cs; only FailureReasons.StaminaExhausted there is a host runtime failure-reason ID today, and scoped collection IDs are compiler-owned schema rows. It is true host-owned and not schema/catalog authority.
  • The SECS compiler — currently lowers the structural/data-declaration source slice into generated C#; later phases will lower behavior, expression, modifier, and mod-operation source into the broader Generated/ shape.

The live lowering contract is the pairing between the numbered design docs, the .secs source, and compiler-owned generated project output. When a numbered design doc explicitly replaces an older pattern, the design doc wins.

Live reading path

  1. Read this file for the doc-set legend and route.
  2. Read 00-overview.md for glossary, doc map, and diagnostic routing.
  3. Read the numbered docs in order when you need the full lowering contract.
  4. Use the relevant numbered doc's local glossary, notes, and cross-references when you need deeper semantic detail.
  5. Use recovery, audit, and backlog docs only for provenance or future planning.

The seven core SECS concepts

These are the concepts that shape the SECS programming model. Lifted verbatim from .claude/rules/secs-concepts.md. Note that not all seven are committed .secs top-level keywords: Formula is a generated delegate lifted from dynamic channel sources and dynamic modifier effects (there is no formula keyword — see 00-overview.md § Glossary and diagnostic SECS0032), and Mod operation / slot merge is the family of inject / replace operations rather than a single declaration keyword. The committed declaration keywords are listed in the workspace-root CLAUDE.md. Activity and Policy are not part of this core seven; they are behavior-layer concepts that extend it (see "The behavior layer" below).

ConceptWhat it isLifecycle
TemplateDefines what entities ARE. Static. Registers intrinsic channel sources, implements contract queries and methods.Registered at startup; looked up by the FNV-1a-64 hash of its canonical id string, which the compiler emits owner-less with the declared name verbatim (for example, valenar:template/Farm; see 01-world-shape.md § "Canonical id string format").
SystemDefines what HAPPENS each tick. Non-static. Frequency-gated, phased.Runs in pipeline order during TickContext.Tick().
EventDefines what happens WHEN. Pulse-triggered, on_action-triggered, or player-choice-triggered.EventDispatcher evaluates triggers per-tick.
ModifierReusable effect bundle (stacking + triggers + duration + decay).Attached by host or by OnAction; managed by ModifierBindingStore.
FormulaDynamic value used by intrinsic channel sources or modifier effects at resolution time.Evaluated lazily during channel resolution; cached in ChannelCache.
ScopeHost-defined hierarchy node (Empire, County, Building). Walked via WalkScope.Static hierarchy maintained by host.
Mod operation / slot mergeLayered content changes expressed with inject, replace, try inject, try replace, inject_or_create, or replace_or_create. Operations target compiler-owned semantic slots; later load-order writes win for the same slot.Resolved by the compiler pre-binding merge pass, with the shipped activity/policy runtime finalizer as the current executable subset.

Full prose definitions live in 00-overview.md § Glossary.

The behavior layer

The current behavior surface adds four live concepts on top of the seven core definitions:

  • Activity — executable behavior units the runtime can start, preview, and track. See 04-behavior.md § Activities.
  • Policy — chooser logic built from needs, selectors, and rules that selects among activities. See 09-ai-policies-and-activities.md.
  • Slot — per-actor mutable lists and related runtime-authored behavior data. See 04-behavior.md § Slots.
  • Mod — layered declaration changes that target the slot schema and merge pipeline. See 06-overrides-and-modding.md.

Warn-only registry diagnostics are also part of the live contract and are documented alongside the relevant features.

Compiler status

The compiler currently supports the Phase 1 structural shell, the Phase 1.5 secsc tooling/cache path, scalar template-field values, top-level field declarations, scalar scope fields, explicit walks_to edges, simple top-level channels, and compiler-owned Valenar catalog/config/helper output under the generated project obj/**/SecsGenerated. The broader language contract lives in the numbered design docs. SECS-Compiler-Plan.md records the implemented slices plus the future backlog; it is not part of the first-pass reading path.

Doc tour

Use this table as the live contract map. Numbered docs are the first-pass path; history, audit, and backlog docs are secondary destinations.

DocCovers
00-overviewLowering-contract entry point. Glossary. Feature-block template. Master diagnostic table (SECS0xxx codes). Diagnostic channels. Read after this README.
01-world-shapeWorld/scope schema. scope, walks_to, ScopedList<T>, ScopedDictionary<TKey,T>. How the host's hierarchy gets declared.
02-templatesThe template keyword. Channel sources, contract methods, lifecycle bindings. The most foundational doc.
03-channels-and-modifiersThe 6-phase channel resolution pipeline (base → additive → multiplicative → HardOverride → clamp → return). Modifier declarations, propagation, stacking, decay. track_prev snapshots. SECS0303 formula read-set warning.
04-behaviorSystems, events, on-actions, activities, policies, slots, and static analysis. The "what happens" layer.
05-expressionsExpression model. Lambda bodies, captured locals, @this / owner references.
06-overrides-and-moddingThe modding contract. Six mod operations. Slot schema (§8.1–§8.10). Severity model (§12.1). Registry static analysis (§12.2).
07-structured-template-data-and-callablesSecsTypeRef, structured template data, typed callable signatures. Replaces the older SecsValueKind design.
08-collections-and-propagationCollection iteration, aggregate accessors (Children.Sum, .Where), modifier propagation, previous-tick bridge reads, registry_only design intent and current gap.
09-ai-policies-and-activitiesPolicies, utility-AI scoring, activities, runtime player slots, mod injection examples. The behavior-layer narrative.
10-host-secs-execution-boundaryOwnership classification, assembly placement, host bridge contract, invocation rules, and the current partial save/load boundary. Carries v1-reference banner; §3.1, §3.3, §4, §20.2 are superseded by v2 — see the v2 docs below.

v2 Architecture Docs

DocCovers
ad-0006-secs-v2-kernel-rewriteADR accepting the v2 architecture (Decisions 1–4, seven new assemblies).
rn-kernel-runtime-layersFour-layer architecture diagram (L1 SECS source → L4 kernel → L5 adapters); assembly reference graph.
rn-kernel-contractSecsKernel API contract, seven required relation kinds, query operation vocabulary, command-journal ordering, determinism spec.
sp-world-schema-contractWorldSchema struct, every required schema row type, compiler-emit and kernel-consume contracts.
rn-native-collections-and-typesSECS.Native collection types; managed-backed initially; deterministic iteration mandatory; no Unity references.
rn-save-load-determinismSecsSavePayload format, PortableRandom (xoshiro256**), restore order, golden replay test.
rn-external-engine-adaptersAdapter contract; Unity is future external work; seven host bridges (six split from v1's three monolithic interfaces, plus the scope-query bridge).

Secondary destinations:

DocRole
audit-findingsSpec audit findings collected during refactors. Historical traceability only.
mod-coverage-auditCoverage audit of mod operations against spec. Historical traceability only.
FUTURE_WORKDeferred engine work, compiler backlog, and doc-cleanup punch list. Backlog, not current contract.

Doc-set roles (where things live)

LocationRole
docs/design/ (this directory)Authoritative lowering contract. What the compiler must emit. SECS source + lowered C# pairs.
Historical audits / recovery docs elsewhere under docs/Provenance and cleanup history. Useful for traceability, but not part of the live contract path.
docs/decisions/Architectural decision records (ADRs). Why the Roslyn fork, why netstandard2.1, etc.
docs/runtime/ (new)v2 runtime / engine architecture docs (rn-* prefix). Kernel contract, layer diagram, native collections, save / load, adapter contract.
docs/specs/ (new)v2 specification docs (sp-* prefix). WorldSchema contract.
docs/research/Exploration notes. Not authoritative. Treat decisions as authoritative, research as scratch.
CLAUDE.md (workspace root)Workspace identity, tenets, universal commands. Read alongside this README.
.claude/rules/*.mdPath-scoped rules that auto-load when working in specific subsystems (netstandard2.1 polyfills, mapgen invariants, SECS concepts, etc.).
SECS-Compiler-Plan.md (workspace root)Eight-phase plan for building the SECS compiler on the Roslyn fork, including the implemented structural shell, tooling/cache path, scalar template-field values, data-declaration rows, and future-phase backlog.

Reading order

  • Fresh orientationCLAUDE.md, this README, 00-overview.md, then the numbered docs you need.
  • Full contract read00-overview.md through 10-host-secs-execution-boundary.md in order.
  • Semantics questions — stay on the numbered design docs and follow their local cross-references; the live contract path carries the current semantics.
  • Planning work — use FUTURE_WORK.md and SECS-Compiler-Plan.md only after the live path.

Status snapshot (May 2026)

  • The v2 runtime is built, tested, and documented. The seven new assemblies (SECS.Core, SECS.Native, SECS.Schema, SECS.Kernel, SECS.Runtime, SECS.Adapters.Standalone, SECS.Compiler.Contracts) live under src/. See docs/adr/ad-0006-secs-v2-kernel-rewrite.md.
  • examples/valenar-v2/Generated/obj/**/SecsGenerated is the current compiler-owned Valenar output surface, compiled by Valenar.V2.Generated.csproj; checked-in Valenar Generated .cs is restricted to ValenarHostIds.cs. Today only FailureReasons.StaminaExhausted there is a host runtime failure-reason ID; it is true host-owned and not schema/catalog authority. Scoped collection IDs are compiler-owned schema rows.
  • The live behavior surface includes activities, policies, runtime slots, the mod runtime, and registry diagnostics.
  • The SECS compiler accepts the Phase 1 scope/contract/template structural shell, scalar template-field values (int, long, float, double, bool simple literals), top-level field declarations, scalar scope fields, explicit walks_to edges, and simple top-level channels. secsc can compile content packages, emit inspectable .g.cs, cache compiled assemblies, and load Generated.SecsModule.BuildSchema(). Structured template fields, dynamic formulas/channel bodies, effective template-value reads, context modifiers, behavior declarations, mod operations, and broader language features remain future work.
  • v2 (src/, tests/, examples/*-v2/) is the current architecture; examples/valenar-v2/Server is a SignalR hub at /gamehub wrapping the v2 runtime, and examples/valenar-v2/Client is the reused v1 React/SignalR Valenar frontend wired against that hub. Settlement, economy, forces, map, realm, journal, combat, and camp remain feature-gated empty until per-domain content waves back them. Time-bank state, game speed, activity availability, queue commands (enqueue / cancel / move), and travel (location graph, queue.enqueue_travel, character.move, travel.plan, travel.cancel) are partially or fully backed — see examples/valenar-v2/README.md.