diff --git a/README.md b/README.md index 078d2f0..fb28188 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ read at runtime from a small **project profile** you fill in during onboarding. | **Agents** (`agents/`) | `rig-debugger`, `rig-reviewer`, `rig-architect`, `rig-qa`, `rig-coder` | Copied into `/.claude/agents/` | | **pi adapter** (`pi/`) | Per-target persona frontmatter (`pi/agents/*.yml`, assembled onto the shared bodies) + the `/rig` dispatcher prompt | Copied into `/.pi/{agents,prompts}/` — see [`docs/pi.md`](docs/pi.md) | | **Support docs** (`templates/`) | starter `REVIEWER.md` (+ `REVIEWER.scope-template.md`), `STYLE.md`, `label-mapping.md` | Copied into `/.claude/` (only if absent) | -| **Scripts** (`scripts/`) | `setup-worktree.sh`, `remove-worktree.sh`, `mint-gh-app-token.sh`, `scope-reviewer.ts`, `set-session-name.sh` (Claude-only) | Copied into `/.claude/scripts/` | +| **Scripts** (`scripts/`) | `setup-worktree.sh`, `remove-worktree.sh`, `mint-gh-app-token.sh`, `scope-reviewer.ts`, `rig-state.ts`, `set-session-name.sh` (Claude-only) | Copied into `/.claude/scripts/` | | **CI templates** (`ci/`) | `security-scan`, `label-pr`, `image-build`, `slack-notify`, `test-gate`, `test-e2e`, and the **AI review-bot bundle** (`review-bot-gate`, `auto-review-fix`, `pr-review-labels`) | Copied into `/.github/workflows/` (see `ci/README.md`) | | **Onboarding** (`skills/rig-onboard/`) | The agent-driven installer skill | Run once against a target project | @@ -89,6 +89,15 @@ reference (the origin project's own values). colocated with the code, mirroring nested `AGENTS.md`). `rig-review` resolves the scoped files a diff touches and asserts them as P1s, so a subsystem's hard-won invariants stop getting re-discovered in PR review. +- **Long runs keep state on disk, not in the transcript.** `/rig-task` spans + seven steps and four delegated agents. `/rig-epic run` loops that over every + child. When the transcript compacts mid-run, the acceptance criteria, the + failing assertion, and which review findings are already fixed go with it. So + every long skill keeps one small structured document per run under + `.rig/state/`, and `scripts/rig-state.ts` validates each update outside the + model. It rejects unknown keys, wrong types, and impossible states. A size + budget stops the document drifting back into a transcript. See + [`docs/state.md`](docs/state.md). - **Agent output is written for humans.** Agents produce a lot of prose — PR bodies, ticket descriptions, review findings, plans, hand-backs — and left alone they write it badly: buried conclusions, passive voice, hedge stacks, diff --git a/docs/state.md b/docs/state.md new file mode 100644 index 0000000..4b83016 --- /dev/null +++ b/docs/state.md @@ -0,0 +1,134 @@ +# Run state (`rig-state`) + +A rig skill is a long procedure. `/rig-task` spans seven steps and four +delegated agents; `/rig-epic run` loops that over every child. The host agent's +only memory of what happened between those steps is its transcript. When that +transcript compacts mid-run, three things go with it: the acceptance criteria, +which test went red and why, and which review findings are already fixed. The +agent then re-derives them from `git` and `gh`, or guesses. + +`rig-state` replaces that memory with one small structured document per run, +kept on disk and validated outside the model: + +``` +.rig/state/.json the current state — what the next step reads +.rig/state/.jsonl an append-only journal of accepted patches +``` + +The state is the working memory. The journal is the audit trail, there so a +human can debug a failed run. **Never feed the journal to a model.** That +reintroduces the history the state replaces. + +Both are throwaway coordination state, rebuildable from the tracker and the +repo, and **gitignored — never committed**. `/rig-doctor` checks that. + +## The contract + +Each step of a skill does three things, in this order: + +1. Read the state (`rig-state show `) instead of scrolling back. +2. Do the step's work. +3. Persist what a *later* step needs, as a patch — not a summary of what + happened. + +That third rule is the one that matters. Record facts and decisions the next +step reads: the branch name, the failing assertion, the reason you rejected an +approach. Don't record narration. If a later step never reads it, it doesn't go +in the state. + +## Commands + +`` resolves from the repo root: `.claude/scripts/` first, then +`.rig/scripts/`, first hit wins — the same rule `/rig-worktree` uses. Run these +with `bun` (or your TypeScript runner). + +| Command | Does | +|---|---| +| `rig-state.ts init [--json '{…}']` | Start a run at the skill's first phase. Fails if the run exists. | +| `rig-state.ts patch --json '{…}' [--step