.conductor/state.json. Every epic, every detour stack frame, every link, every tracker configuration — it’s all in that one JSON file. PROJECT.md is a generated view rendered from it and should never be hand-edited. Understanding what each file is for — and what the rules around touching them are — prevents the class of state corruption that’s hardest to debug: a file that looks valid but disagrees with the real state.
The .conductor/ directory
Three files live here. Each has a distinct purpose and a distinct write policy./pm:init and managed entirely by the PM engine after that. Only state.json is the authoritative source; the other two are logs and should never be edited directly.
state.json structure
The top-level fields of.conductor/state.json and what they mean:
A minimal real example of a
claude-code-lane epic with inline stories:
PROJECT.md
PROJECT.md is a generated Markdown view that renders the full conductor briefing. It is re-rendered by conductor.mjs render after every state change. Never edit it by hand — state.json always wins, and the next render will overwrite any manual changes.
The briefing shows:
- Active epic — title, lane icon, priority, and current status.
- Detour stack — each frame with its paused epic, reason, and spawned detour.
- NEXT UP queue — highest-priority
queuedepics, P0→P3, skipping any epic starved on an unresolveddepends-onlink (with the blocker named explicitly). - Per-lane counts — how many epics are in each lane, by status.
- Tracker sync line — any active-work epics missing
externalIdwhen a tracker is configured. Only honestly-computable drift is shown; PM never fabricates transition state it can’t see. - Hierarchy rollup — for parent epics, an
X/Y children archivedprogress indicator.
SessionStart hook re-injects the briefing via additionalContext every time a session opens or resumes after a compaction — this is how PM survives context loss without requiring you to re-read docs.
detours.log
.conductor/detours.log is an append-only trail of all detour events. One entry per line:
log-detour subcommand. Substantial pushes and pops are logged automatically. The PostToolUse hook also auto-detects unlogged minimal detours from the commit’s shape — file count, commit prefix, whether an epic is active at all, and whether an active detour is already open — and logs them without requiring a manual /pm:detour --minimal invocation.
Two corrections shipped in 0.32.0. The hook used to log a spurious minimal detour for a perfectly ordinary commit when no epic was active — there is no work to detour from in that case, so nothing is logged now. And the detection reads the repository rather than the command text, so a commit in any flag form is seen and a command that merely mentions
git commit is not.In 0.33.0 the trail stopped duplicating itself. A commit-derived row is refused when the trail already holds one for that
(sha, kind) — which mattered because the fallback rung has no memory of what it already logged. A MINIMAL detour is deliberately exempt: it records what the agent declared, not what git observed, so two of them at one commit are two real events. A - sha means “cannot tell” and is never treated as an identity.That duplication was half of why PROJECT.md was never clean — a bookkeeping commit appended a row, which changed the file, which produced another commit. The other half was a bookkeeping filter that guarded one branch of the hook and had never been applied to the identical branch beside it.CLAUDE.md rules block
PM writes and maintains a managed rules block in the project’sCLAUDE.md. This is how the conductor discipline — the detour protocols, the reconcile gate, the tracker sync instructions, the lane workflow rules — becomes part of every Claude Code session automatically, without you re-reading documentation.
The rules block is:
- Written by
/pm:initwhen a project is first set up. - Re-injected by the
SessionStarthook viaadditionalContexton every session open, resume, and compaction recovery, so the rules survive context loss. - Refreshable via
/pm:upgradeafter a plugin update — run it to pull in any new rules or behavioral changes from the latest version. - Idempotent — deleting the block from
CLAUDE.mdand re-running/pm:initor/pm:upgraderestores it safely. To permanently opt out, delete the block and do not run upgrade.

