diff --git a/.github/ISSUE_TEMPLATE/01-bug-report.yml b/.github/ISSUE_TEMPLATE/01-bug-report.yml
new file mode 100644
index 0000000..059ded3
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/01-bug-report.yml
@@ -0,0 +1,79 @@
+name: Bug report
+description: Report a crash, incorrect metric, API break, or other reproducible problem
+title: "[Bug] "
+labels: ["bug"]
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Thanks for reporting a NetForge issue. For usage questions, use Discussions.
+ - type: checkboxes
+ id: checks
+ attributes:
+ label: Before submitting
+ options:
+ - label: I searched existing issues and did not find the same problem.
+ required: true
+ - label: I can reproduce this on the latest `main` branch.
+ required: true
+ - type: textarea
+ id: problem
+ attributes:
+ label: What happened?
+ validations:
+ required: true
+ - type: textarea
+ id: expected
+ attributes:
+ label: Expected behavior
+ validations:
+ required: true
+ - type: textarea
+ id: reproduce
+ attributes:
+ label: Minimal reproduction
+ description: `netforge …` or a few lines of PettingZoo / Gymnasium code.
+ render: shell
+ validations:
+ required: true
+ - type: input
+ id: version
+ attributes:
+ label: NetForge version / commit
+ validations:
+ required: true
+ - type: dropdown
+ id: area
+ attributes:
+ label: Area
+ options:
+ - Environment / PettingZoo
+ - Gymnasium facade
+ - Arena / questions / submissions
+ - Diagnostics / agent cards
+ - JAX backend
+ - SIEM / NLP
+ - Datasets / replay
+ - Docs
+ - Other
+ validations:
+ required: true
+ - type: input
+ id: os
+ attributes:
+ label: Operating system
+ placeholder: "Windows 11 / Ubuntu 24.04 / macOS 15"
+ validations:
+ required: true
+ - type: input
+ id: python
+ attributes:
+ label: Python version
+ placeholder: "3.12.8"
+ validations:
+ required: true
+ - type: textarea
+ id: logs
+ attributes:
+ label: Logs
+ render: shell
diff --git a/.github/ISSUE_TEMPLATE/02-feature-request.yml b/.github/ISSUE_TEMPLATE/02-feature-request.yml
new file mode 100644
index 0000000..0aecee4
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/02-feature-request.yml
@@ -0,0 +1,59 @@
+name: Feature request
+description: Propose gym infrastructure — not a new exploit family
+title: "[Proposal] "
+labels: ["enhancement"]
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Prefer wrappers, metrics, packs, probes, and docs. Algorithms belong in
+ their own repos and should be *evaluated on* NetForge. If the design is
+ not obvious, use the Research template.
+ - type: checkboxes
+ id: checks
+ attributes:
+ label: Before submitting
+ options:
+ - label: I searched existing issues and Discussions for a similar proposal.
+ required: true
+ - label: This is gym/benchmark infrastructure, not a vendored trainer.
+ required: true
+ - type: dropdown
+ id: category
+ attributes:
+ label: Proposal type
+ options:
+ - Scenario pack
+ - Metric / agent card
+ - Capability probe
+ - Wrapper (reward, constraint, comm)
+ - Dataset / Minari
+ - Docs
+ - Interop (PettingZoo, Gymnasium, JaxMARL)
+ - Other
+ validations:
+ required: true
+ - type: textarea
+ id: problem
+ attributes:
+ label: What problem does this solve?
+ validations:
+ required: true
+ - type: textarea
+ id: proposal
+ attributes:
+ label: Proposed solution
+ description: Smallest useful implementation.
+ validations:
+ required: true
+ - type: textarea
+ id: out_of_scope
+ attributes:
+ label: Out of scope
+ - type: textarea
+ id: validation
+ attributes:
+ label: How should this be validated?
+ description: Tests, Arena seeds, a named `netforge questions` entry.
+ validations:
+ required: true
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 0000000..2742d81
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,14 @@
+blank_issues_enabled: true
+contact_links:
+ - name: Ask a question
+ url: https://github.com/reforcemind/NetForge_RL/discussions
+ about: Usage or architecture questions. Use Research issues for scoped design work.
+ - name: Documentation
+ url: https://reforcemind.github.io/NetForge_RL/
+ about: Getting started, Arena, questions, API.
+ - name: Research backlog
+ url: https://github.com/reforcemind/NetForge_RL/blob/main/RESEARCH.md
+ about: Public research issues and good first contributions
+ - name: Arena spec
+ url: https://github.com/reforcemind/NetForge_RL/blob/main/docs/arena.md
+ about: Frozen benchmark contract (splits, metrics, hidden tests)
diff --git a/.github/ISSUE_TEMPLATE/good_first_issue.yml b/.github/ISSUE_TEMPLATE/good_first_issue.yml
new file mode 100644
index 0000000..4608db1
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/good_first_issue.yml
@@ -0,0 +1,22 @@
+name: Good first issue
+description: Small gym/infrastructure task for new contributors
+title: "[good first issue] "
+labels: ["good first issue"]
+body:
+ - type: markdown
+ attributes:
+ value: "Prefer scenario packs, metrics, probes, docs, or wrappers — not new exploits."
+ - type: textarea
+ id: task
+ attributes:
+ label: Task
+ description: What should land in the gym?
+ validations:
+ required: true
+ - type: dropdown
+ id: kind
+ attributes:
+ label: Kind
+ options: [scenario pack, metric, capability probe, wrapper, docs, replay, dataset]
+ validations:
+ required: true
diff --git a/.github/ISSUE_TEMPLATE/research.yml b/.github/ISSUE_TEMPLATE/research.yml
new file mode 100644
index 0000000..338d072
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/research.yml
@@ -0,0 +1,20 @@
+name: Research
+description: A research question the gym should make easy to answer
+title: "[research] "
+labels: ["research"]
+body:
+ - type: markdown
+ attributes:
+ value: "Algorithms belong in their own repos and should be *evaluated on* NetForge."
+ - type: textarea
+ id: question
+ attributes:
+ label: Question
+ description: Generalization, safety, adaptation, POMDP, temporal, self-play, …
+ validations:
+ required: true
+ - type: textarea
+ id: protocol
+ attributes:
+ label: Arena protocol
+ description: Split, seeds, metrics, baselines. Hidden tests if it is a leaderboard claim.
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000..a3b9537
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,15 @@
+## Summary
+
+
+## Evidence
+
+
+```text
+
+```
+
+## Checklist
+- [ ] One issue, one PR
+- [ ] Tests added or updated
+- [ ] Did not vendor a training algorithm (MAPPO / QMIX / CT-GMARL stay out of tree)
+- [ ] User-path docs updated only if the user path changed
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..bd0d467
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,57 @@
+name: CI
+
+on:
+ push:
+ branches: [main]
+ pull_request:
+
+permissions:
+ contents: read
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ lint:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-python@v5
+ with:
+ python-version: "3.12"
+ - run: python -m pip install --upgrade pip
+ - run: pip install ruff
+ - run: ruff format --check .
+ - run: ruff check .
+
+ test:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-python@v5
+ with:
+ python-version: "3.12"
+ - run: python -m pip install --upgrade pip
+ - run: pip install -e ".[dev]"
+ - run: pytest tests/ --cov=netforge_rl --cov-report=xml --cov-fail-under=50
+ - uses: codecov/codecov-action@v4
+ with:
+ token: ${{ secrets.CODECOV_TOKEN }}
+ fail_ci_if_error: false
+
+ docs:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-python@v5
+ with:
+ python-version: "3.12"
+ - run: python -m pip install --upgrade pip
+ - run: pip install -e ".[docs]"
+ - run: sphinx-build -b html -W --keep-going docs docs/_build/html
+ - run: touch docs/_build/html/.nojekyll
+ - uses: actions/upload-artifact@v4
+ with:
+ name: docs-html
+ path: docs/_build/html
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
new file mode 100644
index 0000000..65d89cb
--- /dev/null
+++ b/.github/workflows/docs.yml
@@ -0,0 +1,40 @@
+name: Docs
+
+on:
+ push:
+ branches: [main]
+
+permissions:
+ contents: read
+ pages: write
+ id-token: write
+
+concurrency:
+ group: pages
+ cancel-in-progress: true
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-python@v5
+ with:
+ python-version: "3.12"
+ - run: python -m pip install --upgrade pip
+ - run: pip install -e ".[docs]"
+ - run: sphinx-build -b html -W --keep-going docs docs/_build/html
+ - run: touch docs/_build/html/.nojekyll
+ - uses: actions/upload-pages-artifact@v3
+ with:
+ path: docs/_build/html
+
+ deploy:
+ needs: build
+ runs-on: ubuntu-latest
+ environment:
+ name: github-pages
+ url: ${{ steps.deploy.outputs.page_url }}
+ steps:
+ - id: deploy
+ uses: actions/deploy-pages@v4
diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml
deleted file mode 100644
index 74909be..0000000
--- a/.github/workflows/python-app.yml
+++ /dev/null
@@ -1,51 +0,0 @@
-name: CI Pipeline
-
-on:
- push:
- branches: [ "main" ]
- pull_request:
- branches: [ "main" ]
-
-permissions:
- contents: read
-
-jobs:
- lint:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - name: Set up Python 3.12
- uses: actions/setup-python@v5
- with:
- python-version: "3.12"
- - name: Install dependencies
- run: |
- python -m pip install --upgrade pip
- pip install ruff
- - name: Check formatting with ruff
- run: ruff format --check .
- - name: Lint with ruff
- run: ruff check .
-
- test:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - name: Set up Python 3.12
- uses: actions/setup-python@v5
- with:
- python-version: "3.12"
- - name: Install dependencies
- run: |
- python -m pip install --upgrade pip
- pip install -e .
- pip install pytest pytest-cov scikit-learn gymnasium pettingzoo networkx pyyaml
- - name: Run tests with pytest
- run: |
- pytest tests/ -v --cov=netforge_rl --cov-report=xml --cov-fail-under=50
- - name: Upload coverage reports to Codecov
- uses: codecov/codecov-action@v4
- with:
- token: ${{ secrets.CODECOV_TOKEN }}
- fail_ci_if_error: false
-
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000..52b56c7
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,12 @@
+# Agent notes
+
+Verification is local. GitHub Actions (`ci.yml`) runs ruff + pytest + Sphinx.
+`docs.yml` deploys the HTML site to GitHub Pages on push to `main`.
+
+- Full gate: `scripts/verify_all.sh` (Linux/Git Bash) or `scripts/verify_local.ps1` (Windows)
+- User CLI: `python -m netforge` / `netforge`
+- Docs: `sphinx-build -b html -W --keep-going docs docs/_build/html`
+- Contract: `docs/guides/verification.md`
+
+Sister project docs kit: [FlowEdge](https://github.com/reforcemind/FlowEdge).
+Do not vendor MAPPO/QMIX/CT-GMARL into this tree.
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000..e270b8b
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,129 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+We as members, contributors, and leaders pledge to make participation in our
+community a harassment-free experience for everyone, regardless of age, body
+size, visible or invisible disability, ethnicity, sex characteristics, gender
+identity and expression, level of experience, education, socio-economic status,
+nationality, personal appearance, race, caste, color, religion, or sexual
+identity and orientation.
+
+We pledge to act and interact in ways that contribute to an open, welcoming,
+diverse, inclusive, and healthy community.
+
+## Our Standards
+
+Examples of behavior that contributes to a positive environment for our
+community include:
+
+* Demonstrating empathy and kindness toward other people
+* Being respectful of differing opinions, viewpoints, and experiences
+* Giving and gracefully accepting constructive feedback
+* Accepting responsibility and apologizing to those affected by our mistakes,
+ and learning from the experience
+* Focusing on what is best not just for us as individuals, but for the overall
+ community
+
+Examples of unacceptable behavior include:
+
+* The use of sexualized language or imagery, and sexual attention or advances of
+ any kind
+* Trolling, insulting or derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or email address,
+ without their explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Enforcement Responsibilities
+
+Community leaders are responsible for clarifying and enforcing our standards of
+acceptable behavior and will take appropriate and fair corrective action in
+response to any behavior that they deem inappropriate, threatening, offensive,
+or harmful.
+
+Community leaders have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions that are
+not aligned to this Code of Conduct, and will communicate reasons for moderation
+decisions when appropriate.
+
+## Scope
+
+This Code of Conduct applies within all community spaces, and also applies when
+an individual is officially representing the community in public spaces.
+Examples of representing our community include using an official e-mail
+address, posting via an official social media account, or acting as an appointed
+representative at an online or offline event.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported through a
+[private GitHub security advisory](https://github.com/reforcemind/NetForge_RL/security/advisories/new).
+All complaints will be reviewed and investigated promptly and fairly.
+
+All community leaders are obligated to respect the privacy and security of the
+reporter of any incident.
+
+## Enforcement Guidelines
+
+Community leaders will follow these Community Impact Guidelines in determining
+the consequences for any action they deem in violation of this Code of Conduct:
+
+### 1. Correction
+
+**Community Impact**: Use of inappropriate language or other behavior deemed
+unprofessional or unwelcome in the community.
+
+**Consequence**: A private, written warning from community leaders, providing
+clarity around the nature of the violation and an explanation of why the
+behavior was inappropriate. A public apology may be requested.
+
+### 2. Warning
+
+**Community Impact**: A violation through a single incident or series of
+actions.
+
+**Consequence**: A warning with consequences for continued behavior. No
+interaction with the people involved, including unsolicited interaction with
+those enforcing the Code of Conduct, for a specified period of time. This
+includes avoiding interactions in community spaces as well as external channels
+like social media. Violating these terms may lead to a temporary or
+permanent ban.
+
+### 3. Temporary Ban
+
+**Community Impact**: A serious violation of community standards, including
+sustained inappropriate behavior.
+
+**Consequence**: A temporary ban from any sort of interaction or public
+communication with the community for a specified period of time. No public or
+private interaction with the people involved, including unsolicited interaction
+with those enforcing the Code of Conduct, is allowed during this period.
+Violating these terms may lead to a permanent ban.
+
+### 4. Permanent Ban
+
+**Community Impact**: Demonstrating a pattern of violation of community
+standards, including sustained inappropriate behavior, harassment of an
+individual, or aggression toward or disparagement of classes of individuals.
+
+**Consequence**: A permanent ban from any sort of public interaction within
+the community.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage],
+version 2.1, available at
+https://www.contributor-covenant.org/version/2/1/code_of_conduct.html.
+
+Community Impact Guidelines were inspired by
+[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
+
+For answers to common questions about this code of conduct, see the FAQ at
+https://www.contributor-covenant.org/faq. Translations are available at
+https://www.contributor-covenant.org/translations.
+
+[homepage]: https://www.contributor-covenant.org
+[Mozilla CoC]: https://github.com/mozilla/diversity
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..e856d34
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,26 @@
+# Contributing
+
+NetForge is a cybersecurity RL gym. Prefer packs, metrics, wrappers, probes,
+datasets, docs. MAPPO / QMIX stay in other repos. Blue trains on SIEM, not
+ground-truth compromise.
+
+[Code of Conduct](CODE_OF_CONDUCT.md).
+[Discussions](https://github.com/reforcemind/NetForge_RL/discussions) if issues are locked.
+
+- YAML pack
+- Probe in `netforge_rl/arena/questions/`
+- Reward variant
+- HTML replay
+- Capability probe
+
+Issue → one PR from `main` → tests for behavior changes.
+
+```bash
+pip install -e ".[dev,docs]"
+ruff check . && ruff format .
+pytest tests/ -m fast
+sphinx-build -b html -W --keep-going docs docs/_build/html
+```
+
+Gate: `scripts/verify_all.sh` or `scripts/verify_local.ps1`.
+GitHub Actions is ruff + pytest + Sphinx. `docs.yml` deploys GitHub Pages on `main`.
diff --git a/README.md b/README.md
index 25421a7..e8824c1 100644
--- a/README.md
+++ b/README.md
@@ -57,9 +57,9 @@ import netforge_rl
import gymnasium as gym
from pettingzoo import make
-env = make("parallel", "netforge/ransomware-v4", max_ticks=80)
+env = make('parallel', 'netforge/ransomware-v4', max_ticks=80)
obs, infos = env.reset(seed=0)
-blue = gym.make("NetForge/Blue-v4", max_ticks=80)
+blue = gym.make('NetForge/Blue-v4', max_ticks=80)
```