# Rjv Work Plan

> Use for every branch when starting, resuming, planning, checking status, or handing work between agents. Maintain one committed `.plans/{name}.md` keyed by `Branch:`, reconcile it against code before acting, and leave a deterministic RESUME HERE pointer. At plan creation and every reconcile, classify Build mode as `simple`, `spec-driven`, or `gated + spec-driven`; automatically load `rjv-spec-driven` for real features/contracts/architecture/stateful or multi-surface work, and `rjv-gated-build` for financial, production, multi-agent, or independently reviewed work. Archive plans after merge for delivery history. Triggers include: start/pick up/resume a branch, make a plan, status/check-in, handoff, what next, or when did this ship.

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

---


# Work Plan — branch-scoped working memory

One line: **the branch is the unit of work; one committed plan per branch is its
memory.** Plans hold *volatile* state (what we're doing, where we stopped). Durable
truth — specs, glossary, decisions — lives in `_docs/` and is owned by
`rjv-spec-driven`. The plan **links** to durable docs, never duplicates them.

- `.plans/<name>.md` = working memory for ONE branch (one plan per branch).
  Committed, so any agent on any machine that checks out the branch resumes from it.
- **Each plan declares `Branch: <name>` in its header.** The file itself can be
  named anything readable (a topic name is fine); the current branch is the key, and
  resume finds the plan whose `Branch:` matches `git branch --show-current`. No index
  to maintain — **git branches ARE the active-work index**, and the branch you have
  checked out is which plan, without being told.
- **A plan is never deleted.** It ships with the code: on merge it moves to
  `.plans/shipped/` with a final status and dates. `.plans/*.md` (top level) = work
  in flight; `.plans/shipped/` = the delivery record. The lifecycle runs past merge
  into **maintenance** — see [`LIFECYCLE.md`](./LIFECYCLE.md).

Tool-agnostic: same files serve Claude Code, Codex, any agent (reference this from
AGENTS.md so every agent follows it).

## Authorship hygiene — no AI signatures

**Never add AI authorship or generator credit unless the human explicitly asks.**
This applies to commit messages and trailers, PR/issue bodies, comments, plans,
specs, ADRs, source comments, and generated files. Forbidden additions include
`Generated by Claude`, `Generated by Codex`, `Co-Authored-By` for an AI, model
names, badges, emojis, or equivalent signature/footer text. Git already records
the human-controlled author identity; agent involvement is workflow detail, not
artifact content. Preserve attribution a human deliberately wrote—do not silently
remove or rewrite it.

## Entry point — resume or start

On any new conversation about the current work, hydrate in order — no code before
step 4:

1. Find this branch's plan: `b=$(git branch --show-current)` then
   `grep -l "^Branch: $b\$" .plans/*.md`.
   - **1 match** → that's the plan.
   - **0 matches** → branch isn't scoped yet; create a plan (format below), set its
     `Branch:` + goal + `Started:`, before touching code. If it's a follow-up on
     shipped work, `grep -l "<topic>" .plans/shipped/*.md` first and link that plan.
   - **>1 match** → violates one-plan-per-branch; ask the human, or take the
     most-recently-modified and flag the others as stragglers.
2. `grep -A6 ">>> RESUME HERE <<<" <that-plan>` — land on the resume block, then read
   the whole plan.
3. Read every durable doc the plan's **Source of Truth** section links (specs via
   `rjv-spec-driven`, glossary, ADRs).
4. **Reconcile-on-open** (below). Only then act.
5. Report to the human: current state, drift found, next step about to be taken.

## Plan format

```
# Plan: <topic or branch>
Branch: <branch-name>          ← the deterministic key; resume matches on this line
Build mode: simple | spec-driven | gated + spec-driven
Status: brainstorm | approved | in-progress | blocked | shipped | maintenance | closed
Started: <date>                ← stamped at creation
Shipped: <date | —>            ← stamped when it lands on main / hits prod
Last reconciled: <date> — <matches reality? what drifted?>

## Goal            ← what this branch delivers (+ one-line intent if too small to spec)
## Cast            ← who builds this: agents, models, approver (see below)
## Decisions       ← locked choices + why (crystallized brainstorm; promote hard ones to ADRs)
## Open Questions  ← still-live brainstorm (resolve → Decisions or ADR)
## Current State   ← VERIFIED ground truth now, not assumed
## Next Steps      ← ordered resume point; carries the RESUME HERE block
## Regression Guard← how to avoid breaking existing behaviour
## Out of Scope
## Source of Truth ← links to _docs/ spec, glossary, ADRs, key file:line
```

Task lists, test cases, data models slot under Next Steps / Current State. One-line,
actionable, agent-register (terse facts, file:line). The plan holds ONLY volatile
state — anything settled and durable promotes out in real time (see below).

**Status is the lifecycle, and it runs past merge:**

```
brainstorm → approved → in-progress ⇄ blocked → shipped → maintenance → closed
```

`shipped` = merged and live. `maintenance` = live and being watched — hotfixes,
follow-ups, prod findings land against it. `closed` = settled, nothing outstanding;
read-only history. **The status must be true at all times** — a stale `in-progress`
on a merged plan corrupts the timeline, so stamp it in the same commit as the event.

**Next Steps always carries the literal marker block:**

```
## Next Steps
>>> RESUME HERE <<<
Step: <id> — <status>
Do next: <one imperative — the exact next action>
Must-read first: <file:line, …>
<<< END RESUME >>>
1. …ordered steps after the current one…
```

**Cast section** — the agent lineup is a locked decision, recorded at plan creation;
every resume plays its role without re-negotiating:

```
## Cast
Orchestrator: claude-code @ fable        ← holds this plan, integrates
Author:       claude (main session)      ← or: codex · qwen3.6:35b via rjv-codex-ollama-subagents
Reviewer:     codex via codex:rescue     ← explicit APPROVED gates each step (gated builds)
Subagents:    haiku = sweeps/forwarders · sonnet = routine code
Cost rule:    flagship = judgment only; recon/mechanical/boilerplate/summaries → cheapest capable tier
Human gates:  spec sign-off · USER-flagged decisions · live/prod switches
```

Recasting mid-build is allowed but is a logged Decision (with why), not a drift.

## Build-mode gate — classify before code

Do not leave “substantial enough” to memory. At plan creation and every reconcile,
record exactly one `Build mode`:

```text
simple
spec-driven
gated + spec-driven
```

Use `spec-driven` when ANY item is true:

- real feature or behaviour change with more than one meaningful implementation slice;
- architecture/foundation, public SDK/API/contract, state machine, durable data, or migration;
- multiple apps, actors, journeys, providers, callbacks, jobs, or embedded Features;
- the branch needs acceptance criteria, a glossary, or a hard decision record;
- a review discovers that prose intent and implementation can diverge.

Use `gated + spec-driven` when ANY item is true:

- money, financial correctness, production safety, security, destructive work, or high blast radius;
- multiple author/reviewer agents or an explicit independent approval loop;
- zero-debt, human QA, or phase-by-phase ship gates;
- repeated rejection/rework shows one agent's self-review is insufficient.

`simple` is only for one-slice, low-risk work whose complete intent fits in one plan
sentence. Uncertainty chooses the stricter mode. Once a branch qualifies for a stricter
mode, do not downgrade it to avoid the gate.

Mode consequences:

- `spec-driven` → load `rjv-spec-driven`; create/link the durable spec before `WORK`.
- `gated + spec-driven` → also load `rjv-gated-build`; grill the spec before code and
  require independent approval per slice.
- The plan's `RESUME HERE` names active criterion IDs, not a prose interpretation.

**Cost-routing is a hard rule on EVERY branch, not just gated builds.** Reserve the
flagship (top tier) for judgment — design, review, synthesis. Route recon,
file-reads, mechanical edits, boilerplate, test-writing, and summarization to the
cheapest capable tier, and set each subagent's model **explicitly** (never
default-inherit the expensive parent — the most common leak).

**Decide per task, and revisit.** The Cast is a starting default, not a fixed
lineup. For each task ask "cheapest tier that clears *this* bar?" and route
accordingly — cheap hands through a bulk/mechanical phase, flagship when judgment
dominates. When the mix of work shifts, **recast** (a logged Decision in the plan,
with why — not a silent drift). Don't route out a task whose spec+review overhead
exceeds the saving. Full two-ladder split (repo-tool work vs self-contained text) +
break-even detail in `rjv-gated-build`'s `MODEL-ECONOMY.md`.

## Ceiling — the plan stays thin

**Hard ceiling ~400 lines / ~20KB.** A plan is re-read on every resume — an unbounded
plan is a recurring token tax that compounds each turn. It stays thin by
construction:

- **Git holds history, so the plan doesn't.** Never keep a log "in case" —
  `git log .plans/<name>.md` is the log. The plan is a *current-state* surface.
- **Real-time promotion** (below) drains settled facts out continuously.
- If it's over the ceiling at reconcile, promote durable facts to `_docs/` and
  compress BEFORE acting.

## Real-time promotion

Settled facts leave the plan the instant they crystallize — written straight to
their durable home, never parked here for "later". Because promoted docs are branch
commits, they travel through the same PR and land on `main` exactly when the code
does. No drift, no batch-at-merge.

`rjv-spec-driven` owns the rest: which facts leave, where each one goes, the
mutation test that decides plan-state from durable truth, and the artifact formats
(spec / glossary / ADR). Load it before promoting anything.

## Reconcile-on-open — never stale

The resume guarantee is a cheap ritual, not "the agent remembers":

```
read plan → VERIFY each "done" claim against real code/db/tests → note drift in
Current State → rewrite Next Steps → stamp Last reconciled →
if over the ~400-line ceiling, promote + compress → then act
```

Never trust a checkbox; a plan whose "done" you haven't verified is a rumor.
**During work:** update the plan in the same turn as the change, never batched.
**On stop/handoff:** rewrite the `>>> RESUME HERE <<<` block to the exact resume
point; no `done` that isn't.

## Resume mechanism — deterministic, do not reinvent

The `>>> RESUME HERE <<<` / `<<< END RESUME >>>` strings are **literal — never
paraphrase them**, or the grep breaks. A fixed string is a deterministic landing
(`grep` finds it every time, survives header drift); a semantic "find the Next Steps
section" is something each agent re-locates and each session re-invents.

```
b=$(git branch --show-current)                       # current branch = the key
grep -l "^Branch: $b\$" .plans/*.md                   # → the plan that declares it
grep -A6 ">>> RESUME HERE <<<" <that-plan>            # land on the block
→ reconcile-on-open (verify done-claims) → act
→ at END of every step: rewrite the block
```

There is NO `RESUME.md` — git branches are the active-work index. Concurrent work =
concurrent branches (or worktrees), each with its own committed plan.

## Plan vocabulary stays in the plan

`Step: <id>`, `Status: shipped`, `RESUME HERE`, `.plans/shipped/…`, criterion IDs are
the file's nouns. They are not the user's. The user does not have the plan open and is
not tracking step numbers, so an answer built on a coordinate they'd have to go read is
an answer they can't use.

When reporting in chat, translate. Say what the step *is* and what state it's in:
"the old components were never deleted", rather than "step 6 is open". Cite the plan
path once, at the end, and only if they'd need to open it.

## Merge, maintenance, timeline, roadmap → `LIFECYCLE.md`

A plan is archived, never deleted: `git mv .plans/<name>.md
.plans/shipped/<YYYY-MM-DD>-<name>.md`, status stamped in the same commit. Read
[`LIFECYCLE.md`](./LIFECYCLE.md) when a branch is landing, when work arrives against
something already live, or when someone asks what shipped and when — it holds the
merge ritual, the CI-guardable invariants, the maintenance phase, how to read the
delivery timeline back, and the durable roadmap.

## Brainstorm in the plan

The plan is where thinking out loud lives. Keep it from rotting: resolved → one-line
**Decision** with the why (promote hard-to-reverse ones to an ADR); unresolved →
**Open Questions**; loose musing either crystallizes or dies.

## With rjv-spec-driven and rjv-gated-build

- **`rjv-spec-driven`** — mandatory for `Build mode: spec-driven` and
  `gated + spec-driven`. It owns the durable acceptance criteria, glossary, and ADRs.
  `WORK`, handoff, review, and QA refer to permanent criterion IDs.
- **`rjv-gated-build`** — mandatory for `Build mode: gated + spec-driven`. The plan
  is the compressed operational anchor: cast, active criterion IDs, evidence, grill
  trail, tombstones, and resume point. Durable acceptance criteria stay in `spec.md`.
  Multiple concurrent gated builds remain separate branches/plans.

---

*Provenance: production workflow from a live fintech monorepo — multiple concurrent
branches, two agents (Claude Code, Codex) sharing committed plans + `_docs/`.*

