agent-doc-discipline
Writing-time discipline for documents agents consume (the five surfaces, specs, tickets, .omc/skills/) — every rule checkable and…
Check a TLA+ model of a system that moves between states, such as a product flow or a protocol, and draw it as a Mermaid statechart. The report gives the shortest path to each state that breaks a rule. Use for /statechart.
Claude Code
$ npx -y skills add Yeachan-Heo/oh-my-claudecode --skill statechart --agent claude-code
Codex
$ npx skills add Yeachan-Heo/oh-my-claudecode --skill statechart -a codex -y
Cursor
$ npx skills add Yeachan-Heo/oh-my-claudecode --skill statechart -a cursor -y
Gemini CLI
$ npx skills add Yeachan-Heo/oh-my-claudecode --skill statechart -a gemini-cli -y
GitHub Copilot
$ npx skills add Yeachan-Heo/oh-my-claudecode --skill statechart -a github-copilot -y
OpenCode
$ npx skills add Yeachan-Heo/oh-my-claudecode --skill statechart -a opencode -y
Windsurf
$ npx skills add Yeachan-Heo/oh-my-claudecode --skill statechart -a windsurf -y
name: statechart
description: "Check a TLA+ model of a system that moves between states, such as a product flow or a protocol, and draw it as a Mermaid statechart. The report gives the shortest path to each state that breaks a rule. Use for /statechart."
aliases: []
metadata:
credits:
statechart: pstack
author: Lauren Tan
url: "https://github.com/cursor/plugins/tree/main/pstack"
port: pstack-claude
port-author: Michael Denyer
port-url: "https://github.com/michael-denyer/pstack-claude"The chart shows how a system moves between states, in the words of the person who reads it. That person, the reader, decides whether the behavior is right.
Work in a scratch folder outside the repo. Write a TLA+ spec and its config. Then run:
<skill dir>/scripts/statechart SPEC.tla [--config FILE] [--view FILE] [--out DIR]
`scripts/statechart.ts` is TypeScript, so run it with a runtime that can execute TypeScript.
The first run installs TLC and Java with mise and needs the network.
You do the work that needs judgment: the words on each state and arrow, the phases and their colors, the title, and the report to the reader. Put your work in a view module, and give it with `--view`.
To show the reader's words, the view exports `state(vars)`. The value that `state()` returns picks the form:
Label each state with what the reader can see or cares about, such as "Paying" or "Lease held, write pending". Keep variable names out of labels. In `vars`, a TLA+ sequence is an object with keys from 1, so `v.pc[1]` is `pc[1]`. A set is an array.
The view can also export `step(action, from, to)`. It gets the TLC action name and the values before and after the step, and it returns the label of the arrow. Write each step label as the user sees it happen, such as "you press play" or "the connect fails". Do not name the code or the TLA+ action. Two actions that end the same in the chart get the same label, so that they share one arrow.
When a step can occur only in some conditions, end its label with the condition in brackets, in the reader's words, such as `you press play [while the file loads]`. In a regions chart, the command writes the condition on the other regions on the arrow, in the words of their labels, such as `[when Offline]`. Your brackets replace it, and two arrows from one state can then look the same. So in a regions chart, do not write brackets for a condition on another region. When a value that no label shows decides where a step goes, name the result in the label, such as "the roster read fails".
The view can also export these:
The command calls `state()` and `group()` at most once for each model state, and `step()` at most once for each step. The chart and the report both use those answers. So make each function depend only on its arguments.
The chart does not draw a step that stays in one label. Split a label when the reader must see such a step.
Aim for about 20 arrows or fewer, because a busier chart is hard to read. First return coarser labels from `state()`. Give one label to values that act the same, and leave out a detail that the reader does not need, such as a call in flight whose return changes nothing. Keep each state of a bug path, and keep each mark. When a merge changes a `breaks` state to `mayBreak`, it hides where a rule breaks. Do not merge two states that break different rules, because the reader then cannot see which rule breaks where. If the chart is still too busy, return `null` from `step()` for the steps that the reader does not need, such as a reset that every state has, or a step whose arrow repeats what other arrows show. Obey these rules when you hide steps:
For Codex users: Check out oh-my-codex — the same orchestration experience for OpenAI Codex CLI. Liked OmC but found it a bit overkill? Try gajae-code.
Writing-time discipline for documents agents consume (the five surfaces, specs, tickets, .omc/skills/) — every rule checkable and…
Clean AI-generated code slop with a regression-safe, deletion-first workflow and optional reviewer-only mode
Settle types and module shape before cross-boundary code — competing designs explored in parallel, compared on API surface and…
Periodic architecture survey — walks the module graph and reports ranked deepening candidates (shallow modules, hypothetical…
Run N parallel candidates at one brief and synthesize: rubric-first framing, isolated fan-out, a cross-judge on a different…
Shipyard's navigator — chart a foggy effort (destination unclear, questions not yet stateable) into a map of decision tickets on…
Use your assigned AgentMail inbox to read email tasks, explicitly send or reply, and check delivery. Provided automatically by…
Create a new Architecture Decision Record with sequential numbering and AgentDB registration