Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ A mod in the plugin compacts a session at the end of a turn once its free contex

An effort is its top bead and everything that bead depends on, followed transitively across trackers. The top bead states the outcome the effort delivers, and parent links put nothing in an effort. `muster` adopts or files the top bead rather than creating an epic to anchor the effort. It files the work as observable outcomes, each wired to the outcomes it needs, and the graph ends where the effort's outcome is observed. Each release, each deployment to each host, and any other project's deploy the evidence relies on is a bead in the effort, and a bead that is true only after a release or deployment sits downstream of it. A release belongs to the product and may carry several efforts' work, so `muster` joins the product's open release bead or has one filed, names no tag, and never invents a release for one effort. Where the release runs through a formula that cannot be poured yet, a plain bead stands in. An epic is an "and" over the outcomes it depends on. The steward is started with the top bead, and the effort's slug, index line and berth are keyed on it. The effort ends when someone who has seen the evidence for its outcome closes the top bead.

The bar that each bead, the graph and the top bead meet is written once, in `references/good-bead.md`, and `muster` and the steward both read it.

The slash-only skill sets `disable-model-invocation: true`, because plugin skills cannot be disabled one at a time. Claude Code then refuses it to the Skill tool, so only a typed command or a launch prompt starts it.

The skills contain no multiplexer syntax. They call only `sign-on` and `berth`. Coordination runs over [commy](https://github.com/CodeForBreakfast/commy), with each effort indexed in a `boatyard` topic in its project's channel, and the [beads](https://github.com/gastownhall/beads) graph is the system of record. A worker records its berth id as `agent_pane` and its Claude Code session as `agent_session` on the bead it is working, so bead viewers can draw the seat against its work. A steward claims its top bead, so `tally` on any machine can tell a running effort from a parked one.
Expand Down
30 changes: 30 additions & 0 deletions references/good-bead.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# A good bead

This is the bar every bead in an effort meets, together with the graph that wires them and the top bead that heads them. `muster` builds an effort to it, and the steward drives an effort built to it.

## Each bead

- **A bead is an outcome that someone outside the change can observe, wired to the outcomes it needs.**
- **One bead is one worker is one context.** A single worker could finish it without compacting.
- **A bead is briefable.** It has a clear deliverable, a definition of done and stated edges, so the steward can write a complete brief from it when it starts the seat.
- **A definition of done stated only as removals is incomplete.** Deleting the thing meets an all-negative outcome most completely, so a deletion that orphans behaviour passes every clause. On a cleanup or refactor bead, name what must still work after the removals: the behaviour that keeps running, and what still reaches it.

## The graph

- **Every bead in the effort is reachable from the top bead through dependency edges.** A bead that is only a child of something in the effort is outside it. Where an outcome needs a bead's work, the outcome depends on that bead.
- **The graph ends where the effort's outcome is observed, not where the code merges.** Every step between the merge and the evidence is a bead in the effort: each release, each deployment to each host, and any other project's deploy that the evidence relies on.
- **A release belongs to the product, not to the effort.** One release may carry work from several efforts, so never invent a release for one effort, and name no tag. Find the product's open release bead and make it depend on the work it ships, or have one filed as the host's release convention says. Where the release runs through a formula that cannot be poured yet, a plain bead stands in for it.
- **A bead that is true only once something is released or deployed depends on that release or deployment.** A deployment depends on the release it installs, and the release depends on the work it ships. The work never depends on either, and neither is the work's parent. bd blocks a parent's children while the parent is blocked, so either shape deadlocks.
- **An epic is an "and" over the outcomes it depends on.** It leaves out any outcome that a sibling already reaches through its own dependencies. Most efforts need no epic.
- **Wire true blockers only.** Add a dependency only where B cannot start until A's work exists, and prove each one rather than assuming a sequence. An edge that only orders the work is false. Where a pull request cap or a limit settled on the top bead holds work back, the steward chooses what goes next at the time, and an edge would take that choice away. No backward edges and no cycles.
- **Two beads that would collide in one file are not a dependency.** A collision often means the code is badly shaped. Code that is open for extension lets new work sit beside what is there, while several beads that all have to change one place is churn. Consider whether a better structure would let the beads run apart. Where it would, that restructure is work the colliding beads really depend on. Where it would not, leave them parallel.
- **Work built on another bead's unmerged code depends on that bead.** In a repo that takes pull requests, the edge is what stops the second worker branching from an unmerged pull request and building a stack nobody can review. The steward settles each repo's delivery mode itself, so the top bead does not carry it.

## The top bead

The top bead is the effort's cold-restart record.

- **The top bead describes the effort, and nothing else.** Its body holds the outcome, the evidence that shows it is true, why the effort takes this shape, and what has been settled and must not be reopened. The roster, the parentage, the blocking edges, the critical path and each bead's status all live in the graph, and the body restates none of them. A foreign strand's id is the target of its edge, and the body does not repeat it.
- **The top bead never says how the effort is staffed or delivered.** Staffing is the steward's call at run time. How a repo takes work is in that repo's own instructions.
- **The top bead carries the effort's slug as `effort_slug` in its metadata.** Every commy topic the effort uses is named from it: `#<project>/<effort>`, its `-decisions` topic and each `-<bead>` working topic. A replacement steward has no other way to learn the name, and one that invents a fresh slug posts into topics no worker listens on, and adds a second index line for an effort that already has one.
- **The test:** a fresh steward holding only the top bead and the graph can rebuild the whole effort, in this project and across others. If it cannot, find the missing fact, and check first that it is not a field left unset.
42 changes: 13 additions & 29 deletions skills/muster/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ The steward consumes a wired, context-sized bead graph under one top bead and ne

Coordination runs over commy: see its `using-commy` skill for channels, topics and tone. The `steward` skill is what consumes your output, and the `worker` skill is the seat that does the work.

**The bar a good bead meets is written in `references/good-bead.md` under the plugin's root,** which is two directories above this skill's base directory. It covers each bead, the graph that wires them and the top bead. Read it before you build anything, because every bead, edge and top bead you hand over meets it.

## Are you meant to be mustering?

If nobody invoked you by name, or told you in so many words to muster an effort, you are not preparing one. Leave this skill.
Expand Down Expand Up @@ -45,19 +47,15 @@ An effort is its **top bead** and everything that bead depends on, followed tran

The top bead states the outcome the effort delivers, such as "installed and working for us". Adopt the bead in this project that already states that outcome. Where none does, file one as the top bead. Don't create an epic to anchor the effort.

The top bead is the effort's cold-restart record, as *Wire the graph* describes. It lives in the project you are running in, which is the project the steward runs in. Whoever closes it has seen the evidence that its outcome is true, and the effort ends when it closes.
The top bead is the effort's cold-restart record, as the bar describes. It lives in the project you are running in, which is the project the steward runs in. Whoever closes it has seen the evidence that its outcome is true, and the effort ends when it closes.

## File the work as outcomes

**File the work as outcome beads that someone outside the change can observe, and wire each outcome to the outcomes it needs.**
**File the work as outcome beads that meet the bar for each bead, and wire each outcome to the outcomes it needs.**

## Audit local beads for size and briefability

**One bead is one worker is one context.** For each local bead, ask whether a single worker could finish it without compacting. **Split** any bead that is too big, and say so as you split it so the human can interrupt, but don't wait for approval.

Each bead must also be briefable: it needs a clear deliverable, a definition of done and stated edges, so the steward can write a complete brief from it when it starts the seat. Where a bead is thin on these, flesh it out now.

**A definition of done stated only as removals is incomplete.** Deleting the thing meets an all-negative outcome most completely, so a deletion that orphans behaviour passes every clause. On a cleanup or refactor bead, name what must still work after the removals: the behaviour that keeps running, and what still reaches it.
Hold each local bead to the bar for each bead. **Split** any bead too big for one worker's context, and say so as you split it so the human can interrupt, but don't wait for approval. Where a bead is thin on what a brief needs, flesh it out now.

## Shape other projects' slices over commy

Expand All @@ -67,32 +65,21 @@ For each other project the effort touches, hold a working session in that projec

1. **Post the strand's context** in the foreign channel, in a topic named for the effort: what the effort is, and which slice that project owns.
2. **Find or create the beads.** Some slices already have beads and some don't. Work with them to find the beads that cover the slice, or to create new ones, and take their lead on how to decompose the slice, where its edges sit, and whether something already covers it.
3. **Get the slice into shape.** It must be filed as outcomes, context-sized, briefable, and **wired inside its home tracker so that one worker can drive it to done without an unwired stall**. A half-wired foreign slice is a stall the steward will hit mid-effort, so land it now.
3. **Get the slice into shape.** Its beads must meet the bar for each bead, and the slice must be **wired inside its home tracker so that one worker can drive it to done without an unwired stall**. A half-wired foreign slice is a stall the steward will hit mid-effort, so land it now.
4. **Collect the ids and the ready state** they report.
5. **Wire it in** with `bd dep add` from the waiting local bead, or the top bead, to the foreign id they reported.

Where nobody answers in a foreign project's channel, reach that project as your host asks. A foreign project that still does not answer, or pushes back on shape or feasibility, is a blocker to raise with the human. Don't cover it with an edge to work nobody agreed to.

## Wire the graph and make the top bead a cold-restart record

- **Every bead in the effort is reachable from the top bead through dependency edges.** A bead that is only a child of something in the effort is outside it. Where an outcome needs a bead's work, the outcome depends on that bead.
- **The graph ends where the effort's outcome is observed, not where the code merges.** Every step between the merge and the evidence is a bead in the effort: each release, each deployment to each host, and any other project's deploy that the evidence relies on.
- **A release belongs to the product, not to the effort.** One release may carry work from several efforts, so never invent a release for this one, and name no tag. Find the product's open release bead and make it depend on the work it ships, or have one filed as the host's release convention says. Where the release runs through a formula that cannot be poured yet, a plain bead stands in for it.
- **A bead that is true only once something is released or deployed depends on that release or deployment.** A deployment depends on the release it installs, and the release depends on the work it ships. The work never depends on either, and neither is the work's parent. bd blocks a parent's children while the parent is blocked, so either shape deadlocks.
- **An epic is an "and" over the outcomes it depends on.** It leaves out any outcome that a sibling already reaches through its own dependencies. Most efforts need no epic.
- **Wire true blockers only.** Add a dependency only where B cannot start until A's work exists, and prove each one rather than assuming a sequence. An edge that only orders the work is false. Where a pull request cap or a limit settled on the top bead holds work back, the steward chooses what goes next at the time, and an edge would take that choice away. No backward edges and no cycles.
- **Two beads that would collide in one file are not a dependency.** A collision often means the code is badly shaped. Code that is open for extension lets new work sit beside what is there, while several beads that all have to change one place is churn. Consider whether a better structure would let the beads run apart. Where it would, that restructure is work the colliding beads really depend on. Where it would not, leave them parallel.
- **Work built on another bead's unmerged code depends on that bead.** In a repo that takes pull requests, the edge is what stops the second worker branching from an unmerged pull request and building a stack nobody can review. The steward settles each repo's delivery mode itself, so the top bead does not carry it.
- **Write the top bead to describe the effort, and nothing else.** Its body holds the outcome, the evidence that shows it is true, why the effort takes this shape, and what has been settled and must not be reopened. The roster, the parentage, the blocking edges, the critical path and each bead's status all live in the graph, and the body restates none of them. A foreign strand's id is the target of its edge, and the body does not repeat it.
- **The top bead never says how the effort is staffed or delivered.** Staffing is the steward's call at run time. How a repo takes work is in that repo's own instructions.
- **Put the effort's slug in the top bead's metadata:**
Wire the graph and write the top bead to the bar for the graph and for the top bead. Put the effort's slug in the top bead's metadata:

```bash
bd update <top-bead> --set-metadata effort_slug=<slug>
```
```bash
bd update <top-bead> --set-metadata effort_slug=<slug>
```

Every commy topic the effort uses is named from it: `#<project>/<effort>`, its `-decisions` topic and each `-<bead>` working topic. A replacement steward has no other way to learn the name, and one that invents a fresh slug posts into topics no worker listens on, and adds a second index line for an effort that already has one.
- **The test:** a fresh steward holding only the top bead and the graph can rebuild the whole effort, in this project and across others. If it cannot, find the missing fact, and check first that it is not a field you left unset.
Then run the bar's test: a fresh steward holding only the top bead and the graph can rebuild the whole effort.

## The readiness gate

Expand All @@ -104,13 +91,10 @@ Before you start the steward, confirm that the graph can be driven. All of these
```bash
bdi --beads --brief <project>:<top-bead> | jq -r '.ready[] | "\(.project):\(.id) \(.labels | join(",")) \(.title)"'
```
- Every bead is an observable outcome, context-sized and briefable.
- Every bead in the effort is reachable from the top bead through dependency edges. Every release and deployment between a merge and the observed outcome is a bead in the effort, and every bead that is true only after a release or deployment sits downstream of it.
- Every bead, the graph and the top bead meet every rule in the bar.
- Every foreign strand is confirmed in good shape by its home project, and wired into the graph as an edge on its home-project id.
- The top bead states the outcome and its evidence, the effort's shape and what is settled, and carries the effort slug in its metadata. It restates nothing the graph holds.
- Every edge is a real dependency, and beads that would collide in one file have had their structure considered.

For a graph that is not trivial, give **one** throwaway subagent an adversarial review of it, and keep only its verdict. Its brief: hunt for edges that only order work, colliding beads a better structure would separate, missing blockers including work built on unmerged code, beads that state a task rather than an observable outcome, a release or deployment missing between a merge and the observed outcome, a release invented for this effort alone, a release or deployment wired upstream of the work it ships, beads reached only through a parent link, oversized beads, unwired foreign strands, and a top bead that would not let a cold steward rebuild the effort. Fix what it finds. This review is your own quality check, not a gate on the human. Where your seat may not start subagents, the review does not run, and the checks above remain the real bar.
For a graph that is not trivial, give **one** throwaway subagent an adversarial review of it, and keep only its verdict. Its brief: read the bar at its full path, and hunt for every breach of it, missing blockers included, and for unwired foreign strands. Fix what it finds. This review is your own quality check, not a gate on the human. Where your seat may not start subagents, the review does not run, and the checks above remain the real bar.

**When your seat will take the effort over itself, the review always runs, even on a trivial graph.** A fresh steward is what proves the graph can be driven cold, and a seat that has held the whole conversation is not fresh. So add one more line to the subagent's brief: rebuild the effort from the top bead alone, and report every fact the effort needs that the beads do not hold.

Expand Down
2 changes: 1 addition & 1 deletion skills/steward/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ A seat that muster has just handed the effort to breaks it too, because it may h

### Reconstruct, on every wake

3. **Read the top bead.** `bd show <top-bead>` gives the effort's goal, what has been settled, and the `effort_slug`. The top bead describes the effort and only that. Its roster and its edges come from the graph below it, so a description that restates them is a stale copy to delete, not a picture to complete.
3. **Read the top bead.** `bd show <top-bead>` gives the effort's goal, what has been settled, and the `effort_slug`. The top bead describes the effort and only that, as `muster` builds it to the bar in `references/good-bead.md` under the plugin's root, which is two directories above this skill's base directory. Its roster and its edges come from the graph below it, so a description that restates them is a stale copy to delete, not a picture to complete.
4. **Sort the graph with `bdi`, never with `bd ready` or `bd blocked`.** Neither reads an edge into another tracker, so each lists a bead as ready while its foreign dependency is still open. bdi reads the top bead's tree: the top bead and everything it depends on, followed transitively across trackers, never through a parent link. First run `bd gate check --type=gh:pr`, so a merged pull request's gate is already closed. Then read the tree from your project's directory, and never scope the read with `--project`, because a blocker in a project left out then reads as not ready:

```bash
Expand Down