← ClaudeAtlas

state-machinelisted

State-machine discipline for TypeScript lifecycle, workflow, reducer, and state-machine files — make illegal states unrepresentable, keep transitions pure and exhaustive, and design for replay and concurrency.
g-bastianelli/nuthouse · ★ 1 · AI & Automation · score 65
Install: claude install-skill g-bastianelli/nuthouse
# subroutine — state-machine discipline Apply this to lifecycle transitions. The nearest `AGENTS.md` and event contracts define the vocabulary. ## Model states and events, not boolean combinations - Give each state variant only valid fields; avoid booleans plus optionals. - Model events separately and match with `.exhaustive()` so additions fail compilation until handled. - Return a typed error for an illegal transition; never throw it or silently retain the old state. ```ts type JobState = | { status: "idle" } | { status: "running"; runId: string; startedAt: Date } | { status: "failed"; runId: string; reason: string }; type JobEvent = | { type: "START"; runId: string; at: Date } | { type: "FAIL"; runId: string; reason: string }; function transition(state: JobState, event: JobEvent): Result<JobState, TransitionError> { return match(event) .with({ type: "START" }, ({ runId, at }) => state.status === "idle" ? ok<JobState>({ status: "running", runId, startedAt: at }) : err<TransitionError>({ code: "INVALID_TRANSITION", from: state.status, event: "START" }), ) .with({ type: "FAIL" }, ({ runId, reason }) => state.status === "running" && state.runId === runId ? ok<JobState>({ status: "failed", runId, reason }) : err<TransitionError>({ code: "INVALID_TRANSITION", from: state.status, event: "FAIL" }), ) .exhaustive(); } ``` ## Keep transitions deterministic - Keep transitions pure: no I/O, clock,