Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
ae9275d
feat(forge-rl): bootstrap v2 distributed runtime
MrLPF Aug 21, 2026
36bf6de
feat(forge-rl): implement M1 local high-throughput runtime
MrLPF Aug 21, 2026
373b40e
feat(forge-rl): add M1 acceptance harness
MrLPF Aug 21, 2026
be84cce
feat(forge-rl): add controlled M1 PPO learning gate
MrLPF Aug 21, 2026
ce94906
perf(forge-rl): optimize M1 node-local inference hot path
MrLPF Aug 21, 2026
72a9d1a
fix(forge-rl): restore UTF-8 README encoding
MrLPF Aug 21, 2026
f58d8b0
feat(forge-rl): add event-driven M1 descriptor collection
MrLPF Aug 21, 2026
fe81353
fix(forge-rl): preserve optimized inference constructor compatibility
MrLPF Aug 21, 2026
a1a3b35
perf(forge-rl): add persistent synchronous inference mailbox
MrLPF Aug 21, 2026
98cc31e
perf(forge-rl): prebind mailbox views and align batch release
MrLPF Aug 21, 2026
d8c6e7b
fix(forge-rl): correct fast mailbox acceptance schema
MrLPF Aug 21, 2026
d4432bf
perf(forge-rl): greedily drain ready mailbox requests
MrLPF Aug 21, 2026
7d16b4b
perf(forge-rl): isolate mailbox predictor in a dedicated process
MrLPF Aug 21, 2026
327ec2e
perf(forge-rl): add actor-local CPU inference fast path
MrLPF Aug 22, 2026
f4abe4b
perf(forge-rl): batch threaded actors without IPC
MrLPF Aug 22, 2026
6d180ad
perf(forge-rl): add rendezvous-aware actor wave batching
MrLPF Aug 22, 2026
911e917
perf(forge-rl): make rendezvous batching the M1 in-process default
MrLPF Aug 22, 2026
9105d8a
test(forge-rl): verify staggered Actor rendezvous and timeout fallback
MrLPF Aug 22, 2026
4427afa
perf(forge-rl): coalesce synchronous Actor waves before worker dispatch
MrLPF Aug 22, 2026
62ad8f2
fix(forge-rl): keep each rendezvous wave atomic in the worker
MrLPF Aug 22, 2026
0448676
perf(forge-rl): use bounded sliding arrival windows for Actor batching
MrLPF Aug 22, 2026
87d5faf
perf(forge-rl): tighten rendezvous hard wait to the measured 1 ms budget
MrLPF Aug 22, 2026
b39681b
perf(forge-rl): restore empirically better 2 ms hard batching budget
MrLPF Aug 22, 2026
664c3b7
bench(forge-rl): add work-conserving double-buffer screening
MrLPF Aug 22, 2026
b4766e3
ci(forge-rl): run the focused M1 double-buffer screening
MrLPF Aug 22, 2026
90c009c
perf(forge-rl): add direct vector-batch inference path
MrLPF Aug 22, 2026
10f5a60
feat(forge-rl): export direct vector-batch inference runtime
MrLPF Aug 22, 2026
663a0a7
bench(forge-rl): add direct vector-batch M1 acceptance subject
MrLPF Aug 22, 2026
a64ee81
bench(forge-rl): export vector-batch acceptance subject
MrLPF Aug 22, 2026
f047d8d
bench(forge-rl): expose vector-batch M1 screening mode
MrLPF Aug 22, 2026
8c23b56
bench(forge-rl): support direct vector-batch double-buffer screening
MrLPF Aug 22, 2026
f15ea14
test(forge-rl): verify direct vector-batch inference contracts
MrLPF Aug 22, 2026
0265198
ci(forge-rl): screen direct vector-batch sampling path
MrLPF Aug 22, 2026
1f1ac67
ci(forge-rl): repeat vector-batch screening for stability
MrLPF Aug 22, 2026
0c7741b
feat(forge-rl): use vector-batch runtime for M1 learning gate
MrLPF Aug 22, 2026
e8b2ae0
feat(forge-rl): align M1 learning with vector-batch subject
MrLPF Aug 22, 2026
32d6674
test(forge-rl): use FP32-appropriate mailbox tolerances
MrLPF Aug 22, 2026
76a5607
test(forge-rl): close the C++ vector-env M1 training loop
MrLPF Aug 22, 2026
3e51953
ci(forge-rl): make vector-batch the complete M1 formal subject
MrLPF Aug 22, 2026
94558fa
docs(forge-rl): finish the M1 vector-batch implementation checklist
MrLPF Aug 22, 2026
d400c4c
docs(forge-rl): define one vector-batch M1 acceptance subject
MrLPF Aug 22, 2026
ff71f01
docs(forge-rl): make vector-batch the local production data path
MrLPF Aug 22, 2026
cce9a69
feat(forge-rl): preserve coordinator generations across lease expiry
MrLPF Aug 23, 2026
62891e1
feat(forge-rl): add networked coordinator service and client
MrLPF Aug 23, 2026
e08ce29
feat(forge-rl): export M2 network coordinator contracts
MrLPF Aug 23, 2026
ffea6ed
test(forge-rl): validate M2 network coordinator fencing and discovery
MrLPF Aug 23, 2026
523a3a5
feat(forge-rl): add M2 coordinator service launcher
MrLPF Aug 23, 2026
ab48b90
docs(forge-rl): define M2 network coordinator contract
MrLPF Aug 23, 2026
eb55b58
docs(forge-rl): enter M2 with M1 formal validation pending locally
MrLPF Aug 23, 2026
b902ac0
feat(forge-rl): add direct M2 experience and policy channels
MrLPF Aug 23, 2026
805878d
feat(forge-rl): export M2 direct data channels
MrLPF Aug 23, 2026
e044534
test(forge-rl): validate M2 direct experience and policy channels
MrLPF Aug 23, 2026
bb3520c
docs(forge-rl): specify M2 direct data channels
MrLPF Aug 23, 2026
d2c68da
docs(forge-rl): mark M2 direct channels complete
MrLPF Aug 23, 2026
25e6958
fix(forge-rl): encode scalar policy tensors safely
MrLPF Aug 23, 2026
521bdc8
feat(forge-rl): add topology-independent distributed checkpoints
MrLPF Aug 23, 2026
1784468
test(forge-rl): verify topology-independent checkpoint restore
MrLPF Aug 23, 2026
5bfabf1
feat(forge-rl): export distributed checkpoint manager
MrLPF Aug 23, 2026
7c360f9
docs(forge-rl): specify topology-independent checkpoint contract
MrLPF Aug 23, 2026
0295d1f
docs(forge-rl): mark topology-independent checkpoint complete
MrLPF Aug 23, 2026
c67ed98
feat(forge-rl): add restartable process supervisor for M2 recovery
MrLPF Aug 23, 2026
d590457
test(forge-rl): inject actor and inference replica failures
MrLPF Aug 23, 2026
12f9a79
test(forge-rl): restart failed learner group from distributed checkpoint
MrLPF Aug 23, 2026
9433a25
feat(forge-rl): export M2 failure recovery supervisor
MrLPF Aug 23, 2026
3cbe4b3
docs(forge-rl): document M2 component restart recovery
MrLPF Aug 23, 2026
6c0daa7
docs(forge-rl): mark M2 failure injection complete
MrLPF Aug 23, 2026
d8a9b9e
bench(forge-rl): add M2 weak-scaling acceptance harness
MrLPF Aug 24, 2026
9faeb11
bench(forge-rl): export M2 acceptance utilities
MrLPF Aug 24, 2026
f196ef5
bench(forge-rl): add M2 distributed worker entrypoint
MrLPF Aug 24, 2026
40084fe
bench(forge-rl): add M2 acceptance report entrypoint
MrLPF Aug 24, 2026
b66b172
test(forge-rl): cover M2 weak-scaling acceptance
MrLPF Aug 24, 2026
15aa3cf
ci(forge-rl): add formal M2 two-node acceptance workflow
MrLPF Aug 24, 2026
7f1be19
docs(forge-rl): define formal M2 acceptance
MrLPF Aug 24, 2026
1630775
docs(forge-rl): add M2 formal acceptance gate
MrLPF Aug 24, 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
191 changes: 191 additions & 0 deletions .github/workflows/forge-rl-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
name: ForgeRL CI

on:
pull_request:
paths:
- "ForgeRL/**"
- ".github/workflows/forge-rl-ci.yml"
push:
branches: [master]
paths:
- "ForgeRL/**"
- ".github/workflows/forge-rl-ci.yml"

permissions:
contents: read

jobs:
core:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.11", "3.12"]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: pip
cache-dependency-path: ForgeRL/pyproject.toml
- name: Install CPU dependencies
working-directory: ForgeRL
run: |
python -m pip install --upgrade pip
pip install torch --index-url https://download.pytorch.org/whl/cpu
pip install -e '.[dev]'
- name: Compile source tree
working-directory: ForgeRL
run: python -m compileall -q src tests scripts
- name: Core tests
working-directory: ForgeRL
run: pytest -q -m 'not distributed'
- name: Runtime microbenchmark
working-directory: ForgeRL
run: python scripts/benchmark_runtime.py --items 20000 --width 64 --slots 32
- name: M1 fast-mailbox inference microbenchmark
working-directory: ForgeRL
run: |
python scripts/benchmark_m1_inference.py \
--service-mode mailbox-fast \
--actors 2 --requests-per-actor 25 --items-per-request 4 \
--width 16 --max-batch-items 16 --min-batch-items 8
- name: M1 v1/v2 acceptance correctness smoke
if: matrix.python-version == '3.12'
working-directory: ForgeRL
env:
OMP_NUM_THREADS: "1"
MKL_NUM_THREADS: "1"
run: |
python scripts/benchmark_m1_acceptance.py \
--actors 2 --requests-per-actor 8 --items-per-request 2 \
--width 16 --output-size 4 --max-batch-items 8 \
--v2-min-batch-items 4 --legacy-min-batch-items 1 \
--max-wait-ms 0.5 --request-slots 4 --throughput-gate 0 \
--output benchmarks/results/m1-acceptance-smoke.json
- name: M1 mailbox tuning matrix smoke
if: matrix.python-version == '3.12'
working-directory: ForgeRL
env:
OMP_NUM_THREADS: "1"
MKL_NUM_THREADS: "1"
run: |
python scripts/benchmark_m1_tuning_matrix.py \
--preset smoke --repeats 1 --warmup-repeats 0 \
--requests-per-actor 8 \
--output benchmarks/results/m1-tuning-matrix-smoke.json
- name: M1 target-scale mailbox screening
if: matrix.python-version == '3.12'
working-directory: ForgeRL
env:
OMP_NUM_THREADS: "1"
MKL_NUM_THREADS: "1"
run: |
python scripts/benchmark_m1_acceptance.py \
--actors 8 --requests-per-actor 250 --items-per-request 8 \
--width 64 --output-size 4 --max-batch-items 128 \
--v2-min-batch-items 32 --legacy-min-batch-items 1 \
--max-wait-ms 0.5 --request-slots 8 --throughput-gate 0 \
--output benchmarks/results/m1-target-scale-screening.json
- name: M1 vector-batch sampling stability screening
if: matrix.python-version == '3.12'
working-directory: ForgeRL
env:
OMP_NUM_THREADS: "1"
MKL_NUM_THREADS: "1"
OPENBLAS_NUM_THREADS: "1"
NUMEXPR_NUM_THREADS: "1"
run: |
python scripts/benchmark_m1_double_buffer.py \
--actors 8 --requests-per-actor 1000 --items-per-request 8 \
--width 64 --output-size 4 --max-batch-items 128 \
--min-batch-items 64 --max-wait-ms 0.5 \
--v2-runtime vector-batch \
--repeats 3 --warmup-repeats 1 \
--output benchmarks/results/m1-double-buffer-screening.json
- name: Upload M1 acceptance smoke report
if: matrix.python-version == '3.12'
uses: actions/upload-artifact@v4
with:
name: forgerl-m1-acceptance-smoke
path: ForgeRL/benchmarks/results/m1-acceptance-smoke.json
if-no-files-found: error
- name: Upload M1 tuning matrix smoke report
if: matrix.python-version == '3.12'
uses: actions/upload-artifact@v4
with:
name: forgerl-m1-tuning-matrix-smoke
path: ForgeRL/benchmarks/results/m1-tuning-matrix-smoke.json
if-no-files-found: error
- name: Upload M1 target-scale screening report
if: matrix.python-version == '3.12'
uses: actions/upload-artifact@v4
with:
name: forgerl-m1-target-scale-screening
path: ForgeRL/benchmarks/results/m1-target-scale-screening.json
if-no-files-found: error
- name: Upload M1 vector-batch screening report
if: matrix.python-version == '3.12'
uses: actions/upload-artifact@v4
with:
name: forgerl-m1-vector-batch-screening
path: ForgeRL/benchmarks/results/m1-double-buffer-screening.json
if-no-files-found: error

distributed:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip
cache-dependency-path: ForgeRL/pyproject.toml
- name: Install CPU dependencies
working-directory: ForgeRL
run: |
python -m pip install --upgrade pip
pip install torch --index-url https://download.pytorch.org/whl/cpu
pip install -e '.[dev]'
- name: Two-process Gloo learner test
working-directory: ForgeRL
run: pytest -q -m distributed

gym-smoke:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip
cache-dependency-path: ForgeRL/pyproject.toml
- name: Install Gymnasium benchmark dependencies
working-directory: ForgeRL
run: |
python -m pip install --upgrade pip
pip install torch --index-url https://download.pytorch.org/whl/cpu
pip install -e '.[dev,gym]'
- name: CartPole environment smoke benchmark
working-directory: ForgeRL
run: python scripts/benchmark_env.py --env CartPole-v1 --envs 8 --steps 5000
- name: Pendulum environment smoke benchmark
working-directory: ForgeRL
run: python scripts/benchmark_env.py --env Pendulum-v1 --envs 8 --steps 5000
- name: M1 PPO learning plumbing smoke
working-directory: ForgeRL
env:
OMP_NUM_THREADS: "1"
MKL_NUM_THREADS: "1"
run: |
python scripts/benchmark_m1_learning.py \
--smoke --seeds 7 \
--environments CartPole-v1,Pendulum-v1 \
--device cpu \
--output benchmarks/results/m1-learning-smoke.json
- name: Upload M1 learning smoke report
uses: actions/upload-artifact@v4
with:
name: forgerl-m1-learning-smoke
path: ForgeRL/benchmarks/results/m1-learning-smoke.json
if-no-files-found: error
27 changes: 27 additions & 0 deletions .github/workflows/forge-rl-gpu-smoke.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: ForgeRL GPU learner smoke

on:
workflow_dispatch:

permissions:
contents: read

jobs:
torchrun:
runs-on: [self-hosted, linux, x64, gpu]
steps:
- uses: actions/checkout@v4
- name: Install ForgeRL
working-directory: ForgeRL
run: pip install -e '.[dev]'
- name: Run local multi-GPU learner group
working-directory: ForgeRL
env:
FORGE_RL_EXPECTED_GPUS: "2"
run: |
python - <<'PY'
import os, torch
expected = int(os.environ['FORGE_RL_EXPECTED_GPUS'])
assert torch.cuda.device_count() >= expected, (torch.cuda.device_count(), expected)
PY
torchrun --standalone --nproc-per-node=2 scripts/distributed_smoke.py
137 changes: 137 additions & 0 deletions .github/workflows/forge-rl-m1-formal.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
name: ForgeRL M1 formal acceptance

on:
workflow_dispatch:
inputs:
device:
description: Pre-provisioned benchmark device
required: true
default: cpu
type: choice
options: [cpu, cuda]
seeds:
description: Exactly five or more comma-separated seeds
required: true
default: "1,2,3,4,5"
type: string

permissions:
contents: read

jobs:
formal-m1:
runs-on: [self-hosted, linux, x64, forgerl-benchmark]
timeout-minutes: 720
env:
OMP_NUM_THREADS: "1"
MKL_NUM_THREADS: "1"
OPENBLAS_NUM_THREADS: "1"
NUMEXPR_NUM_THREADS: "1"
steps:
- uses: actions/checkout@v4
- name: Verify pinned benchmark image
working-directory: ForgeRL
run: |
command -v taskset >/dev/null || { echo "taskset is required" >&2; exit 2; }
test -n "${FORGERL_CPUSET:-}" || {
echo "FORGERL_CPUSET must identify the pinned benchmark cores" >&2
exit 2
}
python - <<'PY'
import os
import gymnasium
import numpy
import torch
expected_torch = os.environ.get("FORGERL_EXPECTED_TORCH")
expected_gym = os.environ.get("FORGERL_EXPECTED_GYMNASIUM")
if expected_torch and torch.__version__ != expected_torch:
raise SystemExit(f"torch {torch.__version__} != {expected_torch}")
if expected_gym and gymnasium.__version__ != expected_gym:
raise SystemExit(f"gymnasium {gymnasium.__version__} != {expected_gym}")
requested = "${{ inputs.device }}"
if requested == "cuda" and not torch.cuda.is_available():
raise SystemExit("CUDA formal acceptance requested but CUDA is unavailable")
print({
"python": __import__("sys").version.split()[0],
"torch": torch.__version__,
"numpy": numpy.__version__,
"gymnasium": gymnasium.__version__,
"cuda": torch.cuda.is_available(),
"cpuset": os.environ["FORGERL_CPUSET"],
})
PY
python -m pip install -e . --no-deps
- name: Run five-seed CartPole/Pendulum vector-batch learning gate
working-directory: ForgeRL
run: |
taskset -c "$FORGERL_CPUSET" \
python scripts/benchmark_m1_learning.py \
--seeds "${{ inputs.seeds }}" \
--environments CartPole-v1,Pendulum-v1 \
--device "${{ inputs.device }}" \
--require-learning-gate \
--output benchmarks/results/m1-learning-formal.json
python - <<'PY'
import json
from pathlib import Path
report = json.loads(Path("benchmarks/results/m1-learning-formal.json").read_text())
if report.get("status") != "GO" or not report.get("learning_gate_passed"):
raise SystemExit("formal learning gate did not pass")
runtimes = {
run.get("runtime_metrics", {}).get("runtime")
for run in report.get("runs", [])
if run.get("subject") == "v2"
}
if runtimes != {"vector-batch-learning"}:
raise SystemExit(f"formal v2 learning used unexpected runtimes: {runtimes}")
PY
- name: Run controlled vector-batch stability gate
working-directory: ForgeRL
run: |
taskset -c "$FORGERL_CPUSET" \
python scripts/benchmark_m1_double_buffer.py \
--actors 8 --requests-per-actor 2000 --items-per-request 8 \
--width 64 --output-size 4 --max-batch-items 128 \
--min-batch-items 64 --max-wait-ms 0.5 \
--v2-runtime vector-batch \
--repeats 3 --warmup-repeats 1 --controlled \
--output benchmarks/results/m1-vector-batch-controlled.json
python - <<'PY'
import json
from pathlib import Path
report = json.loads(Path("benchmarks/results/m1-vector-batch-controlled.json").read_text())
if report.get("status") != "DOUBLE_BUFFER_CANDIDATE":
raise SystemExit(f"vector-batch stability gate failed: {report.get('status')}")
if not report.get("formal_eligible") or not report.get("double_buffer_stable_two_x"):
raise SystemExit("vector-batch evidence is not formal and stable >=2x")
if not report.get("work_conservation", {}).get("identical"):
raise SystemExit("single/double-buffer work is not identical")
if not report.get("single_buffer", {}).get("correctness_passed"):
raise SystemExit("single-buffer correctness failed")
if not report.get("double_buffer", {}).get("correctness_passed"):
raise SystemExit("double-buffer correctness failed")
PY
- name: Run final vector-batch M1 gate
working-directory: ForgeRL
run: |
taskset -c "$FORGERL_CPUSET" \
python scripts/benchmark_m1_acceptance.py \
--actors 8 --requests-per-actor 2000 --items-per-request 8 \
--width 64 --max-batch-items 128 \
--v2-min-batch-items 64 --legacy-min-batch-items 1 \
--v2-runtime vector-batch \
--device "${{ inputs.device }}" \
--throughput-gate 2.0 \
--learning-report benchmarks/results/m1-learning-formal.json \
--require-go \
--output benchmarks/results/m1-final.json
- name: Upload formal M1 evidence
if: always()
uses: actions/upload-artifact@v4
with:
name: forgerl-m1-formal-evidence
path: |
ForgeRL/benchmarks/results/m1-learning-formal.json
ForgeRL/benchmarks/results/m1-vector-batch-controlled.json
ForgeRL/benchmarks/results/m1-final.json
if-no-files-found: warn
Loading
Loading