state.json is the state of record and changes only through the engine’s verbs; PROJECT.md is rendered from it. verify-state is the mechanical check that nothing wrote to state.json behind the engine’s back. It is read-only: it never modifies state.json or PROJECT.md.
New as a slash command in 0.50.0. The verb existed before, but had no command doc, so it was reachable only by calling the engine directly.
${CLAUDE_PLUGIN_ROOT} is empty:
What it compares
Every render records a stamp (.conductor/render-stamp.json) holding the record’s revision and state.json’s mtime at that moment, and every engine save adds its own lastSave (revision and mtime) to the same stamp — including the saves of verbs that do not re-render, such as a claim or set-activity-log. A hand-edit advances neither. The check compares the file against the engine’s LAST recorded write, whichever of the two is later.
On exit 1, run
/pm:status to re-render, review the diff of state.json, and reconcile before trusting PROJECT.md again. Never “fix” a finding by hand-editing the file back.
Before 0.50.0 it compared only
state.json’s mtime to the last render, so any verb that saves without re-rendering (a claim, set-activity-log, platform recording) made it exit 1 claiming an undetected hand-edit. A stamp written by an older pm has no lastSave, so the first check after upgrading may report “cannot rule out a hand-edit” until the next save or /pm:status.What it cannot see
- A hand-edit followed by an engine save before
verify-stateruns: the save stamps the edited file as its own, so from then on it reads as the engine’s. - A hand-edit within the filesystem’s mtime resolution of the last engine save, at the same revision.
- A merge, rebase or checkout that brings in
state.jsonANDrender-stamp.jsontogether from another clone: the pair is internally consistent, so it reads as that clone’s engine writes. One that brings instate.jsonalone is caught (its revision or mtime no longer matches the stamp).

