Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
475f7ff
Update mal-toolbox dependency to use specific git reference
sandorstormen Oct 4, 2026
1fee96c
refactor: Added dummy language since programatic lang creation is not…
sandorstormen Oct 5, 2026
6c64667
test: make event logger tests deterministic instead of seed-dependent
sandorstormen Oct 5, 2026
17ea99a
fix: skip dead nodes when expanding attack surface / effects
sandorstormen Oct 5, 2026
390b004
fix: correct action node assertion in defend compromised defender test
sandorstormen Oct 5, 2026
ba16216
refactor: simplify dummy language graph fixture documentation and rem…
sandorstormen Oct 5, 2026
fc28fc3
fix: update mal-toolbox dependency to use rust-rewrite branch
sandorstormen Oct 6, 2026
4f31fff
Move malsim/ to python/ and scaffold Rust workspaces
sandorstormen Oct 7, 2026
b8e6540
Add PORTING_NOTES.md: plan for porting malsim's simulator core to Rust
sandorstormen Oct 7, 2026
efb5fdd
Phase A1: prove shared AttackGraph handle extraction across malsim/ma…
sandorstormen Oct 7, 2026
87c4e41
Phase A2: port TtcDist to Rust (malsim-core)
sandorstormen Oct 7, 2026
ddf33ca
Phase A3: port graph_state + necessity propagation to Rust (malsim-core)
sandorstormen Oct 7, 2026
fc1d074
Phase A4: port graph traversal predicates to Rust (malsim-core)
sandorstormen Oct 7, 2026
8ace9ed
Phase A5: port attack surface / defense surface / effects to Rust (ma…
sandorstormen Oct 7, 2026
1585fbe
Phase A6: port false-alert + detector log generation to Rust (malsim-…
sandorstormen Oct 7, 2026
a743996
Phase A7: port attacker_step / defender_step orchestration to Rust (m…
sandorstormen Oct 7, 2026
c23cf57
Phase A8: malsim-pyo3 native Simulator pyclass (reset_native/step_nat…
sandorstormen Oct 7, 2026
67c6438
Phase A9: rewrite MalSimulator.reset()/.step() to delegate to native
sandorstormen Oct 7, 2026
2d5d30f
fix: Type errors
sandorstormen Oct 8, 2026
3342741
ci: import Rust CI jobs from mal-toolbox PR #255
sandorstormen Oct 8, 2026
fcc730a
ci: clear leaked sccache env before rebuilding mal-toolbox from git
sandorstormen Oct 8, 2026
1c1b62e
Phase A10: audit MalSimulator query methods against native backend
sandorstormen Oct 8, 2026
48d3f84
perf: make step_native return per-step deltas instead of full accumul…
sandorstormen Oct 8, 2026
f949c21
docs: flesh out Phase B (DynaMalSimulator port) in PORTING_NOTES.md
sandorstormen Oct 8, 2026
f8a8128
Phase B1+B2: port DynaMalSimulator's model-effect evaluation and dyna…
sandorstormen Oct 8, 2026
0bf303f
Phase B3: prove a shared Model handle end to end
sandorstormen Oct 8, 2026
bc9a22a
Phase B4 complete, B5 partial: native dyna reset/step entry points
sandorstormen Oct 8, 2026
6ec748f
Phase B5: fix the dyna stale-node-id panic class, document remaining …
sandorstormen Oct 8, 2026
1716d85
Phase B5 complete: resend grown GraphState on dyna steps that mutate …
sandorstormen Oct 8, 2026
c86fa49
Fix stray comma in policies/utils/__init__,py filename
sandorstormen Oct 8, 2026
efad225
Phase B6: audit DynaMalSimulator public surface, add mutated-graph qu…
claude Oct 9, 2026
fc6f326
Ignore .langs/ language cache generated by the test suite
claude Oct 9, 2026
318827d
Fix .gitignore: separate .claude and .langs/ entries
claude Oct 9, 2026
30ffec9
Phase A11/B7 (part 1): delete native-shadowed Python, port viability …
claude Oct 9, 2026
2391f14
Phase A11/B7 (part 2): close Rust test gaps, record A11/B7 in PORTING…
claude Oct 9, 2026
444034b
Fix ruff format check: blank line after import in PORTING_NOTES.md sn…
claude Oct 9, 2026
c10ca3c
PORTING_NOTES: record Phase C conventions (core Simulator, scenario n…
claude Oct 10, 2026
e07add3
Phase C1: port NodePropertyRule matching to Rust (malsim-core scenari…
claude Oct 10, 2026
bc7d293
Phase C2: port scenario YAML loading (validation, extends merge, path…
claude Oct 10, 2026
5fe821f
PORTING_NOTES: record core Simulator API, Flat*Settings naming, setti…
claude Oct 10, 2026
3e1d190
Phase C3: port agent settings from dict + settings resolution to mals…
claude Oct 10, 2026
07ca4bd
Phase C4: Scenario type wiring scenario loading to mal-toolbox's pure…
claude Oct 10, 2026
c4c43b2
Phase C5 (part 1): move Simulator reset/step orchestration from malsi…
claude Oct 10, 2026
447e5f7
Phase C5 (part 2): end-to-end Rust-only smoke test (scenario YAML -> …
claude Oct 10, 2026
3141e7c
Phase C6: Rust/Python scenario-loader parity test via committed golde…
claude Oct 10, 2026
ab06b0e
Fix dyna reset flattening agent settings against the previous episode…
claude Oct 11, 2026
1d1e223
Re-resolve dyna attacker entry points/goals by full name after model …
claude Oct 11, 2026
12c02fa
Update maltoolbox dependencies to use the 'rust-rewrite' branch
sandorstormen Oct 11, 2026
89ef09c
Separate static Simulator and DynaSimulator
claude Oct 11, 2026
ff688ba
Condense PORTING_NOTES.md to current-state reference
sandorstormen Oct 12, 2026
815dad6
Move _native stubs beside the extension module so type checkers find …
sandorstormen Oct 12, 2026
61ccc84
Ship _native.pyi and py.typed in the wheel; update stub path in notes
sandorstormen Oct 12, 2026
5fcca0b
Add Rust policies, rewards and run_simulation to malsim-core
sandorstormen Oct 12, 2026
a5e7fc6
Add malsim-cli crate with the malsim binary
sandorstormen Oct 12, 2026
74e2932
Record Phase D (Rust policies, rewards, run_simulation, CLI) in PORTI…
sandorstormen Oct 12, 2026
b87a1ed
Add max_steps argument to CLI and update run_simulation call
sandorstormen Oct 12, 2026
a8e7b8c
Speed up malsim-core hot paths and make seeded runs reproducible
sandorstormen Oct 15, 2026
f0bce34
Update PORTING_NOTES for node-id collection types and seeded reproduc…
sandorstormen Oct 15, 2026
dc287b0
Add Scenario::save_to_file and to_dict
sandorstormen Oct 19, 2026
ee6c6cc
Bump mal-toolbox to 598bac3
sandorstormen Oct 22, 2026
a9f6bf8
Bump mal-toolbox to 8e63c83
sandorstormen Oct 22, 2026
1eec047
Keep a per-episode step history in malsim-core's SimState
claude Oct 23, 2026
c53f8ac
Expose on-demand state translation from the PyO3 simulators
claude Oct 23, 2026
54c0120
Update attacker action surfaces incrementally
sandorstormen Oct 28, 2026
62819c8
Default attacker reward_mode to EXPECTED_TTC in scenario loaders
sandorstormen Oct 28, 2026
a122614
Tests that don't take too long to run.
sandorstormen Oct 28, 2026
930d061
Undo dyna steps from a graph_state delta instead of a full copy
sandorstormen Oct 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/mypy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ jobs:
- name: Type checking with MyPy
run: |
pip install mypy
mypy malsim tests --install-types --non-interactive
mypy python/malsim tests --install-types --non-interactive
248 changes: 194 additions & 54 deletions .github/workflows/publish-to-pypi-and-test-pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,72 +3,212 @@ name: Publish Python distributions to PyPI and TestPyPI
on: push

jobs:
build:
name: Build Python distribution
runs-on: ubuntu-latest
linux:
name: wheels (linux ${{ matrix.platform.target }})
runs-on: ${{ matrix.platform.runner }}
strategy:
fail-fast: false
matrix:
platform:
- runner: ubuntu-22.04
target: x86_64
- runner: ubuntu-22.04
target: aarch64
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: "3.10"
- name: Build wheels
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.platform.target }}
args: --release --out dist --find-interpreter
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
manylinux: auto
- name: Test wheel (native target only)
if: matrix.platform.target == 'x86_64'
env:
# The maturin-action build step above leaves RUSTC_WRAPPER=sccache
# in the job environment, but that sccache binary only exists
# inside its manylinux container. This step runs on the host and
# rebuilds mal-toolbox (a git dependency) from source via cargo,
# so the leaked wrapper must be cleared or the build fails.
RUSTC_WRAPPER: ""
SCCACHE_GHA_ENABLED: ""
run: |
pip install mal-simulator --find-links dist --force-reinstall
python -c "import malsim"
- name: Upload wheels
uses: actions/upload-artifact@v6
with:
name: wheels-linux-${{ matrix.platform.target }}
path: dist

musllinux:
name: wheels (musllinux ${{ matrix.platform.target }})
runs-on: ${{ matrix.platform.runner }}
strategy:
fail-fast: false
matrix:
platform:
- runner: ubuntu-22.04
target: x86_64
- runner: ubuntu-22.04
target: aarch64
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: "3.10"
- name: Build wheels
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.platform.target }}
args: --release --out dist --find-interpreter
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
manylinux: musllinux_1_2
- name: Upload wheels
uses: actions/upload-artifact@v6
with:
name: wheels-musllinux-${{ matrix.platform.target }}
path: dist

steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.x"
windows:
name: wheels (windows ${{ matrix.platform.target }})
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
platform:
- target: x64
python_arch: x64
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: "3.10"
architecture: ${{ matrix.platform.python_arch }}
- name: Build wheels
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.platform.target }}
args: --release --out dist --find-interpreter
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
- name: Test wheel
run: |
pip install mal-simulator --find-links dist --force-reinstall
python -c "import malsim"
- name: Upload wheels
uses: actions/upload-artifact@v6
with:
name: wheels-windows-${{ matrix.platform.target }}
path: dist

- name: Install pypa/build
run: >-
python3 -m
pip install
build
--user
macos:
name: wheels (macos ${{ matrix.platform.target }})
runs-on: ${{ matrix.platform.runner }}
strategy:
fail-fast: false
matrix:
platform:
- runner: macos-15-intel
target: x86_64
- runner: macos-latest
target: aarch64
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: "3.10"
- name: Build wheels
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.platform.target }}
args: --release --out dist --find-interpreter
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
- name: Test wheel
run: |
pip install mal-simulator --find-links dist --force-reinstall
python -c "import malsim"
- name: Upload wheels
uses: actions/upload-artifact@v6
with:
name: wheels-macos-${{ matrix.platform.target }}
path: dist

- name: Build a binary wheel and a source tarball
run: python3 -m build
- name: Store the distribution packages
uses: actions/upload-artifact@v4
with:
name: python-package-distributions
path: dist/
sdist:
name: sdist
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Build sdist
uses: PyO3/maturin-action@v1
with:
command: sdist
args: --out dist
- name: Upload sdist
uses: actions/upload-artifact@v6
with:
name: wheels-sdist
path: dist

publish-to-pypi:
name: Publish Python distribution to PyPI
if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes
needs:
- build
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/mal-simulator
permissions:
id-token: write # IMPORTANT: mandatory for trusted publishing
publish-to-testpypi:
name: Publish Python distribution to TestPyPI
if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes
needs:
- linux
- musllinux
- windows
- macos
- sdist
runs-on: ubuntu-latest
environment:
name: testpypi
url: https://test.pypi.org/p/mal-simulator
permissions:
id-token: write # IMPORTANT: mandatory for trusted publishing

steps:
steps:
- name: Download all the dists
uses: actions/download-artifact@v4
uses: actions/download-artifact@v7
with:
name: python-package-distributions
pattern: wheels-*
path: dist/
- name: Publish distribution to PyPI
merge-multiple: true
- name: Publish distribution to TestPyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://test.pypi.org/legacy/

publish-to-testpypi:
name: Publish Python distribution to TestPyPI
if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes
needs:
- build
runs-on: ubuntu-latest
environment:
name: testpypi
url: https://test.pypi.org/p/mal-simulator
permissions:
id-token: write # IMPORTANT: mandatory for trusted publishing
publish-to-pypi:
name: Publish Python distribution to PyPI
if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes
needs:
- linux
- musllinux
- windows
- macos
- sdist
- publish-to-testpypi # TestPyPI is a gate: must succeed before the real publish
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/mal-simulator
permissions:
id-token: write # IMPORTANT: mandatory for trusted publishing
attestations: write # for the GitHub-native build provenance attestation below

steps:
steps:
- name: Download all the dists
uses: actions/download-artifact@v4
uses: actions/download-artifact@v7
with:
name: python-package-distributions
pattern: wheels-*
path: dist/
- name: Publish distribution to TestPyPI
uses: pypa/gh-action-pypi-publish@release/v1
merge-multiple: true
- name: Generate artifact attestation
uses: actions/attest@v4
with:
repository-url: https://test.pypi.org/legacy/
subject-path: "dist/*"
- name: Publish distribution to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
51 changes: 51 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: Rust

on:
push:
branches:
- main
pull_request: ~

permissions:
contents: read

jobs:
fmt:
name: fmt (${{ matrix.workspace }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
workspace:
- .
- py-bindings
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt
- name: cargo fmt --check
working-directory: ${{ matrix.workspace }}
run: cargo fmt --all --check

build:
name: build (${{ matrix.workspace }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
workspace:
- .
- py-bindings
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: '3.x'
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
workspaces: ${{ matrix.workspace }}
- name: cargo build
working-directory: ${{ matrix.workspace }}
run: cargo build --workspace --all-targets --locked
2 changes: 1 addition & 1 deletion .github/workflows/test-pytest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install ".[ml]"
pip install -e ".[ml]"
pip install pytest
- name: Test with pytest
run: |
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -183,4 +183,5 @@ prof/*
*.sh

# Claude
.claude
.claude
.langs/
Loading
Loading