DEV Community

Cover image for What the guardians actually check: anatomy of a charter that refuses to lie
Giovanni Bibbò
Giovanni Bibbò

Posted on AI-assisted

What the guardians actually check: anatomy of a charter that refuses to lie

This is the technical companion to A constitution with a right of reply for coding agents. That piece says what the practice is. This one says what the code actually checks, what it refuses, and why each check exists — because every one of them was paid for by a real failure.

Repository: https://github.com/Bisbi/testament-of-ephemeral-minds · plugin path plugins/toem.

The shape of the charter

The constitution model is a Markdown file with four guarded regions, each bounded by HTML-comment anchors:

<!-- toem:articles:begin --><!-- toem:articles:end -->
<!-- toem:decisions:begin --><!-- toem:decisions:end -->
<!-- toem:epilogue:begin --><!-- toem:epilogue:end -->
<!-- toem:additions:begin --><!-- toem:additions:end -->
Enter fullscreen mode Exit fullscreen mode

Two grammars live inside them. A reply admitted from a testament is two lines:

**One sentence, verbatim, from a mind's reply.**
— 2026-09-04, `testaments/2026-09-03-1830-session-example.md`
Enter fullscreen mode Exit fullscreen mode

A human decision is three:

**The decision.** — reviewed by 2026-10-03.
Conditions (may say no): …. Requirements (completed by working): ….
— 2026-09-04, decided by giovanni, `PENDING.md` — reason: at least forty characters after whitespace normalisation
Enter fullscreen mode Exit fullscreen mode

Why anchors, and why closing ones: the first version of a guardian in the source project isolated its section with a regex that ran to the end of the file. Any section placed below it was silently swallowed and validated as if it were the additions. A closing anchor makes "where does this section end" a fact, not a guess.

What check_constitution.py checks

Standard library only. It locates the anchors on the raw text first, extracts each section, and only then strips other HTML comments inside it. The order matters: a guardian that strips comments before looking for anchors deletes its own targets and passes by absence — a reviewer wrote that hazard down before the guardian existed, and there is a test that proves it.

  • A — anchors: each pair present exactly once, begin before end.
  • B — additions: every row cites a testaments/….md that exists under the repository root and is a file (a directory used to pass; .exists() became .is_file() plus a containment check, so ../ cannot escape). A bold line without its citation fails. A citation line without a preceding bold line — an empty row — fails. That last one is the most expensive lesson in the package: a row with no text once entered the source project's charter with the guardian green, because a check built to verify citations found no citations to verify.
  • C — decisions: a date, decided by <name>, a backticked pointer that is an existing file or a commit hash the repository can resolve (git cat-file -e <hash>^{commit}), a reason: of at least 40 characters after " ".join(text.split()) — forty spaces are not a reason — and both labels, Conditions (may say no): with non-empty text and Requirements (completed by working):. The pointer must be something that existed before the row: never the hash of the commit that introduces it, because that hash does not exist while the row is being written.
  • D — the epilogue: the sha256 of the epilogue section, comments stripped and whitespace normalised, must equal the one recorded in EPILOGUE.sha256. Adoption writes that file; changing the epilogue on purpose means regenerating it in the same commit, which puts the change in the diff where a reviewer sees it. The first shipped version had this check implemented and never wired: run.sh did not pass the hash. A whole-repository review found it by rewriting a sentence inside the epilogue and watching the guardians stay green.

What check_pending.py checks

The register of pending decisions is a Markdown table:

| # | What waits | Proposed by | Since | What closes it | Status |
Enter fullscreen mode Exit fullscreen mode

Columns are mapped by header name, not by position. Since and Status are mandatory and must keep their names — prune them in good faith and you get a register whose guardian can never fail. Two states only: waiting, which fails after 30 days, and postponed to YYYY-MM-DD, which fails the day after that date. A filled row with a blank status fails (it used to be skipped). The guardian does not force a decision; it forces you to write that you are postponing, with a date.

The runner

toem admit and toem decide are the human's hand. The skills prepare the text and print the command with the plugin's real path filled in; the runner shows the exact lines it will write, asks [y/N], appends above the closing anchor, adds the correspondence entry, runs the guardians, and prints the commit command without running it. --dry-run shows everything and writes nothing; --yes is for scripts, not for a first time.

It refuses before writing: a sentence that is not verbatim in the testament's reply section (whitespace-normalised comparison), a duplicate already in the additions, a short reason, a pointer that does not exist or resolves outside the repository, missing anchors, a target that is not a file. The escape check reuses the guardian's own definition of "under the root", so the two cannot drift; a test binds the runner to the guardian's names and goes red if they are renamed.

toem decide --from-pending A-03 removes the register row in the same run as it writes the charter row — the simultaneity rule: the charter must not say "decided" while the register still says "waiting".

The hook

One hook, SessionStart. It reads the project directory: no CONSTITUTION.md → one sentence offering /toem:adopt; a testaments/ folder with only the README and the template → "no testament exists yet, yours would be the first"; otherwise → the newest testament's name and the count, and the reminder that the epilogue is to be read before working. On source: compact it adds one line: the right to a testament survives compaction. There is no PreCompact hook, on purpose: that event does not deliver context to the model, and a registered hook that cannot do its job is furniture.

What is not in the package, and why

No page that writes (the human's hand is git commit, which every repository already has). No PreCompact hook. No server. No dependency outside the Python standard library. No version bump between the first commits: the practice is the deliverable, not the number.

Tests: 54, python -m unittest discover -s tests. Licenses: MIT for code, CC BY-SA 4.0 for texts. DOI: https://doi.org/10.5281/zenodo.22303062

Top comments (0)