rote-cli 0.6.0__tar.gz → 0.8.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.
- {rote_cli-0.6.0 → rote_cli-0.8.0}/PKG-INFO +26 -20
- {rote_cli-0.6.0 → rote_cli-0.8.0}/README.md +25 -19
- {rote_cli-0.6.0 → rote_cli-0.8.0}/skills/rote-graduate/references/eval-estimates.md +41 -20
- {rote_cli-0.6.0 → rote_cli-0.8.0}/src/rote/__init__.py +1 -1
- {rote_cli-0.6.0 → rote_cli-0.8.0}/src/rote/adapters/_common.py +8 -4
- {rote_cli-0.6.0 → rote_cli-0.8.0}/src/rote/cli.py +297 -10
- {rote_cli-0.6.0 → rote_cli-0.8.0}/src/rote/eval/__init__.py +4 -1
- {rote_cli-0.6.0 → rote_cli-0.8.0}/src/rote/eval/empirical.py +174 -3
- {rote_cli-0.6.0 → rote_cli-0.8.0}/src/rote/eval/estimate.py +55 -7
- {rote_cli-0.6.0 → rote_cli-0.8.0}/src/rote/eval/priors.py +86 -1
- {rote_cli-0.6.0 → rote_cli-0.8.0}/src/rote/eval/scorecard.py +3 -2
- {rote_cli-0.6.0 → rote_cli-0.8.0}/src/rote/eval/sidecar.py +30 -3
- {rote_cli-0.6.0 → rote_cli-0.8.0}/src/rote/graduator/__init__.py +84 -0
- rote_cli-0.8.0/src/rote/graduator/drivers/codex.py +285 -0
- rote_cli-0.6.0/src/rote/graduator/drivers/codex.py +0 -84
- {rote_cli-0.6.0 → rote_cli-0.8.0}/.gitignore +0 -0
- {rote_cli-0.6.0 → rote_cli-0.8.0}/LICENSE +0 -0
- {rote_cli-0.6.0 → rote_cli-0.8.0}/pyproject.toml +0 -0
- {rote_cli-0.6.0 → rote_cli-0.8.0}/skills/rote-graduate/SKILL.md +0 -0
- {rote_cli-0.6.0 → rote_cli-0.8.0}/skills/rote-graduate/references/crystallization-heuristics.md +0 -0
- {rote_cli-0.6.0 → rote_cli-0.8.0}/skills/rote-graduate/references/ir-schema.md +0 -0
- {rote_cli-0.6.0 → rote_cli-0.8.0}/skills/rote-graduate/references/llm-judge-extraction.md +0 -0
- {rote_cli-0.6.0 → rote_cli-0.8.0}/skills/rote-graduate/references/node-kinds.md +0 -0
- {rote_cli-0.6.0 → rote_cli-0.8.0}/src/rote/adapters/__init__.py +0 -0
- {rote_cli-0.6.0 → rote_cli-0.8.0}/src/rote/adapters/_py_common.py +0 -0
- {rote_cli-0.6.0 → rote_cli-0.8.0}/src/rote/adapters/_ts_common.py +0 -0
- {rote_cli-0.6.0 → rote_cli-0.8.0}/src/rote/adapters/cloudflare.py +0 -0
- {rote_cli-0.6.0 → rote_cli-0.8.0}/src/rote/adapters/dbos.py +0 -0
- {rote_cli-0.6.0 → rote_cli-0.8.0}/src/rote/adapters/dbos_ts.py +0 -0
- {rote_cli-0.6.0 → rote_cli-0.8.0}/src/rote/adapters/inngest.py +0 -0
- {rote_cli-0.6.0 → rote_cli-0.8.0}/src/rote/adapters/python.py +0 -0
- {rote_cli-0.6.0 → rote_cli-0.8.0}/src/rote/adapters/temporal.py +0 -0
- {rote_cli-0.6.0 → rote_cli-0.8.0}/src/rote/eval/pricing.py +0 -0
- {rote_cli-0.6.0 → rote_cli-0.8.0}/src/rote/eval/tokens.py +0 -0
- {rote_cli-0.6.0 → rote_cli-0.8.0}/src/rote/graduator/drivers/__init__.py +0 -0
- {rote_cli-0.6.0 → rote_cli-0.8.0}/src/rote/graduator/drivers/anthropic_api.py +0 -0
- {rote_cli-0.6.0 → rote_cli-0.8.0}/src/rote/graduator/drivers/claude.py +0 -0
- {rote_cli-0.6.0 → rote_cli-0.8.0}/src/rote/graduator/update.py +0 -0
- {rote_cli-0.6.0 → rote_cli-0.8.0}/src/rote/ir.py +0 -0
- {rote_cli-0.6.0 → rote_cli-0.8.0}/src/rote/serve/__init__.py +0 -0
- {rote_cli-0.6.0 → rote_cli-0.8.0}/src/rote/serve/backends.py +0 -0
- {rote_cli-0.6.0 → rote_cli-0.8.0}/src/rote/serve/registry.py +0 -0
- {rote_cli-0.6.0 → rote_cli-0.8.0}/src/rote/serve/server.py +0 -0
- {rote_cli-0.6.0 → rote_cli-0.8.0}/src/rote/skill_source.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rote-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.0
|
|
4
4
|
Summary: Graduate fuzzy AI skills into deterministic, reliable workflows
|
|
5
5
|
Project-URL: Homepage, https://github.com/trevhud/rote
|
|
6
6
|
Project-URL: Repository, https://github.com/trevhud/rote
|
|
@@ -326,17 +326,16 @@ subscription path.
|
|
|
326
326
|
|
|
327
327
|
## Status
|
|
328
328
|
|
|
329
|
-
`rote` is **pre-1.0**. The end-to-end flow works on the BDR example
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
`pytest tests/ -m slow
|
|
337
|
-
|
|
338
|
-
Known gaps: the
|
|
339
|
-
isn't implemented), the extracted modules are `NotImplementedError` stubs
|
|
329
|
+
`rote` is **pre-1.0**. The end-to-end flow works on the BDR example. The
|
|
330
|
+
fast suite (`pytest tests/`) makes no real API calls and is what CI runs
|
|
331
|
+
on every push, alongside a Python e2e (DBOS over SQLite + the MCP server
|
|
332
|
+
over real stdio). Each adapter also has a `slow`-marked e2e that runs its
|
|
333
|
+
emitted code against the real runtime (Temporal's time-skipping server,
|
|
334
|
+
the TypeScript targets via `tsc --noEmit` and live dev servers, the
|
|
335
|
+
plain-Python subprocess); those need a Node toolchain / Docker, so they
|
|
336
|
+
run locally with `pytest tests/ -m slow`, not in CI.
|
|
337
|
+
|
|
338
|
+
Known gaps: the extracted modules are `NotImplementedError` stubs
|
|
340
339
|
you fill in with real API-client code, a Restate adapter is planned, and
|
|
341
340
|
`fan_out` nodes currently receive the whole upstream list in one
|
|
342
341
|
invocation (per-element dispatch is a planned enhancement). Published on
|
|
@@ -357,7 +356,10 @@ rote/
|
|
|
357
356
|
│ ├── graduator/ orchestrator + drivers/ (claude · codex · anthropic_api)
|
|
358
357
|
│ └── adapters/ dbos · temporal · python · cloudflare · dbos_ts · inngest
|
|
359
358
|
│ (+ _common / _py_common / _ts_common emit helpers)
|
|
360
|
-
├── examples/
|
|
359
|
+
├── examples/
|
|
360
|
+
│ ├── bdr-outreach/ canonical: all 5 node kinds · IR baseline · run snapshots
|
|
361
|
+
│ ├── ops-report/ 100% roteness: zero LLM nodes + a HITL gate
|
|
362
|
+
│ └── deal-monitor/ data-heavy: parallel waves · fan-out judges · template render
|
|
361
363
|
└── tests/ fast + slow suites (pytest -m slow)
|
|
362
364
|
```
|
|
363
365
|
|
|
@@ -377,6 +379,12 @@ rote/
|
|
|
377
379
|
heuristics, IR schema, LLM-judge extraction)
|
|
378
380
|
- [`examples/bdr-outreach/`](examples/bdr-outreach/) — the canonical
|
|
379
381
|
skill, its ground-truth IR, and snapshotted real graduator runs
|
|
382
|
+
- [`examples/ops-report/`](examples/ops-report/) — the 100%-roteness
|
|
383
|
+
archetype: every step deterministic, one durable HITL gate, zero LLM
|
|
384
|
+
nodes after graduation
|
|
385
|
+
- [`examples/deal-monitor/`](examples/deal-monitor/) — the data-heavy
|
|
386
|
+
archetype: parallel entry waves, fan-out judges, and a template render
|
|
387
|
+
replacing per-run LLM-generated HTML
|
|
380
388
|
|
|
381
389
|
---
|
|
382
390
|
|
|
@@ -384,19 +392,17 @@ rote/
|
|
|
384
392
|
|
|
385
393
|
In rough priority order:
|
|
386
394
|
|
|
387
|
-
1.
|
|
388
|
-
spawning `codex exec`; unlocks ChatGPT subscribers.
|
|
389
|
-
2. **Re-graduate BDR end-to-end with `signature_spec`** — the bundled IR
|
|
395
|
+
1. **Re-graduate BDR end-to-end with `signature_spec`** — the bundled IR
|
|
390
396
|
was hand-extended with structured schemas; the rubric now teaches the
|
|
391
397
|
field, but no real run has produced one yet.
|
|
392
|
-
|
|
398
|
+
2. **Pre-filter as a `pure_function` node** — today hard thresholds are
|
|
393
399
|
lifted into a judge's `forward()`, which works for Temporal but not
|
|
394
400
|
Cloudflare; a separate node makes the short-circuit uniform.
|
|
395
|
-
|
|
401
|
+
3. **More example skills** — BDR is one shape; research-heavy,
|
|
396
402
|
retrieval-heavy, and code-review skills stress the IR differently.
|
|
397
|
-
|
|
403
|
+
4. **`fan_out` per-element dispatch** — currently the whole upstream list
|
|
398
404
|
arrives in one invocation.
|
|
399
|
-
|
|
405
|
+
5. **The graduator graduating itself** — `rote-graduate` is a SKILL.md;
|
|
400
406
|
pointing `rote graduate` at it should crystallize its rubric-grade
|
|
401
407
|
pieces and leave only the genuinely fuzzy judgments in the loop.
|
|
402
408
|
|
|
@@ -280,17 +280,16 @@ subscription path.
|
|
|
280
280
|
|
|
281
281
|
## Status
|
|
282
282
|
|
|
283
|
-
`rote` is **pre-1.0**. The end-to-end flow works on the BDR example
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
`pytest tests/ -m slow
|
|
291
|
-
|
|
292
|
-
Known gaps: the
|
|
293
|
-
isn't implemented), the extracted modules are `NotImplementedError` stubs
|
|
283
|
+
`rote` is **pre-1.0**. The end-to-end flow works on the BDR example. The
|
|
284
|
+
fast suite (`pytest tests/`) makes no real API calls and is what CI runs
|
|
285
|
+
on every push, alongside a Python e2e (DBOS over SQLite + the MCP server
|
|
286
|
+
over real stdio). Each adapter also has a `slow`-marked e2e that runs its
|
|
287
|
+
emitted code against the real runtime (Temporal's time-skipping server,
|
|
288
|
+
the TypeScript targets via `tsc --noEmit` and live dev servers, the
|
|
289
|
+
plain-Python subprocess); those need a Node toolchain / Docker, so they
|
|
290
|
+
run locally with `pytest tests/ -m slow`, not in CI.
|
|
291
|
+
|
|
292
|
+
Known gaps: the extracted modules are `NotImplementedError` stubs
|
|
294
293
|
you fill in with real API-client code, a Restate adapter is planned, and
|
|
295
294
|
`fan_out` nodes currently receive the whole upstream list in one
|
|
296
295
|
invocation (per-element dispatch is a planned enhancement). Published on
|
|
@@ -311,7 +310,10 @@ rote/
|
|
|
311
310
|
│ ├── graduator/ orchestrator + drivers/ (claude · codex · anthropic_api)
|
|
312
311
|
│ └── adapters/ dbos · temporal · python · cloudflare · dbos_ts · inngest
|
|
313
312
|
│ (+ _common / _py_common / _ts_common emit helpers)
|
|
314
|
-
├── examples/
|
|
313
|
+
├── examples/
|
|
314
|
+
│ ├── bdr-outreach/ canonical: all 5 node kinds · IR baseline · run snapshots
|
|
315
|
+
│ ├── ops-report/ 100% roteness: zero LLM nodes + a HITL gate
|
|
316
|
+
│ └── deal-monitor/ data-heavy: parallel waves · fan-out judges · template render
|
|
315
317
|
└── tests/ fast + slow suites (pytest -m slow)
|
|
316
318
|
```
|
|
317
319
|
|
|
@@ -331,6 +333,12 @@ rote/
|
|
|
331
333
|
heuristics, IR schema, LLM-judge extraction)
|
|
332
334
|
- [`examples/bdr-outreach/`](examples/bdr-outreach/) — the canonical
|
|
333
335
|
skill, its ground-truth IR, and snapshotted real graduator runs
|
|
336
|
+
- [`examples/ops-report/`](examples/ops-report/) — the 100%-roteness
|
|
337
|
+
archetype: every step deterministic, one durable HITL gate, zero LLM
|
|
338
|
+
nodes after graduation
|
|
339
|
+
- [`examples/deal-monitor/`](examples/deal-monitor/) — the data-heavy
|
|
340
|
+
archetype: parallel entry waves, fan-out judges, and a template render
|
|
341
|
+
replacing per-run LLM-generated HTML
|
|
334
342
|
|
|
335
343
|
---
|
|
336
344
|
|
|
@@ -338,19 +346,17 @@ rote/
|
|
|
338
346
|
|
|
339
347
|
In rough priority order:
|
|
340
348
|
|
|
341
|
-
1.
|
|
342
|
-
spawning `codex exec`; unlocks ChatGPT subscribers.
|
|
343
|
-
2. **Re-graduate BDR end-to-end with `signature_spec`** — the bundled IR
|
|
349
|
+
1. **Re-graduate BDR end-to-end with `signature_spec`** — the bundled IR
|
|
344
350
|
was hand-extended with structured schemas; the rubric now teaches the
|
|
345
351
|
field, but no real run has produced one yet.
|
|
346
|
-
|
|
352
|
+
2. **Pre-filter as a `pure_function` node** — today hard thresholds are
|
|
347
353
|
lifted into a judge's `forward()`, which works for Temporal but not
|
|
348
354
|
Cloudflare; a separate node makes the short-circuit uniform.
|
|
349
|
-
|
|
355
|
+
3. **More example skills** — BDR is one shape; research-heavy,
|
|
350
356
|
retrieval-heavy, and code-review skills stress the IR differently.
|
|
351
|
-
|
|
357
|
+
4. **`fan_out` per-element dispatch** — currently the whole upstream list
|
|
352
358
|
arrives in one invocation.
|
|
353
|
-
|
|
359
|
+
5. **The graduator graduating itself** — `rote-graduate` is a SKILL.md;
|
|
354
360
|
pointing `rote graduate` at it should crystallize its rubric-grade
|
|
355
361
|
pieces and leave only the genuinely fuzzy judgments in the loop.
|
|
356
362
|
|
|
@@ -25,6 +25,13 @@ Ground rules:
|
|
|
25
25
|
(agents batch parallel calls). If it says "repeat until you have 25
|
|
26
26
|
qualified contacts", estimate the realistic iteration count from any
|
|
27
27
|
hints (quota sizes, batch sizes, typical yields), not the worst case.
|
|
28
|
+
- **Steps that repeat per item MUST declare `iterations`.** A "process
|
|
29
|
+
each row" step costs its per-row turns *times the row count* — this
|
|
30
|
+
is almost always the dominant term, and flattening it understates the
|
|
31
|
+
whole run by 5–20×. Put the per-iteration turns in `estimated_turns`
|
|
32
|
+
and the realistic item-count range in `iterations` (page sizes,
|
|
33
|
+
pagination labels, batch quotas, and filter windows in the skill text
|
|
34
|
+
are your evidence). The loader multiplies them; never pre-multiply.
|
|
28
35
|
- **Include the overhead the prose hides.** Reading reference files,
|
|
29
36
|
re-checking rubric sections, correcting malformed tool calls — a
|
|
30
37
|
realistic agent spends turns on these. A step whose happy path is 2
|
|
@@ -54,9 +61,14 @@ steps:
|
|
|
54
61
|
phase: "1"
|
|
55
62
|
estimated_turns: {low: 1, high: 2}
|
|
56
63
|
estimated_tool_calls: {low: 4, high: 4}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
64
|
+
- description: "Push each eligible invoice and capture its sent date"
|
|
65
|
+
node_id: process_invoices_loop
|
|
66
|
+
phase: "Processing"
|
|
67
|
+
estimated_turns: {low: 3, high: 6} # PER ROW —
|
|
68
|
+
iterations: {low: 20, high: 90} # — × realistic row count
|
|
69
|
+
totals: # optional — omit if the sum is right;
|
|
70
|
+
low: 88 # must be WHOLE-RUN (post-iteration)
|
|
71
|
+
high: 602 # when any step declares iterations
|
|
60
72
|
notes: >-
|
|
61
73
|
Lead generation dominates: the loop re-queries ZoomInfo with adjusted
|
|
62
74
|
filters until the quota is met; typical campaigns converge in 3-5
|
|
@@ -72,30 +84,39 @@ Field reference:
|
|
|
72
84
|
| `steps[].description` | yes | The step, in the skill's own vocabulary |
|
|
73
85
|
| `steps[].node_id` | no | IR node id, only when the mapping is clean 1:1 |
|
|
74
86
|
| `steps[].phase` | no | Source skill phase, same convention as the IR |
|
|
75
|
-
| `steps[].estimated_turns` | yes | `{low, high}` agent turns |
|
|
87
|
+
| `steps[].estimated_turns` | yes | `{low, high}` agent turns (per iteration when `iterations` is set) |
|
|
76
88
|
| `steps[].estimated_tool_calls` | no | `{low, high}` tool calls, when distinct from turns |
|
|
77
|
-
| `
|
|
89
|
+
| `steps[].iterations` | when the step repeats | `{low, high}` repeats per run (rows, pages, items); whole-run cost = turns × iterations |
|
|
90
|
+
| `totals` | no | Whole-run `{low, high}`; omit to mean "sum the steps (× iterations)" |
|
|
78
91
|
| `notes` | no | The one paragraph a reader needs to trust the numbers |
|
|
79
92
|
|
|
80
93
|
Validated by `rote.eval.sidecar.EvalEstimates` — if you can run Python,
|
|
81
94
|
`load_eval_estimates("eval.yaml")` is the dry check, same pattern as
|
|
82
95
|
`load_pipeline`.
|
|
83
96
|
|
|
84
|
-
## Calibration anchors (
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
-
|
|
90
|
-
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
## Calibration anchors (measured production runs)
|
|
98
|
+
|
|
99
|
+
Whole-run turn counts are regime-dependent — anchor to the skill's
|
|
100
|
+
*shape*, not to a universal range:
|
|
101
|
+
|
|
102
|
+
- **Sequential tool-heavy skills** (BDR-scale: 7 phases, ~20 distinct
|
|
103
|
+
steps, no per-item loop): **30–57 turns** measured. ~13 seconds per
|
|
104
|
+
turn including tool execution.
|
|
105
|
+
- **Per-item loop skills** (browser automation over a table, per-record
|
|
106
|
+
processing): measured production runs landed at **184 and 730 turns**
|
|
107
|
+
— the loop multiplier dominates everything else in the file. If a
|
|
108
|
+
skill says "for each row…", expect hundreds of turns, not tens, and
|
|
109
|
+
express it via `iterations`, never by inflating per-step turns.
|
|
110
|
+
- Per-step anchors: a single fixed API call step: 1–2 turns. A
|
|
111
|
+
batch-and-review step: 2–4. A bounded search loop: 6–15. A genuinely
|
|
112
|
+
open research step: 4–10. One iteration of a per-row browser cycle
|
|
113
|
+
(locate, act, confirm, refresh): 2–6.
|
|
114
|
+
|
|
115
|
+
If your estimate lands wildly outside the anchor for the skill's shape,
|
|
116
|
+
re-examine before writing — either the skill really is bigger/smaller
|
|
117
|
+
(fine, say so in `notes`) or a step estimate is off. A per-item skill
|
|
118
|
+
whose whole-run total sums to under ~100 turns almost certainly has a
|
|
119
|
+
missing `iterations` block.
|
|
99
120
|
|
|
100
121
|
## What NOT to do
|
|
101
122
|
|
|
@@ -223,13 +223,17 @@ def _pipeline_hash(pipeline: Pipeline) -> str:
|
|
|
223
223
|
# Hash the full validated contents: node wiring, inputs, retries, and
|
|
224
224
|
# edges all participate, so any regeneration that changes behavior gets
|
|
225
225
|
# a new workflow type — name/version/counts alone miss rewires.
|
|
226
|
-
# Provenance
|
|
227
|
-
#
|
|
228
|
-
#
|
|
226
|
+
# Provenance is excluded — it's tooling metadata, and annotating where
|
|
227
|
+
# a pipeline came from must not re-version in-flight workflows whose
|
|
228
|
+
# behavior didn't change. That covers ``Node.source`` (which SKILL.md
|
|
229
|
+
# section produced a node) and ``source_skill`` (where the skill bundle
|
|
230
|
+
# lived): the latter is a filesystem path the graduator re-points per
|
|
231
|
+
# output location, so hashing it would mint a new workflow type on
|
|
232
|
+
# every re-graduation to a different directory.
|
|
229
233
|
payload = pipeline.model_dump_json(
|
|
230
234
|
by_alias=True,
|
|
231
235
|
exclude_none=True,
|
|
232
|
-
exclude={"nodes": {"__all__": {"source"}}},
|
|
236
|
+
exclude={"source_skill": True, "nodes": {"__all__": {"source"}}},
|
|
233
237
|
)
|
|
234
238
|
return hashlib.sha256(payload.encode()).hexdigest()[:8]
|
|
235
239
|
|