Skip to main content

Deterministic conduct verdicts for live tabletop sessions — CI for running a game. Findings cite the table charter; ambiguity produces silence, never accusations.

Project description

dmcheck

Deterministic conduct verdicts for live tabletop sessions — CI for running a game.

Feed it a session transcript (and optionally an engine event ledger) plus a table charter, and it returns named findings — the player whose question was never answered, the dice roll nobody acknowledged, the turn that began without anyone being told, the spoiler that leaked into the channel, the five-minute dead air. Every finding cites the charter rule it violates, with the evidence attached.

Cold-boot probe (2026-07-24): a fresh agent session given only this repo URL installed and refereed a session in 2 commands, verified all three exit-code legs against the docs, and confirmed the no-false-accusation contract held (a consumed roll produced silence). Its friction notes shipped as 0.1.1 (--dice-bot, dmcheck charter).

The design contract: a false accusation is the unforgivable bug. A rule fires only when the transcript provably shows the violation — ambiguity produces silence, never noise. The verdict path is model-free and deterministic: same transcript, same findings, every time.

30 seconds to a refereed session

$ pip install dmcheck          # stdlib only, no dependencies
$ dmcheck run session.jsonl --gm "Greta"
{
 "messages": 9,
 "findings": [
  {"rule": "R2", "summary": "unconsumed-roll: a dice result was never followed by any GM message",
   "charter": "roll_ack_within_messages=4",
   "detail": "dice result from DiceBot never followed by a GM message",
   "evidence": {"index": 6, "author": "DiceBot", "content": "Bram rolls 1d20+4: [18] = 22"}},
  ...
 ],
 "counts": {"R1": 1, "R2": 1, "R6": 1, "R7": 1, "R8": 1}
}

Transcript formats: JSONL of {ts, author, content}, or a JSON array of Discord-API-shaped messages ({timestamp, author: {username}, content}) in either order.

The rule set (each one paid for by a real table failure)

Rule Fires when Origin story
R1 a player's question got no GM response within threshold a player asked the DM a lore question; another player ended up answering
R2 a dice result was never followed by any GM message "did I hit?" — a player's successful attack roll sat unacknowledged
R3 an engine event was never narrated to the table the state engine resolved a hit the table never heard about
R4 a turn began and the GM never addressed the actor by name "isn't it her turn?" — asked by a player, which is one player too many
R5 someone acted out of initiative (needs the ledger) engine rejected it silently; the table never knew
R6 a configured hidden term appeared in a GM message a module's secret state names leaked into narration
R7 GM dead air beyond threshold while a player waited 30 seconds reads as thinking; five minutes reads as absence
R8 the session ended with open R1–R3 findings in its tail sessions should end in a defined state — that's what makes the next one possible

These came from running a hybrid table — human and AI players, an AI GM — on Discord, where every one of these failures actually happened and got codified the same week. They apply equally to human GMs: run dmcheck over your own exported game log and see what your table's transcript says.

The charter is config, not code

charters/default.json ships thresholds and conventions derived from a real table's protocol. Override any of it — cue conventions, dead-air tolerance, dice-bot names, hidden-term lists — and version it. A league or organized-play program could publish a charter the way they publish a player's guide; dmcheck then referees any table against it.

$ dmcheck run session.jsonl --charter our-table.json --ledger events.jsonl
$ dmcheck rules            # the rule set with definitions
$ dmcheck charter          # print the effective charter — copy, edit, version it
$ dmcheck run session.jsonl --gm "Rob" --dice-bot "RollBot"   # quick overrides, no file needed
$ dmcheck --schema         # machine-readable I/O contract

For agents

  • tool.json at the repo root; --schema; exit codes: 0 clean · 1 findings · 2 charter/input unusable.
  • MCP server: dmcheck-mcp (stdio) with tools run and rules.
  • Findings are structured JSON with rule id, charter citation, human-readable detail, and an evidence span — built to be consumed by a GM agent that fixes its own procedure between beats.

What it does NOT do (on purpose)

  • No rules adjudication — whether the attack was legal is srdcheck's job.
  • No character math — that's charactercheck. (srdcheck judges the rules, charactercheck derives the actor, dmcheck referees the table.)
  • No narrative-quality judging — whether the prose was good is taste, and taste is not checkable. dmcheck checks procedure only.
  • No model calls, no scores — deterministic findings per rule, never a blended "DM grade."

Credits

The rule set was distilled from live hybrid (human + AI) table sessions; the Router+Detector pattern in native-gaming-harness independently converged on the same idea, which we take as evidence it's the load-bearing piece. dmcheck is game-system-agnostic and unaffiliated with any publisher.

mcp-name: io.github.chaoz23/dmcheck

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dmcheck-0.1.1.tar.gz (13.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dmcheck-0.1.1-py3-none-any.whl (12.4 kB view details)

Uploaded Python 3

File details

Details for the file dmcheck-0.1.1.tar.gz.

File metadata

  • Download URL: dmcheck-0.1.1.tar.gz
  • Upload date:
  • Size: 13.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.5

File hashes

Hashes for dmcheck-0.1.1.tar.gz
Algorithm Hash digest
SHA256 b7c49067a02dfb4655ae602a04f2b8fd29b4178db252bc6f89c63f0fbf544bab
MD5 139ff3c9fe0964e2296b77a3eb801b89
BLAKE2b-256 a42916048f9162a8d2a67841ae7709b56a67f3d5ec6d7cf0f3a4ae7dba7f991e

See more details on using hashes here.

File details

Details for the file dmcheck-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: dmcheck-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 12.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.5

File hashes

Hashes for dmcheck-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 3581899b7890b6636e9acc5bc3ef0f5cf5af1b23762a166cbdc8fe55177c135c
MD5 8a28e59a9ee957646285d1911a778a3d
BLAKE2b-256 7fef05b80a1975fa5f6e6a0ee9758f40ba2124c7b1c66330bbf2cb9a45d29c57

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page