Changelog¶
All notable changes to the netforge_rl project will be documented in this file.
The format is based on Keep a Changelog.
[3.1.0] — 2026-07-10¶
Fixed¶
- JAX backend action timing (
backends/jax/transition.py,backends/jax/action_codes.py): the vectorized backend now enqueues and resolves actions against the same per-agent duration table as the real Python action classes, instead of resolving every action within the tick it's submitted. An agent cannot submit a new action while one is still pending (mirroringparallel_env.py'sagent_locked_until), and a BlueIsolateHostthat matures on a tick now cancels any still-pending Red action on the same host, with same-tick ties favoring Blue. Every one of the 34 action durations was re-derived from its actual Python action class rather than assumed; a prior, unfinished attempt at this had 10 of 34 durations wrong, a deletedscenario_done, a reference to a nonexistenthosts.reachabilityfield, aStepEventsconstruction using stale field names, and a brokensiem_bufferreference in the JaxMARL bridge. backends/reference.py: the NumPy mirror used for JAX parity testing carries the same queue logic, verified against the JAX kernel with zero mismatches across all five scenarios under randomized rollouts, plus targeted deterministic checks of the isolation-cancellation and submission-lock mechanics.
Removed¶
backends/jax/siem_embeddings.py: an unfinished, untested SIEM-embedding-lookup attempt that referenced an unimportedLogEncodername and raisedNameErroron first use. The existingjax_siem_featuresscalar signal remains the JAX backend's telemetry proxy; the JAX and Python backends still diverge on observation richness and on tick cadence (the JAX core advances a fixed one tick perstep()call rather than jumping to the next event).
[3.0.0] — 2026-07¶
Added¶
- Trained baselines + curves:
benchmarks/train_curve.pyruns the JIT-fused JAX IPPO trainer, records the reward/loss curves, renders a chart, and checkpoints the policy (save_params/load_params). A committed 40-iterransomwarerun learns 0.06 → 0.71 mean reward over 245,760 env-steps. - Gymnasium single-agent env (
environment/gym_env.py):NetForgeSingleAgentEnvcontrols one agent against scripted opponents, passesgymnasium.check_env, and exposes the action mask ininfo— a drop-in target for Stable-Baselines3 / CleanRL. - MITRE ATT&CK coverage (
actions/attack_map.py): red actions map to ATT&CK techniques; episodes reportattack_techniquesandattack_coverageininfo. - Graph-native observations (
core/graph_obs.py,environment/graph_wrapper.py): node/edge/edge-attr arrays with fog-of-war masking, one call to PyTorch Geometric viato_pyg;GraphObservationWrapperinjects them intoinfowithout changing obs shapes. - Capability cards (
diagnostics/capability_card.py): run the 6-probe suite across seeds and emit a per-policy JSON + radar chart. - Deception mechanics:
deception_hits/deception_efficacymetrics measuring how much of Red's effort landed on decoys and honeytokens. - SOC export (
siem/export.py): capture the full episode SIEM stream (record_siem=True) and export it as OCSF-style JSON records for real SIEM tooling. - Self-play & Elo (
benchmarks/self_play.py): a population tournament that rates red and blue policies on one SLA-based ladder. - JAX-native SIEM signal (
backends/jax/vector_env.py:jax_siem_features): a per-host numeric alert vector computed in-kernel, wired into the vectorized blue observation behindJaxMARLEnv(telemetry_obs=True)so the fast backend carries telemetry end-to-end.
Fixed¶
- Packaging:
scikit-learnandpilloware hard runtime dependencies (the defaultLogEncodertfidf backend and the LLM vision prompt builder both import them unconditionally) but neither was in coredependencies— a basepip install netforge_rlcould not import the environment or the semantic package. Both moved to core deps. - Circular import:
netforge_rl.baselines.evalimportedEpisodeResultfrom thenetforge_rl.semanticpackage root, which re-entersbaselinesviasemantic.modesduring its own init. Imports now point at the leaf modules (semantic.runner,semantic.leaderboard) that don't importbaselines, breaking the cycle with no lazy/in-function imports. - Tests: two JAX-dependent test files imported
jaxdirectly instead of the repo's establishedpytest.importorskip('jax')guard, so they errored (rather than skipped) in environments without thejaxextra installed (e.g. CI).
Removed¶
benchmarks/sps_baseline.py,sps_jax_vectorized.py: superseded bybenchmarks/throughput.py, which the docs already pointed at.benchmarks/train_ippo.py: superseded bybenchmarks/train_curve.py.benchmarks/baseline_sweep.py: an unused, undocumented, weaker duplicate ofrun_benchmark.py+build_leaderboard.py.
Docs¶
- Rewrote
README.mdanddocs/index.mdfor the v3.0.0 feature set. - Removed duplicated throughput/competition/scoring/sweep instructions that were
repeated across
benchmarks/overview.md,baselines.md, andrun.md; each page now owns one topic and links to the others instead of restating them.
[2.3.0] — 2026-07¶
Added¶
- Difficulty presets:
netforge_rl.environment.presetsexposes namedeasy/medium/hardtiers (make_config,make_env) and a frozen 20-seed held-outEVAL_SEEDSsuite, so difficulty and the train/eval split are reproducible and comparable. - Config knobs wired:
log_latencynow actually delays SIEM log visibility (a lagging SOC feed; 0 = immediate, the historical behaviour) anddhcp_intervalnow controls DHCP churn (previously hard-coded to 40 and ignored from config). - Diagnostics: expanded the probe suite from 2 to 6 capabilities — added
DelayedTelemetry(temporal),FalsePositiveRestraint(precision),OTKineticResponse(safety), andTopologyShift(generalization) alongsideMemoryProbeandNoisySIEM. - Baselines:
KillChainRedPolicy, a scripted recon→exploit→pivot attacker that actually compromises hosts (the naiveHeuristicRedPolicyskipped recon, so its exploits always failed the prior-state check and nothing was ever compromised). Wired intorun_benchmark/build_leaderboard; the regenerated leaderboards now show non-zero, CI-bounded compromise rates. - Spec:
REWARD_WEIGHTStables on each scenario andget_reward_weights(), sobenchmarks/env_spec.pypublishes a stable reward-decomposition spec.
Docs¶
- Rewrote the site to match the current environment: refreshed the landing page and
quickstart; added pages for Difficulty & Splits, Reproducibility, the
Diagnostic suite, and Baselines; corrected throughput claims to measured
env-steps/s vs agent-steps/s; and expanded the datasheet. All code snippets are
smoke-tested and the site builds under
mkdocs --strict.
Fixed¶
- Imports:
netforge_rl.baselines.evalnow importsnetforge_rl.semanticlazily, breaking asemantic → modes → baselines → eval → semanticimport cycle. - Determinism: The sim
MockHypervisorRNG was seeded once at construction and never reset, so exploit outcomes leaked across episodes. It is now reseeded onreset(seed), closing a latent reproducibility hole in the exploit path. - Determinism: SIEM event templates now take a per-call RNG (threaded from the env/logger) instead of a shared module global, so concurrent envs in one process stay independent and reproducible.
- Benchmarks: Fixed
env_spec.py(brokenget_reward_weightsimport) andbuild_leaderboard(brokenevaluateimport); baseline evaluation excludes169.254.0.0/16padding from compromised/isolated counts. - Rewards: Added
iter_host_deltasso reward, metric, and info code reads host changes identically whether an action returns a dict delta or a command-list delta. Command-based actions (e.g.ExploitRemoteService,SpearPhishing) are now credited for privilege/isolation changes they were previously ignored for. - Actions: Unified the action taxonomy under one team per role (
red/blue). Blue detection actions (Monitor,Analyze,DeployEDR, decoys, honeytokens,RotateKerberos) are now reachable by the default blue agents; theoperator/commandersplit that no live agent used was removed. - Actions:
DumpLSASSandRotateKerberosreturned their command wrapped in a string-keyed dict, so it never executed; they now return command lists. - Determinism: Stochastic actions draw from a per-episode RNG on
GlobalNetworkState; the SIEM logger and event templates are reseeded onreset(seed)and timestamps are derived from a fixed epoch. Rewards and telemetry now replay identically under a seed. - Metrics:
169.254.0.0/16padding hosts are excluded from compromised/isolated/ SLA metrics; a separateactive_hostscount is reported. - Scenarios: Fixed the OT subnet name mismatch (
OTvsOT_Subnet) so OT-specific reward branches fire. - Benchmarks:
python -m benchmarks.run_benchmarkruns the sweep on the default path (previously a no-op unless--gap); heuristic policies are now driven through an env-boundPolicyAgentinstead of silently falling back to random.
[2.2.0] — 2026-06¶
Fixed¶
- Core: Normalized rewards using
tanhscaling to prevent reward explosion. - Core: Removed module-level global seeding for deterministic parallel execution.
- Core: Fixed
redagent action mapping and removed duplicate conflict resolution logic. - Core: Fixed fog-of-war masking shapes to align with the 132-dimension observation space.
- Core: Replaced hardcoded decoy IPs with dynamic
169.254.x.xpadding IPs in reconnaissance.
[2.1.0] — 2026-06¶
Added¶
- Environment: Added
TopologyEventEnginetonetforge_rl/environment/parallel_env.pyto support dynamic topologies. - Environment: Implemented curriculum learning framework.
- Training: Added RLlib integration and RMAPPO vs RMAPPO baseline.
Fixed¶
- Core: Fixed decoy recon replacing hosts, static action mask issues, and stale DHCP targeting.
[2.0.0] — 2026-06¶
Added¶
- Core: Added
netforge_rl/core/functional.pyimplementing a pureEnvStateinterpreter. - JAX Backend: Added
netforge_rl/backends/jax/providing vectorized kernels and batched step execution for high-throughput training. - Bridges: Added
JaxMARLenvironment adapter anddlpacksupport for zero-copy array conversion. - Rendering: Implemented decoupled rendering pipeline in
netforge_rl/render/. - Baselines: Added heuristic evaluation policies and a PPO implementation for the JaxMARL backend.
- Semantic Interface: Added
netforge_rl/semantic/for language-model-based agent interaction and LLM fine-tuning. - Notebooks: Added 7 reference notebooks for quickstart, visualization, and RL training.
- Tests: Expanded test suite to 173 tests, including deterministic trajectory hashing.
Changed¶
- Increased maximum parallel throughput to >1M steps-per-second via JAX vectorization.
[1.0.0] — 2026-02¶
Added¶
- Native integration with the PettingZoo
ParallelEnvAPI. - Replaced legacy observation spaces with
gymnasium.spaces. - Created unified
BaseAction/BaseObservationclass hierarchy. - Upgraded testing and runtime requirements to Python 3.14.
Removed¶
- Removed deprecated OpenAI Gym wrappers and legacy evaluation modules.