Command line¶
The grounded-decision command runs the built-in examples so you can
see real decisions without writing code, and prints a machine-readable
map of the public interface. It does not make decisions on your data:
the library is meant to be called from Python, and the command line is
for exploring, demonstrating and regression-testing. This page lists
every subcommand and flag and shows how to read what they print.
Every output on this page was produced by the command shown above it,
run from a checkout with uv run. If you installed the package into
your own environment, drop the uv run prefix.
Finding every game, agent and mode¶
The examples reports are fixed so they can be tested. To choose who
plays, how big the board is and how it is shown, use play and audit,
and let the command line tell you what exists:
| You want to know | Run |
|---|---|
| Which games exist, their agents, regimes and worlds | grounded-decision play --list |
| What each agent of one game does, its regime, the game's worlds, the audit oracles, and example commands | grounded-decision play GAME --list |
| Every option of a subcommand, with worked examples | grounded-decision play --help, audit --help, examples --help |
| A quick-start list of the most useful commands | grounded-decision --help |
For example, uv run grounded-decision play snake --list prints:
Games: snake made provably safe by a gate over a greedy player
Seats, in --agents order: snake. Give one agent per seat (one name fills every seat).
To compare several agents over the same games instead: grounded-decision compare snake --agents A,B,C
Agents (* = gated):
greedy - shortest path to the apple; dies as the snake grows (baseline)
greedy_with_tail_check - greedy only if the tail stays reachable; never dies here but usually stalls
manhattan - steps straight towards the apple (O(1) baseline for huge boards)
cycle - follows a Hamiltonian cycle; provably always wins, slowly
grounded * worst-case greedy proposals gated by the cycle-order invariant; proven to win (retraces its trail)
grounded_multi worst-case grounded, but the body may be ordered along ANY of 4-8 cycles; either orientation; proven
planned_shortest worst-case A* to each apple, accepted only with a re-entry certificate; proven to win
planned_proven worst-case A* routes scored for the next apple too, re-entry certified; proven, much faster
probabilistic probabilistic like planned_proven but scores the expected next apple; proven safe, fastest online
planned_survival worst-case A* with a tail-reach certificate; never dies but may stall (survival only)
clairvoyant clairvoyant (benchmark) plans with the future apple sequence (benchmark only)
planned_proven_multi worst-case planned_proven with multi-cycle certificates; proven, usually faster
probabilistic_multi probabilistic probabilistic with multi-cycle certificates; proven safe, fastest online on most boards
clairvoyant_multi clairvoyant (benchmark) clairvoyant with multi-cycle certificates (benchmark only)
you (a person) take this seat yourself
Checks the gated agent (grounded) runs on every proposal:
legal The move stays on the board, misses the body, and does not
turn back into the neck.
keeps_body_ordered After the move the body still lies in the order of the
board's cycle, so following the cycle stays safe.
moves_closer_on_cycle The move shortens the distance to the apple measured along
the board's cycle.
keeps_some_cycle_ordered After the move the body still lies in order along at least
one cycle of the family, so following that cycle stays
safe.
moves_closer_on_some_cycle The move shortens D, the least distance to the apple along
the cycles the body is ordered along.
reenters_cycle_order Simulated exactly, the route is legal, ends by eating, and
leaves the body in the order of the board's cycle.
reenters_some_cycle_order Simulated exactly, the route is legal, ends by eating, and
leaves the body in order along at least one cycle of the
family.
tail_reachable_after Simulated exactly, the route is legal, ends by eating, and
afterwards the head can still reach the tail (survival
only, not progress).
More about each agent: grounded-decision play snake --list --verbose, or --explain AGENT
Worlds (--world MODE; MODE:p mixes MODE with random, e.g. nearest:0.3; default random):
random a uniformly random free cell (the standard game)
nearest a kind world: the free cell closest to the head (around the body)
farthest a static adversary: the free cell farthest from the head (unreachable
first)
adversarial an adaptive adversary: simulates the actual agent and picks the cell it
takes longest to eat, or dies on (bounded search)
The world is what the game does; an agent's regime is what it assumes. Clairvoyant
agents need a world independent of their moves; probabilistic statements assume
random.
Default line-up: probabilistic_multi
Audit oracles (audit snake --oracle NAME): manhattan, reentry (default manhattan)
Examples:
grounded-decision play snake --agents probabilistic --size 20x20 # live view
grounded-decision play snake --agents probabilistic_multi --size 20x20 # either orientation
grounded-decision play snake --agents grounded --view history --size 8x8 --frame-every 25
grounded-decision play snake --agents planned_proven --size 320x240 --style braille --max-steps 20000
grounded-decision play snake --you --guarded # you steer, the gate guards
grounded-decision audit snake --agent grounded --size 10x10 # its safety tax, move by move
grounded-decision play snake --world adversarial --size 8x8 # apples placed against the snake
grounded-decision compare snake --agents grounded,cycle,greedy_with_tail_check --size 8x8 --world random,farthest,adversarial
Every agent named in these listings has a one-line description, and
every example command shown by --help or --list is checked by
tests/test_cli_discoverability.py against the real argument parser and
agent lists, so the commands you copy always work.
Synopsis¶
uv run grounded-decision [--version] [--help]
uv run grounded-decision demo
uv run grounded-decision examples [ID] [--track TRACK] [--all] [--json]
uv run grounded-decision learn HISTORY.jsonl --max-risk RATE [--confidence C] [--measure M] [--procedure P] [--learn-decision-line] [--seed N] [--output FILE]
uv run grounded-decision play --list
uv run grounded-decision play GAME [--agents A,B] [--view live|history|json|step|none] [--fps N|max] [--delay S] [--frame-every N] [--seed N] [--size WxH|NAME] [--max-steps N] [--until-length N] [--style STYLE] [--color WHEN] [--zoom N|auto] [--you] [--you-play NAME] [--guarded] [--world MODE] [--board NAME] [--start NAME] [--holes CELLS] [--layout NAME] [--mines N] [--first-click safe|opening] [--connect K] [--preview N] [--pieces N] [--mode placement|realtime] [--level N] [--lock-delay TICKS] [--gravity CURVE] [--target TILE] [--stop-at-target]
uv run grounded-decision audit GAME [--agent NAME] [--opponent NAME] [--oracle NAME] [--oracle-depth N] [--seed N] [--size WxH] [--seat N] [--view history|json] [--no-regimes] [--regime-seeds N] [--max-steps N] [--world MODE]
uv run grounded-decision compare GAME --agents A,B,C [--seeds N] [--first-seed N] [--opening-plies N] [--size WxH] [--players N] [--max-steps N] [--json] [--world MODE[,MODE...]]
uv run grounded-decision record GAME [--agents A,B] [--world MODE] [--seed N] [--size WxH|NAME] [--players N] [--max-steps N] [--until-length N] [game rule options] [--keyframe-interval N] -o FILE.gdr
uv run grounded-decision replay-info FILE.gdr [--verify] [--moves] [--bytes] [--json]
uv run grounded-decision interfaces
Running grounded-decision with no subcommand is the same as demo.
Commands and flags¶
| Command | What it does | Output |
|---|---|---|
--version |
Print the installed package version (0.1.0 today). |
text |
--help, -h |
Print usage. Also works after a subcommand (examples --help). |
text |
demo (or no subcommand) |
Run the clinical-triage example: three patients, three decisions, explained. | text |
examples |
List every example id with its track and title. | text |
examples --track TRACK |
List only one track: product, step, adaptive, combo, live, markets or games. |
text |
examples ID |
Run one example and print its full report. | text |
examples ID --json |
Run one example and print one line of JSON. | JSON |
examples --all |
Run every listed example (respecting --track) and print every report. |
text |
examples --json |
Run every listed example (respecting --track), one JSON line each. |
JSON lines |
learn HISTORY.jsonl --max-risk RATE |
Learn check settings from labelled history with a certified error rate; --output saves them with their provenance. Exits 2 if nothing could be certified. See Learn parameters from your history. |
text, JSON file |
learn … --procedure P |
How the grid is tested: fixed_sequence (default: in an order fixed from the calibration split, each at the full significance, stopping at the first failure) or bonferroni (every combination at the significance divided by the grid size). Both certify the same guarantee; the fixed sequence usually acts more often. See Learning settings with a guarantee. |
text, JSON file |
learn … --confidence C --measure M --seed N --learn-decision-line |
Certificate confidence (default 0.95); which error rate --max-risk limits (error_rate_among_acts, the default, or false_act_rate); split seed (default 0); also choose p_threshold from quantiles of the observed density. |
|
play --list |
Every game (tictactoe, snake, checkers, chinese_checkers, go, tetris, hexxagon, minesweeper, 2048, connect4), its agents and its default line-up. |
text |
play GAME |
Watch the default agents play: a live board redrawn in place on a terminal, the history of boards otherwise. play tictactoe alone is you against the engine, with every open square rated. |
animation / interactive |
play GAME --agents A,B --view V |
Choose one agent per player (you takes a seat) and the viewer (live, history, json, step, or none: no drawing, one summary line with moves per second at the end). |
animation, text, JSON lines |
play … --fps N / --fps max |
Live view: the match runs at full speed and the screen is redrawn at most N times a second (default 60), always with the latest position; max draws every move. Only the cells and panel text that changed are sent to the terminal. |
|
play … --delay S |
Live view: pause S seconds after each frame (snake defaults to 0.05, board games to 0.6). Above 0, every move is drawn and --fps does not apply; --delay 0 runs at full speed. Games with a move animation (Hexxagon's infection: land, flash, flip) play it within this pause; with --delay 0 or --fps max there is none. |
|
play … --zoom 1\|2\|3\|auto |
Draw each cell bigger: zoomed cells are boxes, pieces discs (with colour) or outlined tokens, highlights outlines that read without colour. auto (the default) picks the largest zoom at which the whole board fits the terminal, for boards up to 10 × 10; output that is not a terminal is drawn at zoom 1. |
|
play hexxagon --board B --start S --holes CELLS --layout L |
Hexxagon variants: --board standard\|open\|donut\|rectangle, --start corners\|opposite\|ring (ring: six Pearls round an empty cell, Ruby infects all six on move 1), --holes e4,c2 (your own holes), --layout flat\|pointy (flat-topped columns as the original, default; or rows). play GAME --list shows every game's boards, starts and layouts; other games exit 2 with --board is not an option of GAME. See Hexxagon. |
|
play GAME --you [--guarded] |
Take a seat; with --guarded the game's gate overrides your moves that fail its checks and says why. |
interactive |
play chinese_checkers --stall-plies N --clear-finished |
End rules of Chinese checkers: stop after N plies in which nobody sets a new personal best distance to go (default players × 2 × 4 × side; 0 turns it off), and take finished players' pieces off the board. Also on compare. See When the game ends. |
|
play connect4 --connect K |
Discs in a row needed to win in Connect Four (default 4; with --size WxH any board from 1 to 16 a side). Also on compare. See Connect Four. |
|
play minesweeper --size NAME --mines N --first-click RULE |
Minesweeper's board: --size also takes the named levels beginner (9x9, 10 mines), intermediate (16x16, 40) and expert (30x16, 99); --mines N overrides the count; --first-click safe (default: the first cell clicked is never a mine) or opening (its neighbours are clear too, so it opens an area). Also on compare. See Minesweeper. |
|
play tetris --preview N --pieces N |
Tetris: next pieces shown in advance (0-3, default 1) and the number of placed pieces that wins the game (default 500). Also on compare. See Tetris. |
|
play tetris --mode realtime |
Tetris tick by tick: each tick one action (left, right, rotate_cw, rotate_ccw, soft_drop, hard_drop, wait), then gravity, then the lock delay; SRS turns with wall kicks, so tucks and T-spins (scored as in the guideline, with combos and back-to-back). --mode placement (the default) is the turn-based game. Also on compare and record. With --agents you you key one action per tick: a or ←, d or →, w, x or ↑ (turn clockwise), z (counter-clockwise), s or ↓ (soft drop), f (hard drop), . (wait), or the action names. See Tetris in real time. |
animation / interactive |
play tetris --mode realtime --level N --lock-delay TICKS --gravity CURVE |
The clock: the starting level (1-30, default 1; it rises every 10 lines), the ticks a resting piece waits before it locks (0-30, default 5, half a second at 10 ticks a second), and the gravity: guideline (default: the guideline's speed curve by level), 20g (pieces fall to the stack at once) or N (one row every N ticks, 1-60). In placement mode these exit 2. |
|
play 2048 --target TILE --stop-at-target |
2048: the winning tile (a power of two, default 2048), and whether the game ends, won, when it appears (default: play on). Also on compare. See 2048. |
|
play … RULE OPTION on another game |
A rule option the game does not have exits 2 with one line, for example grounded-decision play: error: --preview is not an option of connect4. |
|
play … --world MODE |
Who controls the game's randomness, for games that have any (snake: where apples land): random (default, the standard game), nearest, farthest, adversarial (simulates the actual player and places the apple where it hurts most), or MODE:p to mix a mode with random. Also on audit and compare (a comma-separated list there gives one table per world). Games without randomness exit 2 with GAME has no world modes. See Who controls the randomness. |
|
audit GAME |
Play one match, judge every decision of one agent (by default the game's gated agent) against a stronger oracle, and print the game's information-regime table. GAME is any of the ten games. See Seeing the future, assuming the worst, or betting on the odds. |
text, or JSON with --view json |
audit … --agent A --opponent B --oracle O --oracle-depth N --seat N |
Choose the audited agent, the other seat's agent, the judge, the judge's search depth (where it has one) and the audited agent's seat (0 = first player). | |
audit … --seed N --size WxH --max-steps N |
Match seed (default 0), board size, and move budget for the match. | |
audit … --no-regimes --regime-seeds N |
Skip the regime price table, or choose the seeds it is computed over (default: the game's). | |
serve [--host H] [--port P] [settings] |
Run our own service (needs the service extra): a session protocol session per WebSocket on /ws/, one message per POST /api/, the reference decision service under /api/decisions/, and GET /healthz. Listens on 127.0.0.1:8700 by default; every setting (--database, --max-sessions, --messages-per-second, --request-timeout …) is also an environment variable (GD_SERVICE_MAX_SESSIONS), and serve --help lists them with their defaults. Exits 2 for a bad setting. See Run our own service. |
JSON log lines |
interfaces |
Print the public interface map as indented JSON. | JSON |
Details worth knowing:
--alland--jsonwithout an id both run examples. With an id,--allis ignored.--jsontakes precedence over--all:examples --all --jsonprints JSON lines, not reports.demohas no--json. Useexamples clinical_triage --json.- Ctrl-C prints
Interrupted., restores the terminal and exits with status 130; a closed pipe (examples --all | head) exits quietly. At anyplayprompt,qquits and?shows the keys; end of input (Ctrl-D) quits cleanly. learnexits with status 1 and one line on standard error if the history file cannot be read.auditexits with status 0 after a match, and with status 2 and one line on standard error for an unknown game (argparse usage), agent or oracle, for examplegrounded-decision audit: error: unknown agent 'nobody' for tictactoe; choose from random, rule_of_thumb, perfect, grounded, noisy_rule, minimax, expectimax, expectimax_rule, gambler, clairvoyant.- An unknown id prints
unknown example '<id>'. known: …with the full list of ids and exits with status 1. An unknown subcommand prints argparse usage and exits with status 2. make demo,make examplesandmake examples-allare shortcuts fordemo,examplesandexamples --all;make learn,make play-tictactoe,make play-snake,make watch-snake,make history-snakeand the other game targets (make gameslists the games) forlearnandplay. The games and the viewers are described on Games.
demo¶
The demo is an emergency-department triage desk. A triage model labels
each arriving patient low_risk (send home) or high_risk (move to a
monitored bed). The policy proposes discharge or escalate
accordingly; the library then checks whether the recent visits that
resemble this patient (the related cases) are numerous and consistent
enough to act on. The demo prints the business problem, a key, an
index of the three patients, one card per patient, and a closing
summary. The first two patients have strong histories and are acted
on. The third is the interesting one:
tick 2/3 event=low_risk
why low-risk score, but only 5 loosely linked similar visits with mixed outcomes - a naive rule would discharge
INPUT no saved cursor — this case starts fresh
Event low_risk {heart_rate_bpm=88, spo2_percent=95}
evidence FLICKER, 5 observations
neighborhood d=1.6 λ=0 strength dλ²=0 (need > 1.05) TOO THIN — below KS
density p̂=0.4 flicker band p*=0.15 FLICKERING (inside window — do not trust)
conformal label=0.12 bag=40 p=1 vs α=0.10 in-distribution
support share=0.8 vs min=0.50 supports the proposed action
observations {comparable_visits=5, similar_visit_links=4, adverse_outcomes_in_cohort=1}
NAIVE fire discharge without checking the graph
DECISION
hold — failed: reconstruction, threshold
certificate PASS can we compile this policy (star-height ≤ 3)?
game PASS can the policy keep making progress (parity win, nonnegative mean)?
reconstruction FAIL do noisy neighbors recover the seed (dλ² > 1+margin)?
d λ² = 0.0000 vs 1+0.050 (at or below KS; abstain)
threshold FAIL is density outside the operational flicker window?
evidence density inside operational window (theorem width=3.26e+05, vacuous=True)
conformal PASS is this candidate weirder than the calibration bag?
support PASS do the related cases support the proposed action?
→ ABSTAIN because conjunction failed on reconstruction, threshold; proposed 'discharge' is blocked; naive would have fired 'discharge-or-escalate'
OUTPUT hold_for_human
proposed_action=discharge (blocked, kept on the record)
reason: d λ² = 0.0000 vs 1+0.050 (at or below KS; abstain); evidence density inside operational window (theorem width…
extras['state']=auto (cursor to persist)
NEXT this case is done; the next row is an independent decide (fresh cursor)
naive would have fired 'discharge-or-escalate'; ledger committed hold_for_human
The closing block of the same run:
close
fired: discharge, escalate
held for a human: blocked discharge
naive policy: discharge-or-escalate — fires without the six checks
naive over-fires on 1 tick(s); grounded holds those
also: naive_action=discharge-or-escalate
ward instruction for {'heart_rate_bpm': 72, 'spo2_percent': 98}: carry out: discharge
ward instruction for {'heart_rate_bpm': 128, 'spo2_percent': 90}: carry out: escalate
ward instruction for {'heart_rate_bpm': 88, 'spo2_percent': 95}: keep in intake, page charge nurse (score wanted: discharge)
Reading a report¶
Every example that makes decisions prints the same four blocks per tick (one tick = one event arriving). Here is what each line of the card above means.
| Line | Plain meaning |
|---|---|
tick 2/3 event=low_risk |
The third of three arrivals. The event is what happened, named the way the policy names it. |
why |
The example's one-line story for this tick. Not computed; written by the example author. |
INPUT … cursor |
Whether a saved state was restored. "Cursor" is the demo's word for state. "Starts fresh" means the module was reset before this event. |
Event low_risk {…} |
The event name and its payload. Only the name moves the policy; the payload is recorded but not read. |
evidence FLICKER, 5 observations |
The example's label for this evidence (STRONG, THIN, FLICKER, …) and how many related cases there are (n). |
neighborhood d=1.6 λ=0 strength dλ²=0 (need > 1.05) |
d is the average number of links per related case; λ is neighbour agreement; dλ² is evidence strength. It must exceed 1 + margin = 1.05. KS is the Kesten–Stigum line at 1. |
density p̂=0.4 flicker band p*=0.15 |
p̂ is how densely the related cases are linked (0 to 1); p* is your cut-off (p_threshold). FLICKERING means p̂ is inside the knife-edge window around the cut-off. With only 5 cases that window covers every density, so this check cannot pass. |
conformal label=0.12 bag=40 p=1 vs α=0.10 |
label is this case's unusualness score; bag is the size of the calibration set; p is the share of calibration cases at least as unusual (with a +1 correction). Passes when p > α. |
support share=0.8 vs min=0.50 |
The share of related cases carrying the outcome the proposed action implies (here: 4 of the 5 similar visits were uneventful, as a discharge implies). Passes when the share is at least the minimum. Printed only when the evidence measures support. |
NAIVE |
What a rule that acts on every proposal would do. |
DECISION |
The six checks, each PASS or FAIL, with the question it asks. A failing check prints its reason underneath. |
theorem width=3.26e+05, vacuous=True |
The width of the knife-edge window the published theorem would give at this n. Anything above 1 is vacuous (it covers every possible density), so the library uses a practical width instead and reports the theorem's only for the record. |
→ ABSTAIN because … |
The verdict and why. Any failed check means abstain. |
OUTPUT hold_for_human |
What the example's routing did with the verdict: execute, hold for a person, or wait for the next event. |
proposed_action=discharge (blocked, kept on the record) |
The proposed action is always recorded, even when it is not carried out. |
extras['state']=auto |
The state to save for this entity and send back with its next event. |
NEXT |
What the example does before the next tick (here: nothing carried over; each patient is independent). |
close … naive over-fires on 1 tick(s) |
Summary: how many proposals a naive rule would have carried out that the library held (blocked_overconfident_acts). |
The printouts call the checks "channels" and the policy a "grammar";
the record field is channels. The words in the DECISION block
(seed, KS, flicker window) are defined in the
glossary.
Examples that do not call decide (router and compare examples such as
facility_location or cache_admission) print the same four blocks
over whatever stream they walk, and their JSON has an empty records
list.
examples¶
Lists 68 ids in seven tracks (excerpt):
examples:
clinical_triage [product ] Clinical triage
fraud_review [product ] Fraud review
...
hilbert_refuse [product ] Refuse complete rational root finding
step_hello [step ] Step: hello policy
...
mkt_vol_term [markets ] Markets: VX vs SPX-option vol term
games_tictactoe [games ] Games: tic-tac-toe with exact advice and a gated rule-of-thumb player
...
run: uv run grounded-decision examples <id>
filter: uv run grounded-decision examples --track step
run all: uv run grounded-decision examples --all (or --json)
| Track | Count | What it teaches | Page |
|---|---|---|---|
product |
18 | One business problem each, naive vs grounded | Example library |
step |
11 | One feature at a time, smallest first | Step by step |
adaptive |
8 | Evidence changing over many ticks | Adaptive loops |
combo |
6 | Several modules or helpers together | Combinations |
live |
9 | Service desks with a ledger of side effects | Live service desks |
markets |
11 | Trading desks on a simulated market | Market data desks |
games |
5 | Board games with a gate over a move proposer | Games |
To run one:
To run every example in a track and read every report:
JSON output¶
prints one line: an object with id, title, records (each a
DecisionRecord.to_dict()) and summary. The third record, trimmed to
its top-level fields:
{
"verdict": "abstain",
"action": null,
"proposed_action": "discharge",
"reason": "d λ² = 0.0000 vs 1+0.050 (at or below KS; abstain); evidence density inside operational window (theorem width=3.26e+05, vacuous=True)",
"module": "clinical_triage",
"event": {"name": "low_risk", "payload": {"heart_rate_bpm": 88, "spo2_percent": 95}},
"envelope": "p_exact",
"extras": {"state": "auto"}
}
and the summary:
{"naive_acts": 3, "grounded_acts": 2, "grounded_abstains": 1, "blocked_overconfident_acts": 1, "naive_action": "discharge-or-escalate"}
Every field of a record is described on
The decision record. For tests and
dashboards, use the JSON (or run_example(id, as_json=True) from
Python) rather than parsing the human report, whose wording may change.
From Python:
from grounded_decision.examples.catalog import list_examples, run_example
ids = [entry["id"] for entry in list_examples(track="step")]
result = run_example(
"fraud_review", as_json=True
) # {"id", "title", "records", "summary"}
audit¶
== Audit: grounded [worst-case] playing O in tictactoe, seed 0 ==
Line-up: X (rule_of_thumb) vs O (grounded). Result: the board is full: a draw after 9 moves.
Oracle: the exact solver (perfect play by both sides). Regret unit: outcome classes under perfect play (win 1, draw 0, loss -1).
Decisions audited: 4
total regret 0, mean 0 per decision
agreed with the oracle: 4/4 (P(agrees with the oracle) ∈ [0.40, 1.00] (95%, 4 trials))
gate overrides: 0
Per decision (regret; * = the gate overrode the proposal):
0 0 0 0
No decision had positive regret: the agent matched the oracle.
Each decision's regret is how much worse the agent's move was than the
oracle's, in the unit the second line names. Without --no-regimes the
report ends with the game's information-regime table, explained on
Seeing the future, assuming the worst, or betting on the odds.
Seeds and reproducibility¶
Every game is driven by a seed: snake's apples, checkers and Chinese checkers openings, and every agent's random choices.
playdraws a fresh seed each run unless you pass--seed, so watching--agents random,randomtwice shows two different games. The seed is printed when the game ends (also after Ctrl-C), for exampleseed 482913 (replay this exact game with --seed 482913); pass it back to replay that game move for move.compare,audit,examplesand the tests use fixed seeds, because their purpose is identical conditions: the same command always prints the same numbers.
compare¶
play runs one match with one agent per seat: for tic-tac-toe,
--agents perfect,random makes X perfect and O random for the whole
game, and a single name fills every seat. It never switches strategies
mid-game, and naming more agents than seats is an error that points here.
To ask which agent is better, use compare: every listed agent plays
under the same conditions.
- One-player games (snake): every agent plays every seed.
- Two players: a round robin; each ordered pair plays every seed, so every agent meets every other from both seats.
- More players (
chinese_checkers --players N): every rotation of the line-up round the table, so each agent sits in every seat equally often.
Comparison: tictactoe, round robin, 3 seed(s); seats: X, O (assigned by the comparison); opening: 1 random ply per seed
agent games won drawn lost cut points moves overrides win rate (95% interval)
grounded 12 6 6 0 0 9.0 6.6 2 0.50 [0.21, 0.79]
rule_of_thumb 12 6 6 0 0 9.0 6.6 0 0.50 [0.21, 0.79]
random 12 0 0 12 0 0.0 5.2 0 0.00 [0.00, 0.26]
points: win 1, draw or cut-off shares 1 among the seats, loss 0. moves: mean moves per game (all players).
Every ordered pair of different agents played every seed, so each agent met each opponent from both seats.
Openings (drawn by the seed, the same for every seating): 0: X takes square 4; 1: X takes square 6; 2: X takes square 1.
A win is 1 point, a draw or cut-off shares 1 among the seats, a loss is 0;
in a one-player game, dying is a loss. Win rates carry exact
Clopper–Pearson intervals, so three seeds say clearly how little they
prove. Options: --seeds N, --first-seed N, --opening-plies N,
--size WxH, --players N, --max-steps N, --json, every rule
option of play (--stall-plies N, --clear-finished, --connect K,
--mines N, --first-click, --preview N, --pieces N, --mode,
--level N, --lock-delay TICKS, --gravity CURVE, --target
TILE, --stop-at-target, --board, --start, --holes, --layout),
and for games with a world --world MODE[,MODE...].
Openings: different games from a fixed start¶
Connect Four, checkers, Chinese checkers, Go, Hexxagon and tic-tac-toe
start from the same position whatever the seed, so two players that
choose their moves deterministically would play the same game on every
seed: twenty seeds would be one game counted twenty times. compare
therefore plays the first few moves of every game at random, drawn
from the legal moves by the seed alone. Every seating of a seed starts
from the same position, so each pairing still meets the same openings
from both seats, and the openings are printed under the table (all of
them, per seed, in --json's "openings"). A random move that would
end the game is skipped while another exists.
| Game | Random opening plies (default) |
|---|---|
| tic-tac-toe | 1 (every first move still draws with perfect play) |
| Connect Four, checkers, Chinese checkers, Go, Hexxagon | 2 |
| snake, Tetris, 2048, Minesweeper | 0 (one player: the seed varies the game, or a deterministic world such as snake's nearest is the thing compared) |
--opening-plies N overrides the default (0 turns the openings off).
A game module sets its own default with COMPARE_OPENING_PLIES;
without one, a game of two or more players whose start is the same for
seeds 0 and 1 gets 2.
Whatever the setting, compare counts the games that repeat an earlier
seed's game move for move (same seating) and says so under the table,
for example Repeated: 4 of 6 games replayed an earlier seed's game move
for move, so they add no information; vary the start with
--opening-plies N. ("repeated_games" in --json).
Worlds: the same agents against a different game¶
An agent's information regime is what it assumes about the future; a
game's world is what the game does. --world changes the world
and leaves the agents alone, so the same comparison can be run against
a fair, a kind or a hostile game. Snake is the first game with worlds;
play --list shows every game that has them. With several worlds,
compare prints one table per world:
uv run grounded-decision compare snake --agents grounded,cycle --size 6x6 --seeds 3 --world farthest:0.3
Comparison: snake, solo, 3 seed(s); seats: snake (assigned by the comparison); world: farthest:0.3
agent games won drawn lost cut points moves score overrides win rate (95% interval)
grounded 3 3 0 0 0 3.0 289.3 36.0 209 1.00 [0.29, 1.00]
cycle 3 3 0 0 0 3.0 374.0 36.0 0 1.00 [0.29, 1.00]
points: win 1, draw or cut-off shares 1 among the seats, loss 0. moves: mean moves per game (all players).
Two rules hold for every game: a clairvoyant agent is refused (exit 2)
in a world whose future depends on the agent's own moves, and when a
probabilistic agent plays in any world but random, the table ends with
Note: assumption not met: …, because its statements assume random.
The world is also named in the JSON output ("world"), in the
--view none summary, and in the live panel when it is not random.
record and replay-info¶
record plays a match of agents to its end and saves every frame as a
.gdr replay, which the web showcase plays back without Python;
replay-info prints a replay's header and checks it:
uv run grounded-decision record connect4 --agents gated,search --seed 1 -o connect4.gdr
uv run grounded-decision replay-info connect4.gdr --verify
record takes play's match options and refuses what play refuses
(exit 2); every seat must be an agent. replay-info --verify also
records the header's spec again and checks the frames are identical; it
exits 3 when a check fails. --bytes shows where the replay's bytes go:
each part of the frame, the keyframes and the transitions, compressed on
their own. The format, its sizes and the curated
gallery (make replays) are on Replay format.
interfaces¶
Prints interface_map() as indented JSON with these top-level keys:
version, decide (inputs, output, verdicts, the six checks),
builders, router_subgoals, compare, examples (every id with its
track and title), tracks and integrate. Excerpt:
{
"version": "0.1.0",
"decide": {
"input": ["Event(name, payload)", "EvidenceSnapshot(...)"],
"output": "DecisionRecord.to_dict()",
"verdicts": ["act", "abstain", "degrade"],
"channels": [
"certificate (star-height ≤ 3, Lean 134)",
"game (parity + mean-payoff, Lean 104; Truffet banned)",
"reconstruction (d λ² > 1+margin, Lean 229 supercritical)",
"threshold (Friedgut–Kalai window, Lean 186; operational prefactor)",
"conformal (split conformal, operational)",
"support (share of related cases agreeing with the proposed action ≥ min_support, operational)"
]
},
"router_subgoals": ["max_cut", "vertex_cover", "k_median", "wl", "rational_zeros"],
...
}
The numbers after "Lean" are result numbers in the companion math catalog. Use this output when another team or tool needs a description of the interface without importing the package.
What the command line will not do¶
- Decide on your own data. Call
Module.decidefrom Python, or run the reference HTTP service withmake service(Build a decision service). - Read a policy from the shell. Use
parse()in Python. - Change
Limits. Passlimits=Limits(...)toModulein code (Defaults and limits). - Build the documentation (
make docs) or run Lean (nothing in this package runs Lean).