Documentation Index
Fetch the complete documentation index at: https://mintlify.com/0x-unkwn0wn/simterm/llms.txt
Use this file to discover all available pages before exploring further.
validate_campaign is a pure function in simterm-engine that performs deep semantic analysis of a loaded Campaign value. It has no UI dependency and no side effects — it reads data and returns a report. Any tool, build script, or custom frontend can call it directly without importing the simterm terminal frontend.
This is distinct from load_campaign, which only checks that the RON file is syntactically valid and non-empty. validate_campaign goes further: it chases references, checks VFS paths, validates service/vulnerability linkage, detects verb collisions, and warns about balance values outside their expected ranges.
Function signature
Parameters
campaign — A Campaign value already loaded by load_campaign or load_open_campaign. Pass a reference; validate_campaign does not consume it.
reserved_verbs — A slice of verb strings that the frontend treats as built-in commands ("nmap", "help", "quit", etc.). The engine uses this list to detect easter-egg and declarative-command triggers that would be silently shadowed by the built-in command set. Pass &[] if you do not have a command registry to consult.
The engine never imports the frontend registry. Instead, the frontend calls registry::reserved_verbs() and passes the result here, keeping the engine independent of all presentation code.
ValidationReport
errors contains issues that will cause a campaign to malfunction or be unwinnable. warnings contains issues that are suspicious but do not necessarily break anything (balance values out of range, potentially unreachable achievements, etc.).
has_errors() is the idiomatic way to decide whether a campaign should be blocked from loading. is_clean() returns true only when both errors and warnings are empty.
ValidationIssue
location is a human-readable string such as "misión 'op1'", "logro 'a1'", or "comando 'inspect'". message describes the problem in plain language.
What the validator checks
Mission structure
Every mission must have a non-empty
id. Duplicate id values across missions are an error. Missions with skill outside [0.0, 1.0], root_difficulty outside [1, 10], detection_limit <= 0, or time_limit = Some(0) produce warnings.Service and vulnerability linkage
Every
Vulnerability.affected_service port must appear in the same host’s services list. A vulnerability pointing to a non-existent port is an error. Vulnerability difficulty outside [1, 10] is a warning.Token reachability
If a
Service sets requires, that token must appear in at least one Loot.foothold_token or binary/hash Reward::Token somewhere in the whole campaign — otherwise the gated service can never be unlocked. Similarly, if TargetNode.accepts_token is set but the token is never obtainable, login will never work on that host (warning, not error, because exploit remains a viable path).VFS objective paths
If a mission or
NetHost sets an objective, the validator confirms that path resolves to a File (not a directory, not a non-existent path) in the host’s VFS. A dangling objective is an error.Multi-host network consistency
In multi-host missions, host
hostname values must be unique. Every links entry on a NetHost must match the hostname or short name of another host in the same network. A missing entry point (entry: true) produces a warning (the engine falls back to the first host).Achievement triggers
CompleteMission(id) and ChooseEnding { mission, choice } triggers must reference real mission ids. ChooseEnding.choice must be within the mission’s endings count. ReadFile(path) triggers that point to non-existent VFS files produce a warning.Declarative commands
UnlockAchievement(id) effects must reference a defined CampaignAchievement. Mission(id) and Phase(name) conditions must reference real ids and valid phase names ("recon", "enum", "exploit", "post"). FlagSet(name) conditions where no command ever activates that flag produce a warning (the condition would be permanently false). Duplicate trigger verbs across commands produce a warning.Terminal commands
exit codes outside [0, 255] produce a warning. Template references like {env:MY_VAR} that do not appear in Campaign.env or the engine-derived variables (USER, HOME, PWD, HOSTNAME, SHELL, LOGNAME) produce a warning.Using validate_campaign in a custom tool
LoadError: handling load failures
Before you can callvalidate_campaign you must successfully load the campaign. load_campaign returns Result<Campaign, LoadError>:
| Variant | Cause |
|---|---|
NotFound | The path does not exist or cannot be read |
Parse | The RON file is syntactically invalid or does not match the Campaign struct |
Empty | The RON parsed successfully but missions is empty |
load_campaign vs load_open_campaign
| Function | Returns | Use when… |
|---|---|---|
load_campaign(path) | Result<Campaign, LoadError> | You only need the campaign data (validation, headless testing, custom tooling) |
load_open_campaign(path) | Result<OpenCampaign, LoadError> | You also need to resolve audio or other binary assets from the campaign directory |
OpenCampaign pairs the loaded Campaign with a Box<dyn AssetSource> pointing at the campaign’s directory, so the frontend can read music files without knowing the campaign’s location.
How the frontend uses this
The standardsimterm frontend passes its full command registry into the validator:
nmap, exploit, help, and quit — without the engine ever importing the registry module. The engine stays independent of the frontend; the frontend decides which verbs to expose as reserved.
validate_campaign is the same validation that powers simterm --doctor. Running it in a CI script or pre-commit hook catches authoring mistakes before a campaign is shipped to players.Overview
Crate re-exports and Cargo.toml setup
Data Model
Types that validate_campaign inspects
Runtime
Run a validated campaign with GameState