Spaces:
Running
Running
A newer version of the Gradio SDK is available: 6.19.0
AGENTS.md β Tabras
Engineering conventions for any agent or contributor working in this repo. Read alongside README.md (the design spec). README says what to build; this says how to write it.
Non-negotiables
Tests accompany all code
- No code lands without tests. A feature and its tests are one unit of work, written together β not "tests later."
- The deterministic core (
primitives.py,budget.py,game.py) is pure logic with no model calls β it is fully testable and MUST be fully tested. This is where bugs hide and where balance lives. - Model-dependent code (
generator.py,boss.py) is tested by mocking the model: assert the tool-call schema, the deck-context wiring, and that engine numbers (not model output) set magnitudes. Never test against live model output.
Coverage is the bloat metric
- Track code coverage on every change. Treat uncovered lines as bloat: if coverage is 50%, half the code is untested weight that should either be tested or deleted.
- Target high coverage on the deterministic core specifically β it's pure and has no excuse to be uncovered.
- Coverage is a deletion signal, not just a test signal: uncovered code is a prompt to ask "is this needed at all?"
Functions do one thing
- One function, one responsibility. If a function does two things, it's two functions.
- As simple as possible, complex only where the problem genuinely requires it. Reach for complexity reluctantly and only when the domain demands it.
- A function you can't describe in one line (see comments) is doing too much β split it.
Terse, readable code
- Terseness in service of readability, never against it. Shorter is better only when it reads more clearly.
- No cleverness that costs a reader a second look. Obvious beats impressive.
- Delete aggressively. The best code is no code; the second best is code that's plainly necessary.
Comments: one line, at the function line
- One-line comment at the function definition stating what it does. That's the default.
- No block comments narrating internals, no inline play-by-play. If the body needs explaining, the function is too complex β simplify it instead of annotating it.
- Comments state what/why at the boundary, never how line-by-line (the code is the how).
In practice
- The one-line function comment and the "describe in one line" rule are the same rule: if you can't write the comment, the function isn't doing one thing.
- Coverage + terseness + one-thing functions reinforce each other: small single-purpose functions are trivial to test, which drives coverage, which exposes bloat to delete.
- When in doubt: smaller function, clearer name, a test, delete the rest.
What this looks like
# Convert a card's energy cost into its point budget.
def budget_for(cost: int) -> int:
return cost
Single purpose, one-line comment at the definition, terse, testable. A companion test asserts the mapping. No internal commentary.
Order of work (per the README build order)
Each step ships with its tests before the next begins:
primitives.py β budget.py β generator.py + game.py β playtest β boss.py β draft.py β art β fine-tune.
Do not move to the next file until the current one is tested and covered.