Remove WORKFLOW_DESIGN.md
This commit is contained in:
parent
26d0aa11ee
commit
23fbf5cb50
|
|
@ -1,258 +0,0 @@
|
||||||
# Workflow Design & Implementation Plan
|
|
||||||
|
|
||||||
## Summary
|
|
||||||
|
|
||||||
This document describes the current state and planned implementation of the
|
|
||||||
role-based workflow system in anvillm. It covers bot roles, team composition,
|
|
||||||
emergent delegation, and the Supervisor redesign.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## What Exists Today
|
|
||||||
|
|
||||||
### `anvilspawn` (`scripts/anvilspawn`)
|
|
||||||
|
|
||||||
Single primitive for spawning a bot with a role:
|
|
||||||
|
|
||||||
```
|
|
||||||
anvilspawn <backend> <role> <workdir>
|
|
||||||
```
|
|
||||||
|
|
||||||
- Computes an 8-character hex hash of `$WORKDIR` using md5sum
|
|
||||||
- Spawns a new session: `echo "new $BACKEND $WORKDIR" | 9p write anvillm/ctl`
|
|
||||||
- Sets alias to `$HASH-$ROLE` (e.g. `a3f2b1c4-developer`)
|
|
||||||
- Assigns role via `echo "$ROLE" | 9p write anvillm/$ID/role`
|
|
||||||
|
|
||||||
Bots spawned for the same `$WORKDIR` share the same hash prefix, making them
|
|
||||||
discoverable to each other via `list_sessions`. This is what enables organic
|
|
||||||
collaboration without any explicit wiring.
|
|
||||||
|
|
||||||
### Roles (`roles/`)
|
|
||||||
|
|
||||||
All roles follow a standard structure:
|
|
||||||
|
|
||||||
```
|
|
||||||
## Responsibilities
|
|
||||||
## Prohibited Activities
|
|
||||||
## Workflow
|
|
||||||
## Response Format
|
|
||||||
```
|
|
||||||
|
|
||||||
Current roles:
|
|
||||||
|
|
||||||
| File | Description |
|
|
||||||
|------|-------------|
|
|
||||||
| `solo-developer.md` | Full-cycle: code, research, test, deploy, task mgmt |
|
|
||||||
| `developer.md` | Code only; no research, testing, or review |
|
|
||||||
| `reviewer.md` | Code review; automated checks + manual review |
|
|
||||||
| `tester.md` | Testing; unit, integration, fault injection, static analysis |
|
|
||||||
| `devops.md` | CI/CD, deployment, infrastructure |
|
|
||||||
| `researcher.md` | Query answering via three-tier cache (KB → code → web) |
|
|
||||||
| `taskmgr.md` | GitHub issues and PRs via `gh` CLI |
|
|
||||||
| `author.md` | Documentation writing |
|
|
||||||
| `technical-editor.md` | Editorial review of documentation |
|
|
||||||
| `pkgmgr.md` | Package management (e.g., AUR, RPM, deb) |
|
|
||||||
|
|
||||||
**Key design decisions:**
|
|
||||||
- No explicit delegation protocols in any role — delegation is emergent
|
|
||||||
- No inbox-check startup steps — messages are delivered automatically
|
|
||||||
- `Prohibited Activities` sections drive emergent delegation: when a bot
|
|
||||||
can't do something, it naturally looks for a peer that can
|
|
||||||
|
|
||||||
### Team Composition
|
|
||||||
|
|
||||||
There are no fixed team templates. Teams are assembled by running `anvilspawn`
|
|
||||||
once per role, using the same `$WORKDIR`. The hash ties them together.
|
|
||||||
|
|
||||||
Example — a dev+review+test team:
|
|
||||||
```sh
|
|
||||||
anvilspawn claude developer ~/src/myproject
|
|
||||||
anvilspawn claude reviewer ~/src/myproject
|
|
||||||
anvilspawn claude tester ~/src/myproject
|
|
||||||
```
|
|
||||||
|
|
||||||
All three share the same hash prefix and can find each other via `list_sessions`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Emergent Delegation
|
|
||||||
|
|
||||||
When a bot receives a task outside its `Prohibited Activities`, it naturally:
|
|
||||||
1. Checks `list_sessions` for a peer with a compatible role
|
|
||||||
2. Sends the appropriate message type (REVIEW_REQUEST, QUERY_REQUEST, etc.)
|
|
||||||
3. Waits for a response before proceeding
|
|
||||||
|
|
||||||
If no peer is available, the bot refuses the out-of-scope task rather than
|
|
||||||
attempting it unless explicitly instructed to ignore its role. This is by
|
|
||||||
design — the human decides team composition.
|
|
||||||
|
|
||||||
**Observed behavior:** a `devops` bot, upon receiving a coding task, derived
|
|
||||||
on its own that it should hand off to the `developer` bot. No explicit
|
|
||||||
delegation protocol was required.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Bead Workflow
|
|
||||||
|
|
||||||
### Current State
|
|
||||||
|
|
||||||
Beads support:
|
|
||||||
- States: `open → in_progress → closed`
|
|
||||||
- Parent-child relationships (`new title description <parent-id>`)
|
|
||||||
- Dependencies (`dep`/`undep`, `beads/ready` queue)
|
|
||||||
- Capability labels: `capability:low|standard|high` (model tier hints)
|
|
||||||
- Arbitrary labels via `store.AddLabel`
|
|
||||||
|
|
||||||
Bots have write access to beads and can create child beads organically.
|
|
||||||
|
|
||||||
### Planned: `claimable-by` Label
|
|
||||||
|
|
||||||
A new label type: `claimable-by:<role>` (e.g. `claimable-by:reviewer`).
|
|
||||||
|
|
||||||
This label does two things:
|
|
||||||
1. Opts the bead into Supervisor dispatch (unlabeled beads are ignored)
|
|
||||||
2. Specifies which role must handle it
|
|
||||||
|
|
||||||
Beads without `claimable-by` are left for organic bot claiming or human
|
|
||||||
assignment. Both models coexist without conflict — the Supervisor only
|
|
||||||
touches what it has been told to dispatch.
|
|
||||||
|
|
||||||
**Usage:**
|
|
||||||
```sh
|
|
||||||
# When creating a bead that should be dispatched to a reviewer:
|
|
||||||
echo "new 'Review: auth module' 'description' bd-123 claimable-by:reviewer" \
|
|
||||||
| 9p write anvillm/beads/ctl
|
|
||||||
```
|
|
||||||
|
|
||||||
The `capability` label is now optional and orthogonal to `claimable-by`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Supervisor Redesign
|
|
||||||
|
|
||||||
### Current State
|
|
||||||
|
|
||||||
The existing Supervisor (`bot-templates/Supervisor`, now deleted):
|
|
||||||
- Polls `beads/ready` every N seconds
|
|
||||||
- Dispatches by `capability_level` label → model tier
|
|
||||||
- Spawns new sessions (haiku/sonnet/opus) as needed
|
|
||||||
- Writes a generic "complete bead X" context to spawned sessions
|
|
||||||
- Reuses stopped sessions when model tier matches
|
|
||||||
- Cleans up stopped/exited sessions with closed beads
|
|
||||||
|
|
||||||
### Planned Changes
|
|
||||||
|
|
||||||
**Remove entirely:**
|
|
||||||
- Session spawning — `anvilspawn` is the human's tool for team composition
|
|
||||||
- Capability-level dispatch — optional, ignore for now
|
|
||||||
- Generic worker context writing — bots already have roles from `anvilspawn`
|
|
||||||
|
|
||||||
**Add:**
|
|
||||||
- `claimable-by:<role>` label reading from bead JSON
|
|
||||||
- Session matching by hash prefix AND role:
|
|
||||||
1. Compute `HASH=$(echo -n "$WORKDIR" | md5sum | cut -c1-8)`
|
|
||||||
2. For each session: check alias starts with `$HASH-`
|
|
||||||
3. AND: `9p read anvillm/<id>/role` == required role
|
|
||||||
- Inbox delivery after claiming: write a PROMPT_REQUEST to the matched
|
|
||||||
session's inbox notifying it of the bead assignment
|
|
||||||
- Skip (don't dispatch) if no matching session exists — leave bead queued
|
|
||||||
|
|
||||||
**Keep:**
|
|
||||||
- Polling loop with configurable interval
|
|
||||||
- Cleanup: kill stopped/exited sessions whose assigned beads are closed
|
|
||||||
- Skip beads that are already assigned
|
|
||||||
|
|
||||||
### New Dispatch Logic (pseudocode)
|
|
||||||
|
|
||||||
```
|
|
||||||
HASH = md5(WORKDIR)[0:8]
|
|
||||||
|
|
||||||
for each bead in beads/ready:
|
|
||||||
if bead.assignee is not empty: skip
|
|
||||||
role = extract_label(bead.labels, "claimable-by:")
|
|
||||||
if role is empty: skip # not supervisor-managed
|
|
||||||
|
|
||||||
session = find_session(hash=HASH, role=role, state=running|idle)
|
|
||||||
if session is empty: skip # no bot available, leave queued
|
|
||||||
|
|
||||||
claim(bead.id, session.id)
|
|
||||||
deliver_to_inbox(session.id, bead.id)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Session Matching
|
|
||||||
|
|
||||||
```bash
|
|
||||||
find_session() {
|
|
||||||
local want_role="$1"
|
|
||||||
while read -r sess_id backend state alias cwd; do
|
|
||||||
[[ "$alias" == "$HASH-"* ]] || continue
|
|
||||||
sess_role=$(9p read "anvillm/$sess_id/role" 2>/dev/null)
|
|
||||||
[ "$sess_role" = "$want_role" ] || continue
|
|
||||||
echo "$sess_id"
|
|
||||||
return
|
|
||||||
done < <(9p read anvillm/list)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Inbox Delivery
|
|
||||||
|
|
||||||
After claiming, notify the bot via the user/outbox mechanism:
|
|
||||||
```
|
|
||||||
echo "to=$SESSION_ID type=PROMPT_REQUEST subject=bead:$BEAD_ID body=..." \
|
|
||||||
| 9p write user/outbox
|
|
||||||
```
|
|
||||||
|
|
||||||
*(Exact format to be confirmed against the p9 server user/outbox write handler.)*
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Implementation Plan
|
|
||||||
|
|
||||||
### Phase 1 — `claimable-by` label support in beads (infrastructure)
|
|
||||||
|
|
||||||
- [ ] Add `claimable-by` as a recognized label prefix in `internal/p9/beads.go`
|
|
||||||
- [ ] Expose it in bead JSON output so the Supervisor can read it
|
|
||||||
- [ ] Verify `beads/ready` includes beads with `claimable-by` labels
|
|
||||||
|
|
||||||
### Phase 2 — Supervisor rewrite (`scripts/anvilsupervisor` or updated script)
|
|
||||||
|
|
||||||
- [ ] Remove spawning logic entirely
|
|
||||||
- [ ] Remove capability-level dispatch
|
|
||||||
- [ ] Implement `find_session` with hash+role matching
|
|
||||||
- [ ] Implement `claimable-by` label extraction from bead JSON
|
|
||||||
- [ ] Implement inbox delivery after claim
|
|
||||||
- [ ] Keep cleanup loop
|
|
||||||
- [ ] Update mkfile to install the new Supervisor
|
|
||||||
|
|
||||||
### Phase 3 — Role-aware bead creation
|
|
||||||
|
|
||||||
- [ ] Update `beads` skill to document `claimable-by` label
|
|
||||||
- [ ] Ensure bots that create child beads (e.g. developer creating a review
|
|
||||||
bead) know to add `claimable-by:reviewer` so the Supervisor picks it up
|
|
||||||
|
|
||||||
### Phase 4 — Dependency gate enforcement (future)
|
|
||||||
|
|
||||||
- [ ] Supervisor should not dispatch a bead if its dependencies are not all
|
|
||||||
`closed` (this may already be handled by `beads/ready` — verify)
|
|
||||||
- [ ] Consider adding a rule: parent bead cannot transition to `closed` unless
|
|
||||||
all child beads with `claimable-by` labels are `closed`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Open Questions
|
|
||||||
|
|
||||||
1. **user/outbox format** — confirm exact write format for delivering a message
|
|
||||||
to a session inbox from outside an agent context (i.e. from the Supervisor
|
|
||||||
shell script).
|
|
||||||
|
|
||||||
2. **beads/ready and dependencies** — does `beads/ready` already exclude beads
|
|
||||||
with open dependencies, or does the Supervisor need to check this itself?
|
|
||||||
|
|
||||||
3. **Supervisor as a bot vs. script** — the current Supervisor is a polling
|
|
||||||
shell script. This works but has no inbox. A future consideration is whether
|
|
||||||
the Supervisor should itself be a session (bot) so it can receive
|
|
||||||
notifications rather than polling. Not urgent.
|
|
||||||
|
|
||||||
4. **Multiple sessions with the same role** — if two `developer` bots share
|
|
||||||
the same hash (e.g. two instances for the same workdir), which one gets the
|
|
||||||
bead? Current plan: first match wins. Could be round-robin later.
|
|
||||||
Reference in New Issue