write-vbrief · diff

git:20260708.1d6a7a1 to git:20260712.7dd40b8

1 added, 1 removed. Audit A to A.

---
name: write-vbrief
description: >
Write a vBRIEF spec (.pan/spec.vbrief.json) and continue.json directly — without
launching the interactive planning agent. Use when the work is well-understood
and the agent can author the plan from the issue body and codebase alone.
Also use when you ARE the work agent and need to self-plan before implementing.
Covers the full xBRIEF v0.8 schema, continue.json format, bead sizing rules,
inspection gates, and the `pan plan finalize` handoff command.
triggers:
- write vbrief
- create vbrief
- write spec.vbrief.json
- skip planning agent
- self-plan
- author plan
- create plan manually
- write plan without planning agent
allowed-tools:
- Bash
- Read
- Write
- Grep
- Glob
---
# Write vBRIEF — Direct Plan Authoring
Use this skill when you want to author a vBRIEF plan directly, bypassing the interactive planning agent. This is appropriate when:
- The work is well-scoped and doesn't need a Q&A discovery session
- You are a work agent that received an issue without a pre-existing plan
- The issue is small enough that a full planning session would cost more than the work itself
- You need to rewrite or patch a broken vBRIEF before continuing work
After writing the plan, run `pan plan finalize` to materialize beads and promote the spec to main.
---
## Step 1 — Explore First
Before writing a single line of JSON, read the issue and explore the relevant code. A plan written without codebase context will have wrong file paths, wrong difficulty estimates, and spurious edges.
Minimum exploration:
- Read the issue body and any linked PRDs in `<projectRoot>/.pan/drafts/<ISSUE-ID>.md`
- Grep for the primary symbols, commands, or files the issue mentions
- Identify which subsystems are affected and how many files will change
- Check for existing specs: `find <projectRoot>/.pan/specs -name "*<issue-id>*"`
---
## Step 2 — Write `.pan/spec.vbrief.json`
The file goes at `.pan/spec.vbrief.json` in the workspace root. It MUST conform to xBRIEF v0.8.
### Full schema
```json
{
"xBRIEFInfo": {
"version": "0.8",
"created": "<ISO 8601 timestamp>",
"author": "overdeck/<VERSION>",
"description": "Plan for <ISSUE-ID>: <issue title>"
},
"plan": {
"id": "<issue-id-lowercase>",
"title": "<issue title>",
"status": "approved",
"uid": "<UUID v4>",
"author": "agent:<model-slug>",
"sequence": 1,
"created": "<ISO 8601 timestamp>",
"updated": "<ISO 8601 timestamp>",
"references": [
{ "uri": "<issue URL>", "label": "<ISSUE-ID>", "type": "issue" }
],
"tags": ["<relevant tags>"],
"narratives": {
"Problem": "<what problem this solves>",
"Proposal": "<the approach chosen>",
"NonGoals": "<explicitly out of scope; behaviors this issue must NOT introduce — one per line, prefixed '- '>"
},
"autoDecisions": [],
"items": [
{
"id": "<short-kebab-id>",
"title": "<task title>",
"status": "pending",
"priority": "medium",
"created": "<ISO 8601 timestamp>",
"metadata": {
"difficulty": "trivial|simple|medium|complex|expert",
"issueLabel": "<issue-id-lowercase>",
"requiresInspection": false,
"inspectionDepth": "fast",
"files_scope": ["src/path/to/file.ts"],
"files_scope_confidence": "high",
"verify_commands": ["npm run typecheck"],
"expected_outputs": ["typecheck completes without errors"],
"readiness": "ready",
"traces": ["FR-1", "NFR-2"]
},
"narrative": { "Action": "<what needs to be done>" },
"items": [
{
"id": "<parent-id>.ac1",
"title": "<specific testable acceptance criterion>",
"status": "pending",
"metadata": { "kind": "acceptance_criterion" }
}
]
}
],
"edges": [
{ "from": "<source-item-id>", "to": "<target-item-id>", "type": "blocks" }
]
}
}
```
### Field rules
| Field | Rule |
|-------|------|
| `plan.id` | Issue ID in **lowercase** — e.g. `"pan-1234"`. Never `issueId`, never `issue_id`. |
| `plan.uid` | Fresh UUID v4. Generate with `node -e "console.log(crypto.randomUUID())"`. |
| `plan.status` | Must be `"approved"` when written by a self-planning agent (skip `draft`/`proposed`). |
| `items[].status` | One of: `draft`, `proposed`, `approved`, `pending`, `running`, `completed`, `blocked`, `cancelled`, `failed`. Use `"pending"` for new items. |
| `plan.narratives.NonGoals` | Required narrative. List everything discovery established as out of scope (`"none"` if genuinely nothing); review enforces these as must-not constraints. |
| `items[].metadata.requiresInspection` | **Required on every item.** See inspection rules below. |
| `items[].metadata.inspectionDepth` | `"fast"` (default) or `"deep"`. Only matters when `requiresInspection: true`. |
| `items[].metadata.files_scope` | Required `string[]` of files/globs this item is expected to touch. Use concrete paths or narrow globs, not broad repo-wide patterns. |
| `items[].metadata.files_scope_confidence` | Required confidence in `files_scope`: `"high"`, `"medium"`, or `"low"`. |
| `items[].metadata.verify_commands` | Required for slot-eligible items. List commands that verify this item before slot merge, e.g. `["npm run typecheck", "npx vitest run tests/unit/foo.test.ts"]`. |
| `items[].metadata.expected_outputs` | Required for slot-eligible items. List the observable evidence expected from `verify_commands`, e.g. `["foo.test.ts passes"]`. |
| `items[].metadata.readiness` | Required tri-state swarm readiness: `"ready"` for parallel-safe work, `"sequential"` for intentionally serialized work, `"needs_refinement"` when the item is not ready to dispatch. |
| `items[].metadata.traces` | Optional `string[]` of PRD requirement IDs (`FR-1`, `NFR-2`) this item satisfies. |
| nested `items` with `metadata.kind: "acceptance_criterion"` | Each item must have at least one acceptance-criterion child item. |
---
## Step 3 — Write `.pan/continue.json`
The continue file records decisions and hazards so the work agent (and review/test agents) have context that isn't in the vBRIEF narrative.
```json
{
"version": "1",
"issueId": "<ISSUE-ID-UPPERCASE>",
"created": "<ISO 8601 timestamp>",
"updated": "<ISO 8601 timestamp>",
"gitState": { "branch": "<current branch>", "sha": "<short sha>", "dirty": false },
"decisions": [
{ "id": "D1", "summary": "<decision text>", "recordedAt": "<ISO 8601 timestamp>" }
],
"hazards": [
{ "id": "H1", "summary": "<risk or edge case>", "mitigation": "<how to handle it>" }
],
"resumePoint": null,
"beadsMapping": {},
"agentModel": "agent:<model-slug>",
"sessionHistory": [
{
"timestamp": "<ISO 8601 timestamp>",
"reason": "planning",
"note": "Self-authored plan (no planning agent)",
"agentModel": "agent:<model-slug>"
}
]
}
```
Rules:
- `version` must be `"1"`
- `issueId` must be uppercase (e.g. `"PAN-1234"`)
- `resumePoint` stays `null` — the work agent populates it when it begins
- `beadsMapping` stays `{}` — `pan plan finalize` populates it
---
## Step 4 — Finalize
From the workspace root, run:
```bash
pan plan finalize
```
This atomically:
1. Reads `.pan/spec.vbrief.json`
- 2. Creates beads via `bd create` (one per `items[]` entry, edges respected)
+ 2. Creates beads through the canonical writer (one per `items[]` entry, edges respected)
3. Sets `plan.status` to `"proposed"`
4. Promotes the canonical spec into `<projectRoot>/.pan/specs/<YYYY-MM-DD>-<ISSUE>-<slug>.vbrief.json`
5. Commits on main, pushes, transitions the tracker issue to Planned
Do **not** run `bd create` yourself — `pan plan finalize` is the only sanctioned path.
---
## Bead sizing rules
Default to **many small beads** over a few large ones. A well-sized bead:
- Has one focused change (if you need "and" in the title, it's two beads)
- Is independently reviewable from its diff alone
- Leaves the tree in a working state if merged alone
- Has a testable acceptance criterion
**Heuristics:**
- One renamed command = one bead
- One moved file = one bead (unless mechanically identical batch → sub-items under one bead)
- One new API endpoint = one bead
- One schema migration = one bead
- One doc update = one bead (or one per logical cluster, not "update all docs")
When in doubt, split. Too-small beads: mild overhead. Too-large beads: reviewers can't reason about them, agents deliver partial results, and the inspection gate can't verify mid-implementation.
---
## Edge semantics
Add an edge only when there is a **real** dependency:
| When to add `blocks` edge | When NOT to add |
|---------------------------|-----------------|
| B consumes a file/type/value A produces | Narrative flow ("feels like it should come second") |
| Both items modify the same file | Readability preference |
| B can't start until A reaches a specific state | Defensive sequencing "just in case" |
Absent edges = permission for the work agent to run items in parallel. A spurious edge silently forces serialization that was never intended.
Edge types: `blocks` (hard), `informs` (soft/advisory), `invalidates`, `suggests`
---
## Inspection gate (`requiresInspection`)
Set `requiresInspection: true` **only** when a wrong implementation would cascade into downstream beads before the verification gate catches it:
- **Foundation for downstream beads** — subsequent beads depend on this bead's interfaces, types, or module boundaries
- **Architectural decision crystallizing in code** — naming a public API, choosing a library boundary, picking an event shape
- **Spec ambiguity risk** — the description is broad enough that two very different diffs could both look "done"
- **Security/auth surface** — defects here propagate into later beads assuming the security posture
- **Cross-cutting protocol or schema** — wire format, DB migration, RPC contract, event payload
Set `requiresInspection: false` for:
- Mechanical changes (flag flip, rename, single-file tweak)
- Leaf beads (no downstream bead depends on their internals)
- Tests, docs, comment-only updates
- Wrongs that surface immediately at typecheck/lint
When `requiresInspection: true`, you **must** also set `metadata.foundationFor: ["<bead-id>", ...]` listing the downstream beads that would need to be redone if this one were wrong. An empty `foundationFor` on an inspection bead is a planning error — flip it back to `false`.
Most plans have 0–2 inspection beads. More than 3 suggests the beads are too large.
---
## Difficulty rubric
| Level | When | Typical model |
|-------|------|---------------|
| `trivial` | Typo, comment, formatting only | haiku |
| `simple` | Bug fix, single file, obvious change | haiku |
| `medium` | New feature, 3–5 files, standard patterns | sonnet |
| `complex` | Refactor, migration, 6+ files, some risk | sonnet |
| `expert` | Architecture, security, performance, high risk | opus |
---
## Quick checklist
Before running `pan plan finalize`:
- [ ] `.pan/spec.vbrief.json` has exactly two top-level keys: `xBRIEFInfo` and `plan`
- [ ] `plan.id` is lowercase issue ID
- [ ] `plan.uid` is a fresh UUID v4
- [ ] `plan.status` is `"approved"`
- [ ] Every item has `metadata.requiresInspection` (boolean)
- [ ] Every item has `metadata.files_scope`, `metadata.files_scope_confidence`, and `metadata.readiness`
- [ ] Every slot-eligible item has `metadata.verify_commands` and `metadata.expected_outputs`
- [ ] Every item has at least one nested `items` AC entry
- [ ] `foundationFor` populated on every `requiresInspection: true` item
- [ ] No spurious edges
- [ ] `.pan/continue.json` written with at least one `decisions[]` entry
---
## See also
- `docs/VBRIEF.md` — full schema reference and lifecycle states
- `/pan-plan` — start the interactive planning agent instead
- `pan plan finalize --help` — finalization flags