Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
855fcb7
Implement new binary protocol for hegel-rust
DRMacIver Jan 27, 2026
d65c9df
Add claude-reliability config
DRMacIver Jan 28, 2026
3ddcf58
Update .gitignore for claude-reliability
DRMacIver Jan 28, 2026
3d70c6b
Remove external mode, fix server/client roles
DRMacIver Jan 28, 2026
ee9cefb
TEMPORARY: Get Hegel from new-protocol branch
DRMacIver Jan 28, 2026
56b8ed6
Use serde for CBOR serialization instead of manual conversion
DRMacIver Jan 28, 2026
4f45879
Fix connection deadlock and clippy warnings
DRMacIver Jan 28, 2026
110510f
Apply rustfmt and suppress dead_code warnings
DRMacIver Jan 28, 2026
07b2172
Fix message ID collision and StopTest handling
DRMacIver Jan 28, 2026
dc447bb
Update minimum Rust version to 1.81
DRMacIver Jan 28, 2026
06fbcb8
Fix Rust SDK to use correct three-level channel protocol
DRMacIver Feb 2, 2026
bb82cfb
Fix CI: StopTest detection, mark_complete race, formatting, and nix
DRMacIver Feb 5, 2026
63c9f59
Fix NaN/infinity float values lost through CBOR deserialization
DRMacIver Feb 5, 2026
3625433
Fix unused variable warning that breaks test_output tests
DRMacIver Feb 5, 2026
de8cd6b
Trigger fresh CI run
DRMacIver Feb 5, 2026
5bec7b5
Fix integer overflow in test_optional_mapped
DRMacIver Feb 5, 2026
8a015d0
Gitignore all .claude/ directories
DRMacIver Feb 5, 2026
f1c13ce
Rename embedded.rs to runner.rs
DRMacIver Feb 5, 2026
114bd94
Remove dead code and unnecessary #[allow(dead_code)] annotations
DRMacIver Feb 5, 2026
36163d9
Refactor from serde_json::Value to ciborium::Value
DRMacIver Feb 5, 2026
3b9bc35
Switch hegel dependency back to main branch
DRMacIver Feb 6, 2026
fc5dd0d
Update CI to use hegel main branch
DRMacIver Feb 6, 2026
2023b0e
Ignore claude-reliability config
DRMacIver Feb 6, 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
19 changes: 10 additions & 9 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ cargo test --all-features # Run tests including optional features
hegel-rust/
├── src/
│ ├── lib.rs # Public API: hegel(), Hegel builder, assume(), note()
│ ├── embedded.rs # Spawns hegel CLI, manages socket server
│ ├── cbor_helpers.rs # Macros and helpers for ciborium::Value (cbor_map!, cbor_array!, map_get, etc.)
│ ├── runner.rs # Spawns hegel CLI, manages socket server
│ └── gen/ # Generator implementations
│ ├── mod.rs # Generate trait, socket communication, thread-local state
│ ├── primitives.rs # unit(), booleans(), just(), just_any()
Expand Down Expand Up @@ -55,16 +56,16 @@ hegel-rust/

### How It Works

The SDK spawns the `hegel` CLI as a subprocess with `--client-mode`. The test binary creates a Unix socket server, and hegel connects for each test case. The build script (`build.rs`) automatically installs Python and hegel into cargo's `OUT_DIR/hegel` via uv if not found on PATH.
The SDK creates a socket path and spawns the `hegel` CLI as a subprocess. Hegeld binds to the socket and listens for connections. The SDK then connects as a client, and a single persistent connection is maintained for the program run. Multiple tests can be executed over this connection. The build script (`build.rs`) automatically installs Python and hegel into cargo's `OUT_DIR/hegel` via uv if not found on PATH.

### Protocol

Each test case follows this handshake:
1. Hegel connects to the SDK's socket
2. Hegel sends: `{"is_last_run": bool}` (is_last_run=true on final replay for output)
3. SDK responds: `{"type": "handshake_ack"}`
4. SDK runs test, communicating via `generate`/`start_span`/`stop_span` commands
5. SDK sends result: `{"type": "test_result", "result": "pass"|"fail"|"reject", ...}`
The protocol uses CBOR encoding over multiplexed channels. For each test:
1. SDK sends `run_test` request on control channel
2. Hegeld sends `test_case` events with channel IDs for each test case
3. SDK runs test function, sending `generate`/`start_span`/`stop_span` requests on the test channel
4. SDK sends `mark_complete` with status (VALID, INVALID, or INTERESTING)
5. After all test cases, hegeld sends `test_done` with results`

### Thread-Local State

Expand All @@ -75,7 +76,7 @@ The SDK uses thread-local storage for:
### Generation Protocol

Generators implement the `Generate<T>` trait:
- `schema()`: Returns JSON Schema describing generated values (enables single-request composition)
- `schema()`: Returns a CBOR schema (as `ciborium::Value`) describing generated values (enables single-request composition)
- `generate()`: Produces a value, either via schema or compositional fallback

When `schema()` returns `Some`, the SDK sends one request. When `None` (after `map`/`filter`), it falls back to multiple requests with span grouping for shrinking.
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
strategy:
matrix:
# keep this in sync with the rust-version in cargo.toml
rust: ["1.68", stable]
rust: ["1.81", stable]
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/base
Expand All @@ -46,7 +46,7 @@ jobs:
strategy:
matrix:
# keep this in sync with the rust-version in cargo.toml
rust: ["1.68", stable]
rust: ["1.81", stable]
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/base
Expand Down Expand Up @@ -102,7 +102,7 @@ jobs:
python-version: '3.13'
- name: Install hegel
run: |
pip install git+ssh://git@github.com/antithesishq/hegel.git
pip install git+ssh://git@github.com/antithesishq/hegel.git@main
pip install pytest
- name: Build conformance binaries
working-directory: tests/conformance/rust
Expand Down
10 changes: 9 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,13 @@
.hegel
__pycache__
target/
.claude/settings.local.json
**/.claude/
result
.claude-reliability/
.claude/reliability-config.yml

# claude-reliability managed
.claude/bin/
.claude/*.local.md
.claude/*.local.json
.claude/*.local
101 changes: 65 additions & 36 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,22 @@ name = "hegel"
version = "0.1.0"
edition = "2021"
# if you bump this, also bump ci.yml and hegel-derive/cargo.toml
rust-version = "1.68"
rust-version = "1.81"
description = "Property-based testing SDK for the Hegel test data generator"
license = "MIT"
readme = "README.md"
repository = "https://github.com/antithesishq/hegel-rust"

[dependencies]
serde = { version = "1.0", features = ["derive"] }
# float_roundtrip fixes parsing of floats like "0.9999999999999999"
# See: https://github.com/serde-rs/json/issues/1303
serde_json = { version = "1.0", features = ["float_roundtrip"] }
num = "0.4"
paste = "1.0"
hegel-derive = { path = "hegel-derive" }
tempfile = "3.0"
rand = { version = "0.9", optional = true }
# Binary protocol support
ciborium = "0.2"
crc32fast = "1.4"

[dev-dependencies]
regex = "1.0"
Expand Down
2 changes: 1 addition & 1 deletion build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ fn ensure_hegel() -> PathBuf {
.args([
"pip",
"install",
"git+ssh://git@github.com/antithesishq/hegel.git",
"git+ssh://git@github.com/antithesishq/hegel.git@main",
])
.arg("--python")
.arg(venv_path.join("bin").join("python"))
Expand Down
Loading