Skip to content

cli: grapharc run can only set max_tokens, not the other three budget dimensions #5

Description

@Shashankss1205

Summary

grapharc run accepts only --max-tokens as a ceiling. Budget supports four dimensions — max_tokens, max_iterations, max_seconds, max_concurrency — and the other three are unreachable from this command. The code says so plainly:

# `Budget()` is genuinely unlimited on every dimension, so with no
# `--max-tokens` the budget check passes anything. An earlier comment here
# claimed the opposite; an adversarial run admitted a 200-node chain whose
# worst case was 400,000 tokens. The meter is real only when a ceiling is.
meter = BudgetMeter(Budget(max_tokens=max_tokens) if max_tokens else Budget())

Why this matters

Bounded work is one of the load-bearing promises here: max_seconds is delivered as an interrupt into a running node, not polled between them, and iterations are metered by the runtime itself. Those mechanisms exist and are tested — they are simply not wired to this command's flags. Making every ceiling reachable from the surface an operator actually types is what turns graph engineering from a design claim into something you can hold a run to.

Where in the code

  • grapharc/cli/graphrun.py — around line 157, where the meter is built
  • grapharc/cli/main.py — the run subparser, where --max-tokens is declared (add the siblings next to it)
  • grapharc/runtime/budget.pyBudget, for the exact field names and their semantics
  • grapharc/cli/plan.py — for how another command threads limits from flags into a budget

What to change

  1. Add --max-seconds, --max-iterations and --max-concurrency to the run subparser, matching the existing --max-tokens style (type, metavar, help text).
  2. Thread them into the Budget(...) construction, passing only what was supplied so an unset flag stays unlimited.
  3. Include the resolved ceilings in the --json payload alongside max_tokens, so a run's limits are recoverable from the document.
  4. Add CLI tests in the style of tests/test_cli.py asserting each flag reaches the budget.
  5. Update the README bullet that currently says --max-tokens is the only ceiling.

Check whether these belong in the grapharc.toml config layer too (grapharc/cli/config.py has a KEYS table) — if you add them there, the resolution order and the sources provenance block must keep working.

How to verify

./.venv/bin/grapharc run <graph.json> --max-seconds 5 --json | grep max_seconds
uv run pytest tests/test_cli.py -q
uv run pytest -q
uv run ruff check .

Acceptance criteria

  • All four budget dimensions are settable from grapharc run
  • An unset flag leaves that dimension unlimited (no accidental default ceiling)
  • --json reports the ceilings actually in force
  • Tests assert each flag reaches the Budget
  • README's "--max-tokens is the only ceiling" bullet is updated
  • uv run pytest green, uv run ruff check . clean

Skill level — good first issue

Mostly argparse plumbing with a clear existing example one line away, and the CLI test file shows exactly how to assert it. A good introduction to how flags, config resolution and the --json contract fit together in this repo. Comment here if you would like a pointer on the config layer part, which is optional.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions