runledger 0.2.0__tar.gz → 0.2.2__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 (55) hide show
  1. {runledger-0.2.0 → runledger-0.2.2}/PKG-INFO +53 -17
  2. runledger-0.2.0/src/runledger.egg-info/PKG-INFO → runledger-0.2.2/README.md +48 -40
  3. {runledger-0.2.0 → runledger-0.2.2}/pyproject.toml +7 -1
  4. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/__init__.py +1 -1
  5. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/cli.py +228 -118
  6. runledger-0.2.2/src/runledger/reporting/__init__.py +17 -0
  7. runledger-0.2.2/src/runledger/reporting/failures.py +278 -0
  8. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/runner/subprocess.py +64 -8
  9. runledger-0.2.0/README.md → runledger-0.2.2/src/runledger.egg-info/PKG-INFO +76 -16
  10. {runledger-0.2.0 → runledger-0.2.2}/src/runledger.egg-info/SOURCES.txt +2 -0
  11. {runledger-0.2.0 → runledger-0.2.2}/LICENSE +0 -0
  12. {runledger-0.2.0 → runledger-0.2.2}/setup.cfg +0 -0
  13. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/__main__.py +0 -0
  14. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/artifacts/__init__.py +0 -0
  15. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/artifacts/junit.py +0 -0
  16. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/artifacts/report.py +0 -0
  17. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/artifacts/run_log.py +0 -0
  18. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/artifacts/summary.py +0 -0
  19. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/assertions/__init__.py +0 -0
  20. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/assertions/base.py +0 -0
  21. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/assertions/engine.py +0 -0
  22. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/assertions/json_schema.py +0 -0
  23. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/assertions/required_fields.py +0 -0
  24. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/assertions/tool_contract.py +0 -0
  25. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/baseline/__init__.py +0 -0
  26. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/baseline/io.py +0 -0
  27. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/baseline/models.py +0 -0
  28. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/cassette/__init__.py +0 -0
  29. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/cassette/loader.py +0 -0
  30. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/cassette/match.py +0 -0
  31. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/cassette/models.py +0 -0
  32. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/cassette/writer.py +0 -0
  33. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/config/__init__.py +0 -0
  34. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/config/loader.py +0 -0
  35. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/config/models.py +0 -0
  36. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/protocol/__init__.py +0 -0
  37. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/protocol/jsonl.py +0 -0
  38. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/protocol/messages.py +0 -0
  39. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/regression/__init__.py +0 -0
  40. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/regression/engine.py +0 -0
  41. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/runner/__init__.py +0 -0
  42. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/runner/budgets.py +0 -0
  43. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/runner/engine.py +0 -0
  44. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/runner/models.py +0 -0
  45. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/tools/__init__.py +0 -0
  46. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/tools/builtin.py +0 -0
  47. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/tools/registry.py +0 -0
  48. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/util/__init__.py +0 -0
  49. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/util/canonical_json.py +0 -0
  50. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/util/normalize.py +0 -0
  51. {runledger-0.2.0 → runledger-0.2.2}/src/runledger/util/redaction.py +0 -0
  52. {runledger-0.2.0 → runledger-0.2.2}/src/runledger.egg-info/dependency_links.txt +0 -0
  53. {runledger-0.2.0 → runledger-0.2.2}/src/runledger.egg-info/entry_points.txt +0 -0
  54. {runledger-0.2.0 → runledger-0.2.2}/src/runledger.egg-info/requires.txt +0 -0
  55. {runledger-0.2.0 → runledger-0.2.2}/src/runledger.egg-info/top_level.txt +0 -0
@@ -1,9 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: runledger
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: CI for tool-using agents: deterministic eval suites with record/replay, hard assertions, budgets, and PR regression gates.
5
5
  Author: RunLedger
6
6
  License-Expression: MIT
7
+ Project-URL: Homepage, https://runledger.io
8
+ Project-URL: Repository, https://github.com/runledger/Runledger
9
+ Project-URL: Documentation, https://github.com/runledger/Runledger/tree/main/docs
10
+ Project-URL: Changelog, https://github.com/runledger/Runledger/blob/main/CHANGELOG.md
7
11
  Keywords: llm,agents,evaluation,ci,github-actions,replay,testing,junit,jsonschema
8
12
  Requires-Python: >=3.9
9
13
  Description-Content-Type: text/markdown
@@ -30,25 +34,57 @@ Dynamic: license-file
30
34
 
31
35
  Website: https://runledger.io
32
36
 
33
- **Deterministic CI regression checks for tool-using agents.** Record tool calls once, replay in CI, and fail PRs on mismatches, contract violations, or budget regressions.
37
+ **Deterministic CI regression checks for tool-using agents.** Record tool calls once, replay them in CI, and fail the run when a schema, tool-order, or tool-call budget gate fails.
34
38
 
35
- - Demo repo: https://github.com/runledger/runledger-demo (main is green; regression branches fail for real reasons)
39
+ - Demo: https://github.com/ZackMitchell910/runledger-demo/pull/1 (intentionally left open to show RunLedger failing a bad agent change)
36
40
  - If this is useful, please star the repo (it helps a lot).
37
41
 
38
- RunLedger is a **CI harness**, not an "eval metrics framework":
39
- - **DeepEval-style tools** help you *score* behavior.
40
- - **RunLedger** helps you *ship safely* by making agent tests deterministic and merge-gated.
42
+ ## Five-minute quickstart
41
43
 
42
- ---
43
-
44
- ## Try it now (60 seconds)
44
+ From an empty directory, with Python 3.9+:
45
45
 
46
46
  ```bash
47
- pipx install runledger
47
+ python3 -m pip install runledger
48
48
  runledger init
49
49
  runledger run ./evals/demo --mode replay --baseline baselines/demo.json
50
50
  ```
51
51
 
52
+ `runledger init` writes:
53
+
54
+ - `evals/demo/` — replay suite, cassette, JSON Schema, and a small agent that calls `search_docs`
55
+ - `baselines/demo.json` — baseline from that passing run
56
+ - `.github/workflows/runledger.yml` — pull-request workflow that runs the same command
57
+
58
+ A second `runledger init` leaves those files unchanged. `--force` regenerates them.
59
+
60
+ The demo exits non-zero unless all three of these hold:
61
+
62
+ - **Schema.** The final output matches `evals/demo/schema.json` (`category` and `reply`).
63
+ - **Tool order.** The agent calls `search_docs` (`call_order` in `evals/demo/cases/t1.yaml`).
64
+ - **Tool-call budget.** The run stays within `max_tool_calls: 1`.
65
+
66
+ A passing run prints `PASS` and writes `runledger_out/demo/<run_id>/` (`summary.json`, `junit.xml`, `report.html`, `run.jsonl`). Commit the init files to run that gate on pull requests.
67
+
68
+ The same check as a GitHub Action. `suite.yaml` already points at `baselines/demo.json`, so the action compares against that baseline:
69
+
70
+ ```yaml
71
+ - id: evals
72
+ uses: runledger/Runledger@v0.2
73
+ with:
74
+ path: ./evals/demo
75
+ mode: replay
76
+ ```
77
+
78
+ This repo's `action.yml` also accepts a `baseline` input and sets `result` (`pass` or `fail`), `exit-code`, and `artifacts-path`. Those fields ship when a release containing this file is tagged. The in-repo self-test calls the action with `uses: ./`.
79
+
80
+ Page copy for runledger.io lives in `docs/site-quickstart.md`.
81
+
82
+ ---
83
+
84
+ RunLedger is a **CI harness**, not an "eval metrics framework":
85
+ - **DeepEval-style tools** help you *score* behavior.
86
+ - **RunLedger** helps you *ship safely* by making agent tests deterministic and merge-gated.
87
+
52
88
  ## Integrations (merged)
53
89
 
54
90
  - hoangsonww/Agentic-AI-Pipeline - https://github.com/hoangsonww/Agentic-AI-Pipeline/pull/24
@@ -73,7 +109,7 @@ RunLedger stops regressions by shifting from "vibes-based" evaluation to determi
73
109
 
74
110
  - **Record & replay:** record tool outputs once; replay them in CI for instant, stable tests.
75
111
  - **Strict contracts:** enforce tool schemas, calling order, and allowlists.
76
- - **Budget gating:** fail PRs automatically if wall time, tool-call count, or tool errors exceed defined limits.
112
+ - **Budget gating:** fail the run when tool-call count exceeds `max_tool_calls`. Wall time and tool-error caps are separate gates, configured with `max_wall_ms` and `max_tool_errors`.
77
113
 
78
114
  ### RunLedger vs evaluation frameworks
79
115
 
@@ -352,18 +388,18 @@ jobs:
352
388
  - uses: actions/checkout@v4
353
389
 
354
390
  - name: Run deterministic evals (replay)
391
+ id: evals
355
392
  uses: runledger/Runledger@v0.2
356
393
  with:
357
394
  path: ./evals/demo
358
395
  mode: replay
359
396
 
360
- - name: Upload eval artifacts
361
- uses: actions/upload-artifact@v4
362
- with:
363
- name: agent-eval-artifacts
364
- path: runledger_out/**
397
+ - name: Show the action result
398
+ run: echo "result=${{ steps.evals.outputs.result }} exit=${{ steps.evals.outputs.exit-code }}"
365
399
  ```
366
400
 
401
+ `runledger init` writes `.github/workflows/runledger.yml`, which installs the CLI and runs the suite with `--baseline`. The action above is the Marketplace entry in `action.yml`. It uploads `runledger_out/**` itself. On a release that contains this `action.yml`, the step also sets `result`, `exit-code`, and `artifacts-path`, and you can pass `baseline:` to override `suite.yaml`.
402
+
367
403
  ---
368
404
 
369
405
  ## Determinism guide (rules of the road)
@@ -386,6 +422,7 @@ jobs:
386
422
 
387
423
  ## Docs
388
424
 
425
+ - `docs/site-quickstart.md` -- five-minute copy for runledger.io
389
426
  - `docs/quickstart.md` -- install + first run
390
427
  - `docs/assertions.md` -- assertions, tool contracts, budgets
391
428
  - `docs/baselines.md` -- baselines, diffing, promotion
@@ -398,7 +435,6 @@ jobs:
398
435
  ## Roadmap
399
436
 
400
437
  * `init` templates for Python (OpenAI SDK), LangGraph/LangChain, and Node/TS
401
- * richer budgets (tokens/cost) via optional `task_metrics`
402
438
  * PR comments bot for regression summaries
403
439
  * plugin system for custom assertions
404
440
  * HTML report trace viewer improvements
@@ -1,27 +1,3 @@
1
- Metadata-Version: 2.4
2
- Name: runledger
3
- Version: 0.2.0
4
- Summary: CI for tool-using agents: deterministic eval suites with record/replay, hard assertions, budgets, and PR regression gates.
5
- Author: RunLedger
6
- License-Expression: MIT
7
- Keywords: llm,agents,evaluation,ci,github-actions,replay,testing,junit,jsonschema
8
- Requires-Python: >=3.9
9
- Description-Content-Type: text/markdown
10
- License-File: LICENSE
11
- Requires-Dist: typer>=0.9.0
12
- Requires-Dist: rich>=13.0.0
13
- Requires-Dist: pydantic>=2.0.0
14
- Requires-Dist: pyyaml>=6.0.0
15
- Requires-Dist: jsonschema>=4.0.0
16
- Requires-Dist: jinja2>=3.1.0
17
- Requires-Dist: eval_type_backport>=0.2.0; python_version < "3.10"
18
- Provides-Extra: dev
19
- Requires-Dist: pytest>=7.0.0; extra == "dev"
20
- Requires-Dist: pytest-timeout>=2.1.0; extra == "dev"
21
- Requires-Dist: ruff>=0.1.0; extra == "dev"
22
- Requires-Dist: mypy>=1.0.0; extra == "dev"
23
- Dynamic: license-file
24
-
25
1
  # RunLedger
26
2
 
27
3
  [![CI](https://github.com/runledger/Runledger/actions/workflows/ci.yml/badge.svg)](https://github.com/runledger/Runledger/actions/workflows/ci.yml)
@@ -30,25 +6,57 @@ Dynamic: license-file
30
6
 
31
7
  Website: https://runledger.io
32
8
 
33
- **Deterministic CI regression checks for tool-using agents.** Record tool calls once, replay in CI, and fail PRs on mismatches, contract violations, or budget regressions.
9
+ **Deterministic CI regression checks for tool-using agents.** Record tool calls once, replay them in CI, and fail the run when a schema, tool-order, or tool-call budget gate fails.
34
10
 
35
- - Demo repo: https://github.com/runledger/runledger-demo (main is green; regression branches fail for real reasons)
11
+ - Demo: https://github.com/ZackMitchell910/runledger-demo/pull/1 (intentionally left open to show RunLedger failing a bad agent change)
36
12
  - If this is useful, please star the repo (it helps a lot).
37
13
 
38
- RunLedger is a **CI harness**, not an "eval metrics framework":
39
- - **DeepEval-style tools** help you *score* behavior.
40
- - **RunLedger** helps you *ship safely* by making agent tests deterministic and merge-gated.
14
+ ## Five-minute quickstart
41
15
 
42
- ---
43
-
44
- ## Try it now (60 seconds)
16
+ From an empty directory, with Python 3.9+:
45
17
 
46
18
  ```bash
47
- pipx install runledger
19
+ python3 -m pip install runledger
48
20
  runledger init
49
21
  runledger run ./evals/demo --mode replay --baseline baselines/demo.json
50
22
  ```
51
23
 
24
+ `runledger init` writes:
25
+
26
+ - `evals/demo/` — replay suite, cassette, JSON Schema, and a small agent that calls `search_docs`
27
+ - `baselines/demo.json` — baseline from that passing run
28
+ - `.github/workflows/runledger.yml` — pull-request workflow that runs the same command
29
+
30
+ A second `runledger init` leaves those files unchanged. `--force` regenerates them.
31
+
32
+ The demo exits non-zero unless all three of these hold:
33
+
34
+ - **Schema.** The final output matches `evals/demo/schema.json` (`category` and `reply`).
35
+ - **Tool order.** The agent calls `search_docs` (`call_order` in `evals/demo/cases/t1.yaml`).
36
+ - **Tool-call budget.** The run stays within `max_tool_calls: 1`.
37
+
38
+ A passing run prints `PASS` and writes `runledger_out/demo/<run_id>/` (`summary.json`, `junit.xml`, `report.html`, `run.jsonl`). Commit the init files to run that gate on pull requests.
39
+
40
+ The same check as a GitHub Action. `suite.yaml` already points at `baselines/demo.json`, so the action compares against that baseline:
41
+
42
+ ```yaml
43
+ - id: evals
44
+ uses: runledger/Runledger@v0.2
45
+ with:
46
+ path: ./evals/demo
47
+ mode: replay
48
+ ```
49
+
50
+ This repo's `action.yml` also accepts a `baseline` input and sets `result` (`pass` or `fail`), `exit-code`, and `artifacts-path`. Those fields ship when a release containing this file is tagged. The in-repo self-test calls the action with `uses: ./`.
51
+
52
+ Page copy for runledger.io lives in `docs/site-quickstart.md`.
53
+
54
+ ---
55
+
56
+ RunLedger is a **CI harness**, not an "eval metrics framework":
57
+ - **DeepEval-style tools** help you *score* behavior.
58
+ - **RunLedger** helps you *ship safely* by making agent tests deterministic and merge-gated.
59
+
52
60
  ## Integrations (merged)
53
61
 
54
62
  - hoangsonww/Agentic-AI-Pipeline - https://github.com/hoangsonww/Agentic-AI-Pipeline/pull/24
@@ -73,7 +81,7 @@ RunLedger stops regressions by shifting from "vibes-based" evaluation to determi
73
81
 
74
82
  - **Record & replay:** record tool outputs once; replay them in CI for instant, stable tests.
75
83
  - **Strict contracts:** enforce tool schemas, calling order, and allowlists.
76
- - **Budget gating:** fail PRs automatically if wall time, tool-call count, or tool errors exceed defined limits.
84
+ - **Budget gating:** fail the run when tool-call count exceeds `max_tool_calls`. Wall time and tool-error caps are separate gates, configured with `max_wall_ms` and `max_tool_errors`.
77
85
 
78
86
  ### RunLedger vs evaluation frameworks
79
87
 
@@ -352,18 +360,18 @@ jobs:
352
360
  - uses: actions/checkout@v4
353
361
 
354
362
  - name: Run deterministic evals (replay)
363
+ id: evals
355
364
  uses: runledger/Runledger@v0.2
356
365
  with:
357
366
  path: ./evals/demo
358
367
  mode: replay
359
368
 
360
- - name: Upload eval artifacts
361
- uses: actions/upload-artifact@v4
362
- with:
363
- name: agent-eval-artifacts
364
- path: runledger_out/**
369
+ - name: Show the action result
370
+ run: echo "result=${{ steps.evals.outputs.result }} exit=${{ steps.evals.outputs.exit-code }}"
365
371
  ```
366
372
 
373
+ `runledger init` writes `.github/workflows/runledger.yml`, which installs the CLI and runs the suite with `--baseline`. The action above is the Marketplace entry in `action.yml`. It uploads `runledger_out/**` itself. On a release that contains this `action.yml`, the step also sets `result`, `exit-code`, and `artifacts-path`, and you can pass `baseline:` to override `suite.yaml`.
374
+
367
375
  ---
368
376
 
369
377
  ## Determinism guide (rules of the road)
@@ -386,6 +394,7 @@ jobs:
386
394
 
387
395
  ## Docs
388
396
 
397
+ - `docs/site-quickstart.md` -- five-minute copy for runledger.io
389
398
  - `docs/quickstart.md` -- install + first run
390
399
  - `docs/assertions.md` -- assertions, tool contracts, budgets
391
400
  - `docs/baselines.md` -- baselines, diffing, promotion
@@ -398,7 +407,6 @@ jobs:
398
407
  ## Roadmap
399
408
 
400
409
  * `init` templates for Python (OpenAI SDK), LangGraph/LangChain, and Node/TS
401
- * richer budgets (tokens/cost) via optional `task_metrics`
402
410
  * PR comments bot for regression summaries
403
411
  * plugin system for custom assertions
404
412
  * HTML report trace viewer improvements
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "runledger"
7
- version = "0.2.0"
7
+ version = "0.2.2"
8
8
  description = "CI for tool-using agents: deterministic eval suites with record/replay, hard assertions, budgets, and PR regression gates."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -34,6 +34,12 @@ dependencies = [
34
34
  "eval_type_backport>=0.2.0; python_version < \"3.10\"",
35
35
  ]
36
36
 
37
+ [project.urls]
38
+ Homepage = "https://runledger.io"
39
+ Repository = "https://github.com/runledger/Runledger"
40
+ Documentation = "https://github.com/runledger/Runledger/tree/main/docs"
41
+ Changelog = "https://github.com/runledger/Runledger/blob/main/CHANGELOG.md"
42
+
37
43
  [project.optional-dependencies]
38
44
  dev = [
39
45
  "pytest>=7.0.0",
@@ -1,3 +1,3 @@
1
1
  __all__ = ["__version__"]
2
2
 
3
- __version__ = "0.2.0"
3
+ __version__ = "0.2.2"