'Compile an APPROVED ac2 plan into lean beads — the four-section ac2 schema, a wired dependency graph, and plan retirement. Refuses any bead whose ACs name no executable probe (no probe, no bead). Triggers: "ac2 beadify", "compile the plan into ac2 beads", "ac2 beads from plan". To grade the result use ac-polish.'
Resources
1Install
npx skillscat add craigvandotcom/agent-compounds/ac-beadify Install via the SkillsCat registry.
ac-beadify — plan in, lean beads out
I/O Contract
| Input | One plan plan-approve.sh check accepts (ac-plan, graded by ac-polish plan-checklist) |
| Output | Beads in br on the ac2 schema, with every dependency edge wired both ways |
| Artifacts | The epic bead; the plan moved to _plans/_done/ (retirement) |
| Verification | br dep cycles · br lint · the probe-extractor below · Consumes↔edge parity |
Contract compiled TO: references/bead-schema.md (mandatory load); canon by pointer:skills/ac-pipeline/SKILL.md, beads-standards.
The refusal that defines this skill
No probe, no bead. An AC that names no executable probe is REFUSED, emitted nowhere,
returned to the plan — a refusal, never a warning, never a label: softening it IS the
vacuous-AC regression (measured H-impact, recurrence 5). Mechanically, for every candidate bead:
# every AC must yield a probe; every probe must be runnable AND RED against current HEAD
grep -o 'Probe: `[^`]*`' "$BEAD" | sed 's/^Probe: `//; s/`$//' \
| while IFS= read -r p; do
sh -n -c "$p" || { echo "REFUSED: unrunnable probe: $p"; continue; }
sh -c "$p" >/dev/null 2>&1 \
&& echo "REFUSED: already green — this probe passes before the work exists: $p"
doneCount the extracted probes against the AC bullets; fewer = REFUSED. A prose fragment
(wc -l, "diff the file") is not a probe. Execution is part of the refusal — a probe
already green at compile REFUSES the bead (dogfood #2 measured 19; baseline inac-pipeline/FRICTIONS.md). One that cannot run (state-mutating, needs a device/credentials)
goes on an explicit NOT-EXECUTED list — never a silent skip; one naming an artifact this bead
has yet to create keeps the guarded form test -x <path> && bash <path>, honestly RED at compile.
Procedure
- Read the plan and check it mechanically. Load
references/bead-schema.md. Runskills/_tools/plan-approve.sh check <plan>— the writer's own read-back, never a hand
grep of its keys. Non-zero (REFUSED …orNOT-GATED …) is REFUSED and the plan is
returned, never compiled. - Cut the work into beads. Sizing is from the bead-checklist, never from taste: one bead
= one focused worker pass. Two signals govern the cut, both cheaper here than at implement:- Split signal — heavy in-bead cognition at implement time means it was too big; split it.
- Under-specification is a PREMISE-FAILURE class — a worker must never grind through an
underdetermined bead improvising decisions the bead should have made; a fork the plan does not
settle appends aneeds-humancard to## Decisionsper the one card grammar inskills/ac-plan/references/decisions.md, setsstatus: refined,
printsbeadify-refusal: needs-humanon its own line and stops — a plan defect surfaced
to the docket, never a bead, never a human gate.
- Write each bead to the four-section schema, exactly.
## Intent·## Acceptance Criteria·## Delivers·## Consumes— first header per type:bug→## Steps to Reproduce,epic→## Success Criteria(br lintcompiles those in). Nothing else.
Line numbers are banned in Intent. The epic's AC is the plan's silver bullet verbatim,
and## Success Criteriastill opens with the plan's## Visionverbatim. Every child AC
quotes its plan "Done when:" verbatim and adds only the probe; a split deliverable has each
child quote the parent line and add its own slice's values. "a test named X passes" is not an AC. - Apply the refusal (§ above) to every bead before any of them is created. Refuse the
bead, not the batch — but do not create a partial graph around a refused node. - Wire Delivers/Consumes as the graph.
## Deliversnames artifacts; a dependent's## Consumescites<blocker-id> -> <artifact>that the blocker's Delivers promises, ornone; a<…>placeholder is REFUSED (it reads as a premise). Then create the edges and
read them back: direction is<blocked> depends-on <blocker>, a reversedbr dep addis
SILENT, so read every edge back (br dep cycles, thenbr showon both ends). Every
child of the compiled epic gets ONE edge — parent-child (containment) — read back the
same way. The no-probe refusal names epics explicitly (a probe-less epic is refused like any other bead); parity holds both ways.
- One path per
## Deliversbullet, and every delivered path that git ALREADY TRACKS owes a
touchers line.skills/_tools/touchers.sh derive <path>prints<stem> <N> <command>;
write it beneath the bullet astouchers: `<command>` → <N> · owned by: <sibling bead>
— elseout-of-scope: <why>.
5b. Emit the closeout bead — D3: every plan-derived epic gets one even with no one-shots
(keyed off beadified: absent); emit the closeout bead per references/bead-schema.md § Closeout (D8 shape, edges + readback, one-shot refusal D4, Detect: lift D7).
6. Create the beads per the schema's Header fields — bodies go -d "$(cat <file>)" (br create REJECTS -f with a title); bead text stays dcg-safe.
7. Retire the plan (§ below).
Plan retirement — the seams chain, and the one case that refuses it
On a successful compile the plan file is moved to _plans/_done/, the epic bead gets a
comment naming its new path; the plan is preserved, never deleted.
A seams plan is never a single file — retire the whole chain. A plan compiled fromac-polish seams mode carries seams_source: naming its seams doc; each seams doc carriesparent: / supersedes: / splits[]: / seeded_from: edges to its siblings. Walk those
edges and move EVERY reachable _plans/ file to _plans/_done/ (not just $PLAN_FILE) —
stamped status: done + beadified: <epic-id>, RETIREMENT HELD guard (§ below) per file.
REFUSE to retire while an open bead still needs the plan as its subject — a dogfood
receipt, a bead whose Delivers or Intent names the plan path. If one exists, leave the file
where it is and say so:
RUST_LOG=error br list --status open --json \
| grep -Fq "$(basename "$PLAN_FILE")" && echo "RETIREMENT HELD: an open bead still names $PLAN_FILE"The guard lives HERE — the only place its condition still holds.
Hand-off
End with Next: /ac-polish bead <epic> and stop.