crucible-rl 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. crucible_rl-0.1.0/.gitattributes +4 -0
  2. crucible_rl-0.1.0/.github/CODEOWNERS +3 -0
  3. crucible_rl-0.1.0/.github/workflows/ci.yml +26 -0
  4. crucible_rl-0.1.0/.gitignore +25 -0
  5. crucible_rl-0.1.0/CONTRIBUTING.md +39 -0
  6. crucible_rl-0.1.0/CONVENTIONS.md +37 -0
  7. crucible_rl-0.1.0/LICENSE +20 -0
  8. crucible_rl-0.1.0/PKG-INFO +258 -0
  9. crucible_rl-0.1.0/README.md +225 -0
  10. crucible_rl-0.1.0/ROADMAP.md +116 -0
  11. crucible_rl-0.1.0/crucible/__init__.py +43 -0
  12. crucible_rl-0.1.0/crucible/cli.py +83 -0
  13. crucible_rl-0.1.0/crucible/env.py +71 -0
  14. crucible_rl-0.1.0/crucible/envs/__init__.py +22 -0
  15. crucible_rl-0.1.0/crucible/envs/code.py +82 -0
  16. crucible_rl-0.1.0/crucible/envs/command.py +79 -0
  17. crucible_rl-0.1.0/crucible/envs/guess.py +71 -0
  18. crucible_rl-0.1.0/crucible/envs/http.py +75 -0
  19. crucible_rl-0.1.0/crucible/envs/sql.py +91 -0
  20. crucible_rl-0.1.0/crucible/envs/terminal.py +91 -0
  21. crucible_rl-0.1.0/crucible/export.py +75 -0
  22. crucible_rl-0.1.0/crucible/integrations/__init__.py +7 -0
  23. crucible_rl-0.1.0/crucible/integrations/trl.py +71 -0
  24. crucible_rl-0.1.0/crucible/integrations/verifiers.py +53 -0
  25. crucible_rl-0.1.0/crucible/registry.py +46 -0
  26. crucible_rl-0.1.0/crucible/reward.py +59 -0
  27. crucible_rl-0.1.0/crucible/rollout.py +144 -0
  28. crucible_rl-0.1.0/crucible/sandbox.py +204 -0
  29. crucible_rl-0.1.0/crucible/trajectory.py +107 -0
  30. crucible_rl-0.1.0/docs/ARCHITECTURE.md +282 -0
  31. crucible_rl-0.1.0/docs/BACKLOG.md +205 -0
  32. crucible_rl-0.1.0/docs/VISION.md +100 -0
  33. crucible_rl-0.1.0/docs/assets/grpo_sql.png +0 -0
  34. crucible_rl-0.1.0/docs/assets/grpo_suite.png +0 -0
  35. crucible_rl-0.1.0/docs/assets/loop.svg +60 -0
  36. crucible_rl-0.1.0/docs/assets/xmodal.png +0 -0
  37. crucible_rl-0.1.0/examples/__init__.py +1 -0
  38. crucible_rl-0.1.0/examples/agents.py +48 -0
  39. crucible_rl-0.1.0/examples/demo.py +92 -0
  40. crucible_rl-0.1.0/examples/learn.py +102 -0
  41. crucible_rl-0.1.0/examples/results/README.md +111 -0
  42. crucible_rl-0.1.0/examples/results/grpo_sql_rewards.json +29 -0
  43. crucible_rl-0.1.0/examples/results/grpo_suite.json +287 -0
  44. crucible_rl-0.1.0/examples/results/plot_grpo.py +82 -0
  45. crucible_rl-0.1.0/examples/results/plot_grpo_suite.py +89 -0
  46. crucible_rl-0.1.0/examples/results/plot_xmodal.py +89 -0
  47. crucible_rl-0.1.0/examples/results/xmodal.json +212 -0
  48. crucible_rl-0.1.0/examples/train_grpo.py +258 -0
  49. crucible_rl-0.1.0/examples/train_grpo_suite.py +186 -0
  50. crucible_rl-0.1.0/examples/train_xmodal.py +231 -0
  51. crucible_rl-0.1.0/pyproject.toml +52 -0
  52. crucible_rl-0.1.0/space/README.md +39 -0
  53. crucible_rl-0.1.0/space/app.py +114 -0
  54. crucible_rl-0.1.0/space/requirements.txt +2 -0
  55. crucible_rl-0.1.0/tests/test_cli.py +98 -0
  56. crucible_rl-0.1.0/tests/test_code_env.py +78 -0
  57. crucible_rl-0.1.0/tests/test_command_env.py +54 -0
  58. crucible_rl-0.1.0/tests/test_core.py +143 -0
  59. crucible_rl-0.1.0/tests/test_docker_sandbox.py +37 -0
  60. crucible_rl-0.1.0/tests/test_envs.py +130 -0
  61. crucible_rl-0.1.0/tests/test_export.py +59 -0
  62. crucible_rl-0.1.0/tests/test_http_env.py +55 -0
  63. crucible_rl-0.1.0/tests/test_learning.py +33 -0
  64. crucible_rl-0.1.0/tests/test_persistence.py +80 -0
  65. crucible_rl-0.1.0/tests/test_pytest_repo.py +56 -0
  66. crucible_rl-0.1.0/tests/test_registry.py +38 -0
  67. crucible_rl-0.1.0/tests/test_reward.py +83 -0
  68. crucible_rl-0.1.0/tests/test_sandbox.py +97 -0
  69. crucible_rl-0.1.0/tests/test_terminal_env.py +68 -0
  70. crucible_rl-0.1.0/tests/test_train_grpo.py +68 -0
  71. crucible_rl-0.1.0/tests/test_train_grpo_suite.py +47 -0
  72. crucible_rl-0.1.0/tests/test_train_xmodal.py +59 -0
  73. crucible_rl-0.1.0/tests/test_trl_integration.py +43 -0
  74. crucible_rl-0.1.0/tests/test_verifiers_integration.py +35 -0
@@ -0,0 +1,4 @@
1
+ # Normalize line endings: text files are LF in the repo, checked out native.
2
+ * text=auto eol=lf
3
+ *.py text eol=lf
4
+ *.md text eol=lf
@@ -0,0 +1,3 @@
1
+ # Every path is owned by the maintainer, so with branch protection set to "require
2
+ # review from Code Owners", every pull request needs a maintainer +1 before it merges.
3
+ * @nadeauglenn1-max
@@ -0,0 +1,26 @@
1
+ name: ci
2
+
3
+ on:
4
+ push:
5
+ branches: [main, master]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ matrix:
13
+ python-version: ["3.11", "3.12", "3.13"]
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+
17
+ - uses: actions/setup-python@v5
18
+ with:
19
+ python-version: ${{ matrix.python-version }}
20
+
21
+ - name: Install
22
+ run: pip install -e ".[dev]"
23
+
24
+ - name: Test (coverage gate >= 90%)
25
+ # pyproject addopts already enforces --cov=crucible --cov-fail-under=90.
26
+ run: pytest
@@ -0,0 +1,25 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ .pytest_cache/
5
+ .venv/
6
+ venv/
7
+ *.egg-info/
8
+ build/
9
+ dist/
10
+
11
+ # Coverage
12
+ .coverage
13
+ htmlcov/
14
+ coverage.xml
15
+
16
+ # Local trajectories / runs (don't commit captured episodes)
17
+ /runs/
18
+ /runtime/
19
+ *.trajectory.json
20
+
21
+ # Editor / OS
22
+ .DS_Store
23
+ .idea/
24
+ .vscode/
25
+ *~
@@ -0,0 +1,39 @@
1
+ # Contributing to Crucible
2
+
3
+ Crucible is open source under the [MIT License](LICENSE) — fork it, build on it, ship
4
+ your own environments. Contributions back to this repository are welcome, with one
5
+ governing rule.
6
+
7
+ ## Every merge needs a maintainer +1
8
+
9
+ - `master` is protected — no direct pushes.
10
+ - Propose changes as a pull request from a fork or branch.
11
+ - [`.github/CODEOWNERS`](.github/CODEOWNERS) routes every path to the maintainer
12
+ (@nadeauglenn1-max), so with branch protection set to *require review from Code
13
+ Owners*, approval is enforced by the repo, not just by convention.
14
+ - The maintainer has final say on what merges.
15
+
16
+ ## The bar (same as every change here)
17
+
18
+ 1. **Tests ship with the change**, and coverage stays **≥ 90%** (`pytest` enforces
19
+ it; CI runs the gate on Python 3.11–3.13).
20
+ 2. **Docs move with the code** — update the README / `docs/` in the *same* PR that
21
+ changes behavior. New feature ⇒ its "how" in [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md)
22
+ or a backlog entry in [`docs/BACKLOG.md`](docs/BACKLOG.md).
23
+ 3. **The core stays zero-dependency.** Environments and agents may add dependencies;
24
+ `crucible/` core (env, trajectory, rollout, cli) imports only the standard library.
25
+ 4. **Honor the determinism contract.** An environment must be a pure function of its
26
+ seed and actions, or `replay` will (correctly) fail it.
27
+ 5. **Stay inside the boundary.** Crucible is training/eval infrastructure, not runtime
28
+ agent-accountability — see [`docs/VISION.md`](docs/VISION.md) §5.
29
+
30
+ ## Getting started
31
+
32
+ ```bash
33
+ pip install -e ".[dev]"
34
+ pytest
35
+ ```
36
+
37
+ New environments are the most valuable contribution — see the recipe in
38
+ [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) §7. By contributing, you agree your
39
+ contribution is provided under the project's MIT License.
@@ -0,0 +1,37 @@
1
+ # Crucible — Conventions
2
+
3
+ Standing conventions apply (reuse over rebuild, fix-don't-flag, docs-never-lag-code,
4
+ no-MVP production bar, clean-room provenance, tests ship with the change).
5
+ Project-specific notes:
6
+
7
+ ## Core stays tiny and dependency-free
8
+
9
+ The `crucible` core (`env`, `trajectory`, `rollout`, `replay`) imports only the
10
+ Python standard library. Environments and agents may pull dependencies; the core
11
+ may not. Adoption is a feature, and a zero-dependency core is how you get it.
12
+
13
+ ## The determinism contract is law
14
+
15
+ `reset(seed)` fully determines an episode. Same seed + same actions ⇒ same
16
+ observations, rewards, and digests. `replay` verifies this and **reports mismatches
17
+ loudly** — a non-reproducible environment is a bug we surface, never one we hide.
18
+
19
+ ## Provenance boundary (read `docs/VISION.md` §5)
20
+
21
+ Crucible is training/eval infrastructure. Reward = **programmatic task-success
22
+ checking**. Do **not** drift into runtime agent-accountability, tamper-evident
23
+ trust, or governance — that is a different field and the author's separate IP lives
24
+ there. If a design starts to look like "prove what a deployed agent did," stop.
25
+
26
+ ## Quality gates
27
+
28
+ - **Coverage ≥ 90%** on the core + envs, enforced in CI; tests ship with the code.
29
+ - Deterministic tests only — no flaky sleeps; drive time/seeds explicitly.
30
+ - Docs move with the code (README, `docs/VISION.md`) in the same change.
31
+
32
+ ## Provenance
33
+
34
+ Clean-room: personal account and environment only, its own history, no code from
35
+ the author's other projects. Licensed **MIT**; public. Contributions merge only with
36
+ green CI plus a maintainer +1 (CODEOWNERS + branch protection) — see
37
+ [`CONTRIBUTING.md`](CONTRIBUTING.md).
@@ -0,0 +1,20 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Glenn Nadeau
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,258 @@
1
+ Metadata-Version: 2.4
2
+ Name: crucible-rl
3
+ Version: 0.1.0
4
+ Summary: Turn any real software into a trainable, gradable, replayable RL environment for AI agents.
5
+ Project-URL: Homepage, https://github.com/nadeauglenn1-max/crucible
6
+ Project-URL: Repository, https://github.com/nadeauglenn1-max/crucible
7
+ Project-URL: Issues, https://github.com/nadeauglenn1-max/crucible/issues
8
+ Author: Glenn Nadeau
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: agents,environments,evaluation,grpo,gymnasium,llm,reinforcement-learning,rl,rlvr,training
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.11
23
+ Provides-Extra: dev
24
+ Requires-Dist: pytest-cov>=5; extra == 'dev'
25
+ Requires-Dist: pytest>=8; extra == 'dev'
26
+ Provides-Extra: train
27
+ Requires-Dist: accelerate>=0.30; extra == 'train'
28
+ Requires-Dist: datasets>=2.19; extra == 'train'
29
+ Requires-Dist: peft>=0.11; extra == 'train'
30
+ Requires-Dist: transformers>=4.44; extra == 'train'
31
+ Requires-Dist: trl>=0.15; extra == 'train'
32
+ Description-Content-Type: text/markdown
33
+
34
+ # Crucible
35
+
36
+ > **Crucible** — both the vessel that contains and the trial that transforms, which is
37
+ > exactly what an environment does to an agent.
38
+
39
+ **Crucible turns any real software into a trainable, gradable world for AI agents.**
40
+
41
+ ![The Crucible loop: wrap real software into an environment, train an agent in it, and replay every episode](docs/assets/loop.svg)
42
+
43
+ Wrap a CLI, a database, a codebase, or an API in a few lines and it becomes an
44
+ *environment*: an agent can be run through it, scored on real outcomes, and — the
45
+ part nobody else has — its whole episode **replayed deterministically**, so every run
46
+ is reproducible and every reward is auditable.
47
+
48
+ ```python
49
+ from crucible import rollout, replay
50
+
51
+ traj = rollout(my_env, my_agent, seed=0) # run the agent, record the episode
52
+ report = replay(fresh_env, traj) # re-run and verify it byte-for-byte
53
+ assert report.ok
54
+ traj.save("episode.trajectory.json") # the artifact leaves memory
55
+ ```
56
+
57
+ ## Why this exists
58
+
59
+ The frontier of AI moved off pre-training. Models now improve by **doing** —
60
+ reinforcement learning in environments — and the field agrees on the bottleneck:
61
+ *"RL environments are the key bottleneck to the next wave of AI progress, but big
62
+ labs are locking them down."* Environments are the **training data of 2026**, and
63
+ there is no open, easy way to *make* them. The open ecosystem has a hub (Prime
64
+ Intellect) and a training stack (TRL, verifiers, prime-rl) — it does not have a great
65
+ open **authoring layer**. That's the seam Crucible fills. The full argument is in
66
+ [`docs/VISION.md`](docs/VISION.md).
67
+
68
+ ## It actually trains a model
69
+
70
+ Not a toy: a `SQLTaskEnv` used *directly* as a GRPO reward — no labels, no hand-written
71
+ reward code — took `Qwen2.5-0.5B-Instruct` from **5% → 100%** on a real SQL task in 80
72
+ steps on a single laptop GPU. The model discovered the query itself, guided only by the
73
+ environment.
74
+
75
+ ![A 0.5B model learns a SQL task from a Crucible environment](docs/assets/grpo_sql.png)
76
+
77
+ And it's **not one lucky task** — a fresh model trained on four *distinct* SQL skills
78
+ improved on every one (subquery, `SUM`, `HAVING`, `AVG`). The method trains, not the
79
+ task.
80
+
81
+ ![Four SQL skills, four fresh models, each taught by a Crucible environment](docs/assets/grpo_suite.png)
82
+
83
+ And **not just SQL** — the identical loop trains *different kinds of agents*: a **shell**
84
+ agent (`CommandEnv`, 70→100%) and a **coding** agent graded by *really running its code*
85
+ (`CodeTaskEnv`, 55→85%), alongside a database agent. Only the environment changes. Full
86
+ runs + how to reproduce: [`examples/results/`](examples/results/README.md).
87
+
88
+ ![One training loop, three different environment types](docs/assets/xmodal.png)
89
+
90
+ ## Install
91
+
92
+ ```bash
93
+ pip install crucible-rl # the zero-dependency core, Python 3.11+
94
+ pip install "crucible-rl[train]" # + the RL stack, to reproduce the GRPO run
95
+ pip install -e ".[dev]" # or hack on it from a clone
96
+ ```
97
+
98
+ ## Quickstart (60 seconds)
99
+
100
+ Run the built-in demo — three real worlds, each forged and replayed:
101
+
102
+ ```bash
103
+ python -m examples.demo
104
+ ```
105
+
106
+ ```
107
+ === CodeTaskEnv - fix the bug so the test goes green (the reward writes itself) ===
108
+ steps: 2 total reward: +0.90 replay: reproduced OK
109
+ ```
110
+
111
+ Inspect a saved episode from the terminal:
112
+
113
+ ```bash
114
+ crucible show episode.trajectory.json # summary + integrity check
115
+ ```
116
+
117
+ ## Core concepts
118
+
119
+ Three nouns, two verbs — the whole core is ~180 lines and imports only the standard
120
+ library.
121
+
122
+ | Piece | What it is |
123
+ | --- | --- |
124
+ | **`Environment`** | Real software wrapped with `reset(seed)` / `step(action)` |
125
+ | **`Agent`** | Anything with `act(observation) -> action` (scripted, search, an LLM) |
126
+ | **`Trajectory`** | The replayable episode record (seed, observations, actions, rewards) |
127
+ | **`rollout`** | Drives an agent through an environment and records a Trajectory |
128
+ | **`replay`** | Re-runs a Trajectory against a fresh environment and verifies it |
129
+
130
+ How each of these works internally — the rollout loop, the replay verifier, the
131
+ determinism contract, digests, the on-disk format — is documented to junior-dev
132
+ detail in **[`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md)**.
133
+
134
+ ## Write your own environment
135
+
136
+ Wrap software you already have; implement two methods and (optionally) a digest:
137
+
138
+ ```python
139
+ from crucible.env import Environment, StepResult
140
+
141
+ class ReverseStringEnv(Environment):
142
+ def __init__(self, target: str):
143
+ self.target = target
144
+ def reset(self, seed: int):
145
+ return {"task": f"reverse: {self.target!r}"}
146
+ def step(self, action):
147
+ correct = str(action) == self.target[::-1]
148
+ return StepResult(
149
+ observation={"you_said": str(action)},
150
+ reward=1.0 if correct else -0.1,
151
+ done=correct,
152
+ info={"correct": correct},
153
+ )
154
+ ```
155
+
156
+ The rules that make an environment *replayable* (determinism, JSON-serializable
157
+ observations, verifiable reward, digests) and a full worked example are in
158
+ [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) §7.
159
+
160
+ ## The example environments (`crucible/envs/`)
161
+
162
+ | Env | Shows |
163
+ | --- | --- |
164
+ | `GuessEnv` | A fully deterministic game — the clean proof that replay reproduces an episode exactly |
165
+ | `SQLTaskEnv` | Wrapping **real SQLite** — reward is programmatic and verifiable (run the query, compare the rows) |
166
+ | `CodeTaskEnv` | The SWE-agent shape — **the test suite is the reward function** (edit files, grader runs, green is the reward) |
167
+ | `CommandEnv` | Wrap any **command-line tool** — the agent emits a command, reward is exit-0 + stdout match (sandboxed, registerable) |
168
+ | `TerminalEnv` | A **stateful shell session** — commands accumulate state across steps (mkdir here, write there); reward is a goal over the workdir |
169
+ | `HttpTaskEnv` | Wrap a **recorded HTTP service** (VCR/cassette) — the agent finds the right request; deterministic and registerable |
170
+
171
+ ## The CLI
172
+
173
+ - `crucible show <file>` — summarize a saved episode (env, seed, steps, reward,
174
+ fingerprint) and integrity-check it.
175
+ - `crucible replay <file>` — rebuild the environment from the registry and **re-run**
176
+ the episode, confirming it reproduces (or printing the mismatches). Works for
177
+ registered environments; see [ARCHITECTURE §6c](docs/ARCHITECTURE.md).
178
+
179
+ ## Project layout
180
+
181
+ ```
182
+ crucible/ the zero-dependency core + example environments
183
+ env.py the Environment contract (reset/step, determinism, digest)
184
+ trajectory.py the replayable record (JSON, versioned save/load, fingerprint)
185
+ rollout.py rollout() records; replay() re-runs and verifies
186
+ registry.py register/make envs by name (powers `crucible replay`)
187
+ reward.py Rubric — partial-credit rewards from weighted checks
188
+ sandbox.py run a grader/command in a subprocess (safe for untrusted code)
189
+ export.py flatten trajectories to {prompt, completion, reward} / JSONL
190
+ cli.py the `crucible` command
191
+ envs/ Guess, SQLTask, CodeTask, Command, Terminal, HttpTask
192
+ examples/ demo, agents, and the GRPO training runs + results (not packaged)
193
+ tests/ the suite (100% coverage, enforced in CI)
194
+ docs/ VISION (why), ARCHITECTURE (how), BACKLOG (what's next)
195
+ ```
196
+
197
+ ## Development
198
+
199
+ ```bash
200
+ pip install -e ".[dev]"
201
+ pytest # runs the suite; pyproject enforces --cov-fail-under=90
202
+ ```
203
+
204
+ CI (`.github/workflows/ci.yml`) runs the same gate on Python 3.11–3.13. Every change
205
+ ships with tests and moves the docs in the same commit (see
206
+ [`CONVENTIONS.md`](CONVENTIONS.md)).
207
+
208
+ ## Status & roadmap
209
+
210
+ **V1 (the MVP) is complete**, and the repo is **public under MIT** with tests, CI,
211
+ and a code-owner +1 required to merge. Author → run → grade → replay → persist, as a
212
+ real tool, on one code path, 100% coverage. Where it goes from here — the three-phase
213
+ direction — is in **[`ROADMAP.md`](ROADMAP.md)**; the per-item "how to build it" detail
214
+ is in **[`docs/BACKLOG.md`](docs/BACKLOG.md)**. Progress at a glance:
215
+
216
+ **Built**
217
+
218
+ - [x] Core — `Environment` contract, `Trajectory`, `rollout`, `replay`
219
+ - [x] Deterministic replay that verifies the whole episode (observations, rewards, digests)
220
+ - [x] Trajectory persistence (versioned format) + `crucible show` / `crucible replay` CLI
221
+ - [x] Environment registry (`register` / `make`) for rebuild-from-a-file replay
222
+ - [x] Sandboxed grading — subprocess (`SubprocessSandbox`) or container (`DockerSandbox`), fail-closed
223
+ - [x] Rubrics — partial-credit rewards from weighted checks
224
+ - [x] Environments: `GuessEnv`, `SQLTaskEnv`, `CodeTaskEnv`, `CommandEnv`, `TerminalEnv`, `HttpTaskEnv`
225
+ - [x] Real git-repo-with-pytest (by composition) — the agent turns real tests green
226
+ - [x] Training export — `{prompt, completion, reward}` / JSONL
227
+ - [x] TRL adapter — a Crucible environment *as* a GRPO reward function
228
+ - [x] verifiers adapter — same bridge for Prime Intellect's stack
229
+ - [x] CI + ≥90% coverage gate (Python 3.11–3.13)
230
+ - [x] Public (MIT); contributions via PR with green CI + a code-owner +1 required
231
+ - [x] Gradio demo app (`space/app.py`) — runs locally (`python space/app.py`)
232
+ - [x] **A real GRPO training run** — a 0.5B model learned a SQL task **5% → 100%**
233
+ with a Crucible environment *as* the reward, no labels; **generalizes** across
234
+ four distinct SQL skills **and three different environment types** (database,
235
+ shell, code) ([`examples/results/`](examples/results/README.md))
236
+ - [x] Packaging — `pip install crucible-rl` (zero-dep core) / `[train]` extra for the
237
+ RL stack; PyPI-publish-ready (metadata, wheel + sdist pass `twine check`)
238
+
239
+ **Next**
240
+
241
+ - [ ] Push the release to PyPI (packaging is ready; `twine upload` pending)
242
+ - [ ] Trajectory commons — shareable, auditable trajectory datasets on the Hub
243
+ - [ ] Host the demo Space *(app is built; hosting deferred — Hugging Face now
244
+ charges for Gradio Spaces, and a free static/`gradio-lite` port is the fallback)*
245
+ - [ ] Learned reward for non-verifiable tasks *(parked — research)*
246
+
247
+ ## What it is *not*
248
+
249
+ Crucible is **training/eval infrastructure** (the Gymnasium / Prime-Intellect
250
+ lineage). Its "verification" is programmatic task-success checking for reward. It is
251
+ deliberately **not** a runtime agent-accountability or governance system — a
252
+ different field. See [`docs/VISION.md`](docs/VISION.md) §5.
253
+
254
+ ## License & contributing
255
+
256
+ **MIT** ([`LICENSE`](LICENSE)) — fork it and build. The repo is public; contributions
257
+ are welcome via pull request, and every merge needs green CI (Python 3.11–3.13) plus a
258
+ code-owner +1 (see [`CONTRIBUTING.md`](CONTRIBUTING.md)).
@@ -0,0 +1,225 @@
1
+ # Crucible
2
+
3
+ > **Crucible** — both the vessel that contains and the trial that transforms, which is
4
+ > exactly what an environment does to an agent.
5
+
6
+ **Crucible turns any real software into a trainable, gradable world for AI agents.**
7
+
8
+ ![The Crucible loop: wrap real software into an environment, train an agent in it, and replay every episode](docs/assets/loop.svg)
9
+
10
+ Wrap a CLI, a database, a codebase, or an API in a few lines and it becomes an
11
+ *environment*: an agent can be run through it, scored on real outcomes, and — the
12
+ part nobody else has — its whole episode **replayed deterministically**, so every run
13
+ is reproducible and every reward is auditable.
14
+
15
+ ```python
16
+ from crucible import rollout, replay
17
+
18
+ traj = rollout(my_env, my_agent, seed=0) # run the agent, record the episode
19
+ report = replay(fresh_env, traj) # re-run and verify it byte-for-byte
20
+ assert report.ok
21
+ traj.save("episode.trajectory.json") # the artifact leaves memory
22
+ ```
23
+
24
+ ## Why this exists
25
+
26
+ The frontier of AI moved off pre-training. Models now improve by **doing** —
27
+ reinforcement learning in environments — and the field agrees on the bottleneck:
28
+ *"RL environments are the key bottleneck to the next wave of AI progress, but big
29
+ labs are locking them down."* Environments are the **training data of 2026**, and
30
+ there is no open, easy way to *make* them. The open ecosystem has a hub (Prime
31
+ Intellect) and a training stack (TRL, verifiers, prime-rl) — it does not have a great
32
+ open **authoring layer**. That's the seam Crucible fills. The full argument is in
33
+ [`docs/VISION.md`](docs/VISION.md).
34
+
35
+ ## It actually trains a model
36
+
37
+ Not a toy: a `SQLTaskEnv` used *directly* as a GRPO reward — no labels, no hand-written
38
+ reward code — took `Qwen2.5-0.5B-Instruct` from **5% → 100%** on a real SQL task in 80
39
+ steps on a single laptop GPU. The model discovered the query itself, guided only by the
40
+ environment.
41
+
42
+ ![A 0.5B model learns a SQL task from a Crucible environment](docs/assets/grpo_sql.png)
43
+
44
+ And it's **not one lucky task** — a fresh model trained on four *distinct* SQL skills
45
+ improved on every one (subquery, `SUM`, `HAVING`, `AVG`). The method trains, not the
46
+ task.
47
+
48
+ ![Four SQL skills, four fresh models, each taught by a Crucible environment](docs/assets/grpo_suite.png)
49
+
50
+ And **not just SQL** — the identical loop trains *different kinds of agents*: a **shell**
51
+ agent (`CommandEnv`, 70→100%) and a **coding** agent graded by *really running its code*
52
+ (`CodeTaskEnv`, 55→85%), alongside a database agent. Only the environment changes. Full
53
+ runs + how to reproduce: [`examples/results/`](examples/results/README.md).
54
+
55
+ ![One training loop, three different environment types](docs/assets/xmodal.png)
56
+
57
+ ## Install
58
+
59
+ ```bash
60
+ pip install crucible-rl # the zero-dependency core, Python 3.11+
61
+ pip install "crucible-rl[train]" # + the RL stack, to reproduce the GRPO run
62
+ pip install -e ".[dev]" # or hack on it from a clone
63
+ ```
64
+
65
+ ## Quickstart (60 seconds)
66
+
67
+ Run the built-in demo — three real worlds, each forged and replayed:
68
+
69
+ ```bash
70
+ python -m examples.demo
71
+ ```
72
+
73
+ ```
74
+ === CodeTaskEnv - fix the bug so the test goes green (the reward writes itself) ===
75
+ steps: 2 total reward: +0.90 replay: reproduced OK
76
+ ```
77
+
78
+ Inspect a saved episode from the terminal:
79
+
80
+ ```bash
81
+ crucible show episode.trajectory.json # summary + integrity check
82
+ ```
83
+
84
+ ## Core concepts
85
+
86
+ Three nouns, two verbs — the whole core is ~180 lines and imports only the standard
87
+ library.
88
+
89
+ | Piece | What it is |
90
+ | --- | --- |
91
+ | **`Environment`** | Real software wrapped with `reset(seed)` / `step(action)` |
92
+ | **`Agent`** | Anything with `act(observation) -> action` (scripted, search, an LLM) |
93
+ | **`Trajectory`** | The replayable episode record (seed, observations, actions, rewards) |
94
+ | **`rollout`** | Drives an agent through an environment and records a Trajectory |
95
+ | **`replay`** | Re-runs a Trajectory against a fresh environment and verifies it |
96
+
97
+ How each of these works internally — the rollout loop, the replay verifier, the
98
+ determinism contract, digests, the on-disk format — is documented to junior-dev
99
+ detail in **[`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md)**.
100
+
101
+ ## Write your own environment
102
+
103
+ Wrap software you already have; implement two methods and (optionally) a digest:
104
+
105
+ ```python
106
+ from crucible.env import Environment, StepResult
107
+
108
+ class ReverseStringEnv(Environment):
109
+ def __init__(self, target: str):
110
+ self.target = target
111
+ def reset(self, seed: int):
112
+ return {"task": f"reverse: {self.target!r}"}
113
+ def step(self, action):
114
+ correct = str(action) == self.target[::-1]
115
+ return StepResult(
116
+ observation={"you_said": str(action)},
117
+ reward=1.0 if correct else -0.1,
118
+ done=correct,
119
+ info={"correct": correct},
120
+ )
121
+ ```
122
+
123
+ The rules that make an environment *replayable* (determinism, JSON-serializable
124
+ observations, verifiable reward, digests) and a full worked example are in
125
+ [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) §7.
126
+
127
+ ## The example environments (`crucible/envs/`)
128
+
129
+ | Env | Shows |
130
+ | --- | --- |
131
+ | `GuessEnv` | A fully deterministic game — the clean proof that replay reproduces an episode exactly |
132
+ | `SQLTaskEnv` | Wrapping **real SQLite** — reward is programmatic and verifiable (run the query, compare the rows) |
133
+ | `CodeTaskEnv` | The SWE-agent shape — **the test suite is the reward function** (edit files, grader runs, green is the reward) |
134
+ | `CommandEnv` | Wrap any **command-line tool** — the agent emits a command, reward is exit-0 + stdout match (sandboxed, registerable) |
135
+ | `TerminalEnv` | A **stateful shell session** — commands accumulate state across steps (mkdir here, write there); reward is a goal over the workdir |
136
+ | `HttpTaskEnv` | Wrap a **recorded HTTP service** (VCR/cassette) — the agent finds the right request; deterministic and registerable |
137
+
138
+ ## The CLI
139
+
140
+ - `crucible show <file>` — summarize a saved episode (env, seed, steps, reward,
141
+ fingerprint) and integrity-check it.
142
+ - `crucible replay <file>` — rebuild the environment from the registry and **re-run**
143
+ the episode, confirming it reproduces (or printing the mismatches). Works for
144
+ registered environments; see [ARCHITECTURE §6c](docs/ARCHITECTURE.md).
145
+
146
+ ## Project layout
147
+
148
+ ```
149
+ crucible/ the zero-dependency core + example environments
150
+ env.py the Environment contract (reset/step, determinism, digest)
151
+ trajectory.py the replayable record (JSON, versioned save/load, fingerprint)
152
+ rollout.py rollout() records; replay() re-runs and verifies
153
+ registry.py register/make envs by name (powers `crucible replay`)
154
+ reward.py Rubric — partial-credit rewards from weighted checks
155
+ sandbox.py run a grader/command in a subprocess (safe for untrusted code)
156
+ export.py flatten trajectories to {prompt, completion, reward} / JSONL
157
+ cli.py the `crucible` command
158
+ envs/ Guess, SQLTask, CodeTask, Command, Terminal, HttpTask
159
+ examples/ demo, agents, and the GRPO training runs + results (not packaged)
160
+ tests/ the suite (100% coverage, enforced in CI)
161
+ docs/ VISION (why), ARCHITECTURE (how), BACKLOG (what's next)
162
+ ```
163
+
164
+ ## Development
165
+
166
+ ```bash
167
+ pip install -e ".[dev]"
168
+ pytest # runs the suite; pyproject enforces --cov-fail-under=90
169
+ ```
170
+
171
+ CI (`.github/workflows/ci.yml`) runs the same gate on Python 3.11–3.13. Every change
172
+ ships with tests and moves the docs in the same commit (see
173
+ [`CONVENTIONS.md`](CONVENTIONS.md)).
174
+
175
+ ## Status & roadmap
176
+
177
+ **V1 (the MVP) is complete**, and the repo is **public under MIT** with tests, CI,
178
+ and a code-owner +1 required to merge. Author → run → grade → replay → persist, as a
179
+ real tool, on one code path, 100% coverage. Where it goes from here — the three-phase
180
+ direction — is in **[`ROADMAP.md`](ROADMAP.md)**; the per-item "how to build it" detail
181
+ is in **[`docs/BACKLOG.md`](docs/BACKLOG.md)**. Progress at a glance:
182
+
183
+ **Built**
184
+
185
+ - [x] Core — `Environment` contract, `Trajectory`, `rollout`, `replay`
186
+ - [x] Deterministic replay that verifies the whole episode (observations, rewards, digests)
187
+ - [x] Trajectory persistence (versioned format) + `crucible show` / `crucible replay` CLI
188
+ - [x] Environment registry (`register` / `make`) for rebuild-from-a-file replay
189
+ - [x] Sandboxed grading — subprocess (`SubprocessSandbox`) or container (`DockerSandbox`), fail-closed
190
+ - [x] Rubrics — partial-credit rewards from weighted checks
191
+ - [x] Environments: `GuessEnv`, `SQLTaskEnv`, `CodeTaskEnv`, `CommandEnv`, `TerminalEnv`, `HttpTaskEnv`
192
+ - [x] Real git-repo-with-pytest (by composition) — the agent turns real tests green
193
+ - [x] Training export — `{prompt, completion, reward}` / JSONL
194
+ - [x] TRL adapter — a Crucible environment *as* a GRPO reward function
195
+ - [x] verifiers adapter — same bridge for Prime Intellect's stack
196
+ - [x] CI + ≥90% coverage gate (Python 3.11–3.13)
197
+ - [x] Public (MIT); contributions via PR with green CI + a code-owner +1 required
198
+ - [x] Gradio demo app (`space/app.py`) — runs locally (`python space/app.py`)
199
+ - [x] **A real GRPO training run** — a 0.5B model learned a SQL task **5% → 100%**
200
+ with a Crucible environment *as* the reward, no labels; **generalizes** across
201
+ four distinct SQL skills **and three different environment types** (database,
202
+ shell, code) ([`examples/results/`](examples/results/README.md))
203
+ - [x] Packaging — `pip install crucible-rl` (zero-dep core) / `[train]` extra for the
204
+ RL stack; PyPI-publish-ready (metadata, wheel + sdist pass `twine check`)
205
+
206
+ **Next**
207
+
208
+ - [ ] Push the release to PyPI (packaging is ready; `twine upload` pending)
209
+ - [ ] Trajectory commons — shareable, auditable trajectory datasets on the Hub
210
+ - [ ] Host the demo Space *(app is built; hosting deferred — Hugging Face now
211
+ charges for Gradio Spaces, and a free static/`gradio-lite` port is the fallback)*
212
+ - [ ] Learned reward for non-verifiable tasks *(parked — research)*
213
+
214
+ ## What it is *not*
215
+
216
+ Crucible is **training/eval infrastructure** (the Gymnasium / Prime-Intellect
217
+ lineage). Its "verification" is programmatic task-success checking for reward. It is
218
+ deliberately **not** a runtime agent-accountability or governance system — a
219
+ different field. See [`docs/VISION.md`](docs/VISION.md) §5.
220
+
221
+ ## License & contributing
222
+
223
+ **MIT** ([`LICENSE`](LICENSE)) — fork it and build. The repo is public; contributions
224
+ are welcome via pull request, and every merge needs green CI (Python 3.11–3.13) plus a
225
+ code-owner +1 (see [`CONTRIBUTING.md`](CONTRIBUTING.md)).