From 6b827ea36d93091b70b09bcf4701ad0cb842da13 Mon Sep 17 00:00:00 2001 From: Graeme Foster <80714+GraemeF@users.noreply.github.com> Date: Mon, 2 Nov 2026 16:47:11 +0000 Subject: [PATCH] fix(skills): have a worker ask for a permission in its own berth A worker now asks for a refused command with the question dialog in its own berth and waits there, so its blocked berth reaches the human without a relay through the steward's berth, which the human rarely watches. The steward relays only where its host has no route of its own for a blocked berth. --- skills/steward/SKILL.md | 18 ++++++++++-------- skills/worker/SKILL.md | 8 ++++---- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/skills/steward/SKILL.md b/skills/steward/SKILL.md index dc1b44c..5eea36e 100644 --- a/skills/steward/SKILL.md +++ b/skills/steward/SKILL.md @@ -26,7 +26,7 @@ That is also why you must be miserly with your own context. The effort outlives **Your host's rule for asking the human wins over this skill.** Where its `CLAUDE.md`, or a document it names, says how a seat reaches the human, follow that and read this section as the default it replaces. -Workers never ping the human. A question that a seat waits on goes on its own bead labelled `human`, in the tracker of the project whose work waits on it, and the waiting bead depends on it. That label is the human's queue, so a question needs no post and no mention. A permission goes to the human in your berth. An action only the human can take goes where your host files the human's actions, and to the decisions topic only where it names no such place. **Ask in your berth only to answer what the human asked you there, and to follow up on that same point.** Every other question goes on a question bead, even while the human is typing to you. That covers a question a worker raised and one that comes from your own reading. Your reply in the berth may point at the bead. Anything else needs a bead or the decisions topic, and you keep both current. +Workers never ping the human. A question that a seat waits on goes on its own bead labelled `human`, in the tracker of the project whose work waits on it, and the waiting bead depends on it. That label is the human's queue, so a question needs no post and no mention. A permission waits in the berth of the seat that needs it, as *A worker's permission waits in its own berth* says. An action only the human can take goes where your host files the human's actions, and to the decisions topic only where it names no such place. **Ask in your berth only to answer what the human asked you there, and to follow up on that same point.** Every other question goes on a question bead, even while the human is typing to you. That covers a question a worker raised and one that comes from your own reading. Your reply in the berth may point at the bead. Anything else needs a bead or the decisions topic, and you keep both current. ## Topics @@ -144,7 +144,7 @@ A seat that muster has just handed the effort to breaks it too, because it may h `--limit 0` matters. The default is 50 rows, and a truncated list quietly turns a sleeping worker's bead into one you might start over. The list covers the whole tracker, so skip a bead outside the effort. Its seat may sit in a yard your `berth list` cannot see. Check whether each berth is still its bead's seat, as *Watching the berths you started* says. - **A berth that is still its seat means a live seat is there, awake or asleep.** It sleeps on a question when the bead it sits on depends on an open `human` bead, which `bd human list --json` lists. It sleeps on a permission or an action when its latest post in its working topic asks for one. This wins even when the bead also sits behind an open pull-request gate, which is exactly the case for a rework seat that hit a question mid-rebase. The seat watches the bead its wait ends on, and that watch wakes it. Don't poll its pull request. + **A berth that is still its seat means a live seat is there, awake or asleep.** It sleeps on a question when the bead it sits on depends on an open `human` bead, which `bd human list --json` lists. It waits on a permission when `berth agent-state` reads `blocked`, and sleeps on an action when its latest post in its working topic asks for one. This wins even when the bead also sits behind an open pull-request gate, which is exactly the case for a rework seat that hit a question mid-rebase. The seat watches the bead its wait ends on, and that watch wakes it. Don't poll its pull request. **Otherwise the seat died, and nothing will wake it.** Hand the bead back to the graph as *Watching the berths you started* says. A dependency on a question bead keeps it out of bdi's `ready` until the human answers, and an open pull-request gate keeps it out until the merge. Then start a fresh worker on it in the next `-r` topic, with any answer quoted from the question bead in its brief. Where the bead is a step of a delivery molecule, brief the worker on the work bead that waits on that molecule, and it sits on the step again. A bead whose seat died waiting on a permission or an action is ready at once, and its fresh worker asks again. 2. **Otherwise an open `gh:pr` gate or an open outcome step of a delivery molecule means the bead is in delivery**, as *A bead closes on merge* and *A bead delivered by a formula* say. No seat is on the bead itself, so never relay to it and never start a worker on it. Poll its pull request, or read its molecule, whose steps show any seat still working it. @@ -369,7 +369,7 @@ Starting workers is a **loop**, not a kickoff. Start one at each ready bead, and ### Watching the berths you started - **What ties a seat to its work** is the `agent_pane` and `agent_session` on the bead the seat sits on. That is the bead you briefed it on, or under a delivery formula the step of that bead's molecule it is working. `sign-on` labels the berth with the bead you brief, the worker names its berth after each bead it moves to, and you set neither yourself. -- **`berth agent-state ` reads `blocked` when a worker is waiting at a permission prompt.** Only the human can clear it, so take it to them as *A worker's permission goes to the human in your berth* says. +- **`berth agent-state ` reads `blocked` when a worker is waiting at a permission prompt.** Only the human can clear it, as *A worker's permission waits in its own berth* says. - **A bead names a berth only while that berth is its seat.** A seat that dies before it finishes leaves its berth on its bead, and a berth id is reused once its berth closes. A stale `agent_pane` then joins the bead to whatever seat takes the id next. The berth is still the bead's seat only while `berth list` holds its id, labelled with the bead's id, with an agent in it. A berth whose Claude Code has exited to its shell is still open, but it holds no agent, so its seat is dead: ```bash @@ -425,11 +425,13 @@ One topic per effort, `#/-decisions`: - **You are its only writer.** Workers post their actions to their working topics, and you lift them in. - **Your berth is a channel only for what the human brings you there.** You ask a question there only as *You own the human's attention for this effort* says, and an action only if they can do it there and then. If they leave a question unanswered, or say they will think about it, file the bead before your turn ends, and write any answer they give you there onto its bead in their words. An instruction they give you there for a worker goes on a bead first, as *No seat does work that has no bead* says. -### A worker's permission goes to the human in your berth +### A worker's permission waits in its own berth -A permission is the one ask that does not go in the decisions topic. A worker that needs the human's approval for a command posts the command and how to reach its berth to its working topic. A worker stuck at an approval prompt reads `blocked` in `berth agent-state` instead, and its berth id is the `agent_pane` on its bead. +A permission is the one ask that goes neither on a bead nor in the decisions topic. A worker that needs the human's approval for a command asks for it with the question dialog in its own berth and waits there. A worker stopped at an approval prompt is already waiting. Either way `berth agent-state` reads `blocked`, and the worker's berth id is the `agent_pane` on the bead it sits on. -Tell the human in your own berth: which worker, the command, why the work needs it, and how to reach the worker's berth. They approve in the worker's berth and name the action. Or they run the command there themselves, which always works, and tell the worker to carry on. An approval they give anywhere else never reaches the worker, because a permission classifier judges a command by the conversation of the seat that runs it. So don't relay an approval they give you, and don't file a question bead for it. +The human approves in that berth and names the action, or runs the command there themselves. An approval they give anywhere else never reaches the worker, because a permission classifier judges a command by the conversation of the seat that runs it. So don't relay an approval they give you, and don't file a question bead for it. + +**Where your host carries a blocked berth to the human itself, don't relay the permission,** because your relay would be a second copy of the host's ask. Where your host names no such route, tell the human in your berth which worker is blocked and how to reach its berth. ## The boatyard index @@ -449,7 +451,7 @@ Restate your line only on those changes, never on progress. Those lines are the A stall is work that has stopped moving, and restarting it is your job. Work out which kind it is, then act on the same wake: -- **Staffed and waiting on the human.** A live worker sleeps on a question bead, or has posted an action or a permission in its working topic. A question bead needs nothing from you until it closes. Lift an action into the decisions topic, and take a permission to the human in your berth. +- **Staffed and waiting on the human.** A live worker sleeps on a question bead, has posted an action in its working topic, or waits on a permission in its own berth. A question bead needs nothing from you until it closes. Lift an action into the decisions topic, and leave a permission where *A worker's permission waits in its own berth* says. - **Unstaffed.** The work has no accountable worker at all: a question you assumed someone else owned, a handover a channel never answered, a newly unblocked bead nobody is on. Start a worker for it now. **A bead in delivery is not this.** It has no seat by design, and a second worker on it duplicates a change already in a reviewer's queue. - **Dark.** A worker has gone silent past its checkpoint. Nudge its working topic once. If it is still dark at the next wake, start a replacement. @@ -556,7 +558,7 @@ A steward resumes the effort through the wake ritual, as on any fresh start, and - **You don't decide the human's calls.** Architecture, money and external commitments go on a question bead. - **One effort, possibly across projects.** You run in the project where the top bead lives. Work in another tracker is wired into your graph by an edge on its home-project id, and its readiness is read through `bdi`. - **Other projects' channels are not part of your effort.** Never route anything to the human through whoever answers in another project's channel, and read your workers' state from your own working topics. -- **Don't work around permission prompts.** If a command you need yourself is refused, ask the human for it in your own berth, as for a worker's permission. +- **Don't work around permission prompts.** If a command you need yourself is refused, ask for it with the question dialog in your own berth, as a worker does. ## Before a compaction diff --git a/skills/worker/SKILL.md b/skills/worker/SKILL.md index f774297..856e490 100644 --- a/skills/worker/SKILL.md +++ b/skills/worker/SKILL.md @@ -94,7 +94,7 @@ You will most often stall on something only the human can give you: an answer to The human answers by closing the question bead, and the answer stays on it. Keep the bead true while you wait: edit it if the question changes, and dismiss it with `bd human dismiss` if the question goes away. 3. **Watch the bead your wait ends on** with beady-eye's `watch` tool. For a question, that is the question bead. For a dependency on another bead, in your tracker or another project's, it is that bead, and you name its project. -4. **Post to your working topic.** For a question, post a one-line pointer to its bead, because the question lives on the bead and never only in the post. An action only the human can take, such as supplying a credential, is not a question and gets no question bead: post the action itself, and the steward takes it to the human. Never ask the human directly, and never ask with `AskUserQuestion` or any prompt in your terminal. Nobody watches a worker's berth. +4. **Post to your working topic.** For a question, post a one-line pointer to its bead, because the question lives on the bead and never only in the post. An action only the human can take, such as supplying a credential, is not a question and gets no question bead: post the action itself, and the steward takes it to the human. Never ask the human directly, and never ask a question or an action with `AskUserQuestion` or any prompt in your terminal, because nobody watches a worker's berth for one. A permission is the one ask you make in your berth, as *Getting the human's permission* says. 5. **Sleep.** Stay open to inbound messages, with no scheduled re-check. Your watch wakes you when the bead changes. The steward relays the human's word on an action, and relays a closed question bead while beady-eye says its watcher is down. Each relay also mentions you, and a mention reaches you even after your subscription has lapsed. 6. **On a message from beady-eye, act on the bead it names.** A comment, or any change that leaves the bead open, does not end your wait. Read it with `bd show`, answer on the bead if the human asked you something there, and sleep again. A bead that closed, or went from its tracker, ends the wait. `unwatch` it, then resume. 7. **Resume.** Rebuild your context first, because the compactor may have compacted you while you slept. Re-read your brief, `bd show` your bead and its notes, and read your working topic since your last post. Then read the answer on the closed question bead with `bd show`. An answer that does not settle the question is still an answer: file a fresh question only if you still need one. Re-check whatever fact you were waiting on, such as a secret now existing or a commit having landed. Post to your working topic that you are awake and resuming, because the steward is waiting for that post, and continue in place. @@ -104,10 +104,10 @@ You will most often stall on something only the human can give you: an answer to Permission is the one thing you ever need from the human in your berth. When your host's permission mode refuses a command you need, only the human can let it through, and they have to do it in your berth. A permission classifier judges a command by the conversation of the seat that runs it, so an approval given on a bead or on commy never reaches it. An approval typed in your berth clears it only if it names the action. 1. **Record it on your bead, and stay on the bead you sit on,** as step 1 of *Block and sleep* says. File no question bead for a permission. -2. **Post the ask to your working topic:** the exact command, why the work needs it, and how to reach your berth. The steward takes it to the human. -3. **Sleep.** The human types their approval into your berth and names the action, such as "go ahead and copy the key". A bare "I approve" does not clear it. Or they run the command there themselves, which always works, and tell you to carry on. Run the command if they approved it, or check its result if they ran it, and continue. +2. **Ask with the question dialog in your own berth, and wait at it.** `AskUserQuestion` is a deferred tool, so load it first. Name the exact command and why the work needs it, and word the approving option so it names the action, such as "Go ahead and copy the key". The dialog leaves your berth `blocked`, and a blocked berth is how the human learns that a seat needs them. Don't also post the ask to your working topic or anywhere else, because that would be a second copy of the same ask. +3. **Act on the answer.** If the human approved, run the command. If they ran it there themselves, which always works, check its result. Then continue. If they refused, record that on your bead and post it to your working topic. -When a command stops at an approval prompt instead, you cannot post. Stay at the prompt. `berth agent-state` reads `blocked`, and the steward sends the human to it. +When a command stops at an approval prompt instead, you are already waiting. Stay at the prompt. ## Stay in lane