# Plan Assist

> Set up and maintain a three-tier project-documentation system (charter.md + work-plan.md + log.md) that keeps a project's intent from drifting across sessions. The journal is a write-ahead log for project intent; a cheap periodic "heartbeat" catches drift early. Use when the user says "set up project docs", "plan docs", "start a new project", "plan-assist", "session handoff", "wrap up this session", "before I move/reset the repo", or "project heartbeat". Invoke explicitly or when these phrases surface.

- Skill: `benjsmith/plan-assist` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add benjsmith/plan-assist`
- Raw SKILL.md: https://api.skillmd.com/api/skills/benjsmith/plan-assist/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Docs & Writing
- Author: benjsmith (https://skillmd.com/u/benjsmith)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/benjsmith/plan-assist

---


# plan-assist — layered planning docs

Three root docs. **charter.md** = stable directives (DO/DO NOT, invariants,
build-order status table, gotchas). **work-plan.md** = current plan + handoff.
**log.md** = append-only journal, canonical. Goal: prevent drift.

## INVARIANTS (never break)
- **I1.** If charter.md and log.md disagree → **log.md wins**. charter.md only distills it.
- **I2.** log.md is **append-only**: never edit/delete old entries; newest at bottom; absolute dates only (resolve "today" to the real date).
- **I3.** log.md is a **write-ahead log**: append AND commit a dated entry BEFORE any risky op, not after — so a destructive op can't lose it. (A session once lost its tree on a `mv`; the journal was the only recovery.)

## SESSION CONTRACT — do each, in order
1. **START:** read charter.md → work-plan.md → log.md (skim recent). Always, even if the prompt seems narrow.
2. **ON CHANGE:** edit work-plan.md in the SAME commit as the code change — never let it lag.
3. **BEFORE RISKY OP** (`mv` workdir · `git reset --hard` · force-push · big migration): commit a dated log.md entry FIRST (per I3).
4. **PHASE LANDS:** summarize it into log.md, prune it from work-plan.md (keep < ~250 lines).
5. **STOP MID-TASK:** write a SESSION HANDOFF block atop work-plan.md (shape below).
6. **SESSION END:** append a dated log.md entry (decided/changed · new gotchas · status changes · open questions).
7. **EACH COMMIT + BOUNDARY:** run the HEARTBEAT.

Keep live status OUT of charter.md (it lives in work-plan.md); the build-order table is the only exception.

### SESSION HANDOFF shape (atop work-plan.md)
```markdown
## ⏸ SESSION HANDOFF — <YYYY-MM-DD>
**Done + verified:** <what shipped, with commit hashes>
**Left to do:** <next concrete steps, in order>
**How to run / diagnose:** <build / test / smoke commands>
**Environment notes:** <traps, env vars, anything non-obvious>
```
Remove it once the next session picks the work back up.

## HEARTBEAT (cheap; one line — "in sync, on-phase" — unless something fires)
drift? · stale build-order marker in charter.md (⏳ but shipped / ✅ but broken)? ·
journal debt → append to log.md now? · work-plan.md > 250 lines → prune? ·
periodically run build/tests/smoke? · stale open questions in log.md?
Full text + hook snippets: `hooks/heartbeat.md`. Only stop to act when a check fires.

## BOOTSTRAP (only if the docs are absent)
**Never clobber** — if a target exists, read it and offer to merge, don't overwrite. Use today's date for `<YYYY-MM-DD>`.
1. Infer the project name; skim the code for a first-pass DO/DO-NOT list and build-order skeleton (placeholders if nothing's discoverable).
2. Create charter.md, work-plan.md, log.md from `templates/` with `<project-name>` filled in.
3. Add the `templates/CLAUDE-orientation.md` block to CLAUDE.md (create if absent; don't duplicate if present).
4. Seed log.md with a `## Session 1 work log — <today>` baseline entry.
5. Offer the heartbeat hook — default skill-baked (no config); install the `hooks/heartbeat.md` snippet only if the user wants harness enforcement.
6. *(Opt-in)* offer to add the read-only allowlist below to `.claude/settings.local.json` so session-start/heartbeat inspection stops prompting. Only with the user's OK. **Never allowlist risky ops** (`git reset --hard`, `mv`, force-push, migrations) — keeping them prompt-gated is the safety guardrail this skill is built around.

```json
{ "permissions": { "allow": [
  "Bash(git status:*)", "Bash(git log:*)", "Bash(git diff:*)",
  "Bash(git show:*)", "Bash(wc -l:*)", "Bash(date:*)"
] } }
```

