Files
gastown/.beads/formulas/mol-convoy-feed.formula.toml
2026-01-02 18:08:14 -08:00

260 lines
6.2 KiB
TOML

description = """
Feed stranded convoys by dispatching ready work to available polecats.
Dogs execute this formula when the Deacon detects a stranded convoy. A convoy
is stranded when it has ready issues (open, unblocked, no assignee) but no
workers are processing them.
## Dog Contract
This is infrastructure work. You:
1. Receive convoy ID via variable
2. Load convoy and find ready issues
3. Check idle polecat capacity across rigs
4. Dispatch min(ready_issues, idle_polecats) using gt sling
5. Report actions taken
6. Return to kennel
## Variables
| Variable | Source | Description |
|----------|--------|-------------|
| convoy | --var | The stranded convoy ID to feed |
## Single Pass Design
Dog doesn't babysit or wait for completion. The workflow is:
1. Find ready issues in convoy
2. Dispatch each to an available polecat
3. Exit immediately
If convoy is still stranded next Deacon patrol cycle, another dog will be
dispatched. This keeps the system stateless and batch-oriented.
## Failure Modes
| Situation | Action |
|-----------|--------|
| Convoy not found | Exit with error, notify Deacon |
| No ready issues | Exit success (false positive, convoy is fine) |
| No idle polecats | Exit success, note in report (will retry next cycle) |
| Sling fails | Continue with remaining issues, note failures |"""
formula = "mol-convoy-feed"
version = 1
[squash]
trigger = "on_complete"
template_type = "work"
include_metrics = true
[[steps]]
id = "load-convoy"
title = "Load convoy and identify ready issues"
description = """
Load the convoy and find issues ready for dispatch.
**1. Check assignment:**
```bash
gt hook # Shows convoy in hook_bead or vars
```
**2. Load convoy details:**
```bash
gt convoy status {{convoy}} --json
```
**3. Identify ready issues:**
For each tracked issue in the convoy:
```bash
bd show <issue-id> --json
```
An issue is "ready" if ALL of these are true:
- status = "open" (NOT in_progress, closed, or hooked)
- not in blocked list (check: bd blocked --json)
- assignee is empty OR assignee session is dead
Check blocked status:
```bash
bd blocked --json
# If issue ID appears here, it's blocked (skip it)
```
Check assignee session if set:
```bash
# If assignee like "gastown/polecats/nux"
tmux has-session -t gt-gastown-polecat-nux 2>/dev/null && echo "alive" || echo "dead"
```
**4. Build ready list:**
Collect all ready issues with their metadata:
- Issue ID
- Title
- Priority
- Rig (extracted from prefix)
Sort by priority (P0 first) for dispatch order.
**Exit criteria:** Ready issues identified and prioritized."""
[[steps]]
id = "check-capacity"
title = "Check polecat capacity across rigs"
needs = ["load-convoy"]
description = """
Determine how many polecats are available for dispatch.
**1. For each rig that has ready issues:**
```bash
gt polecats <rig>
# Shows polecat status: idle, working, etc.
```
**2. Count available capacity:**
Available polecats are those that:
- Exist in the rig's polecat pool
- Currently idle (no hooked work)
- Session is running
**3. Calculate dispatch count:**
```
dispatch_count = min(ready_issues, available_polecats)
```
If dispatch_count = 0:
- Log: "No capacity available, will retry next cycle"
- Proceed to report step (no dispatches to make)
**4. Match issues to rigs:**
For each ready issue, determine target rig from issue prefix:
- gt-* issues → gastown rig
- bd-* issues → beads rig
- etc.
**Exit criteria:** Dispatch plan created with issue→rig mappings."""
[[steps]]
id = "dispatch-work"
title = "Dispatch ready issues to polecats"
needs = ["check-capacity"]
description = """
Sling each ready issue to an available polecat.
**For each issue in dispatch plan:**
```bash
# Dispatch issue to the appropriate rig
# This spawns a fresh polecat or assigns to idle one
gt sling <issue-id> <rig>
# Example:
gt sling gt-abc123 gastown
gt sling bd-xyz789 beads
```
**Track results:**
For each dispatch:
- Success: Note issue ID, target rig, polecat assigned
- Failure: Note issue ID, error message
**Important notes:**
- `gt sling` handles polecat selection automatically
- It will spawn a new polecat if none available
- The polecat gets the issue hooked and starts immediately
- Don't wait for polecat to complete - fire and forget
**If sling fails:**
- Continue with remaining issues
- Note the failure for the report
- Don't escalate individual failures (will retry next cycle)
**Exit criteria:** All dispatchable issues have been slung."""
[[steps]]
id = "report-results"
title = "Generate and send feeding report"
needs = ["dispatch-work"]
description = """
Create summary report of convoy feeding actions.
**1. Generate report:**
```markdown
## Convoy Feed Report: {{convoy}}
**Ready issues found**: {{ready_count}}
**Polecats available**: {{available_count}}
**Issues dispatched**: {{dispatch_count}}
### Dispatched Work
{{#each dispatched}}
- {{issue_id}}: {{title}} → {{rig}}/{{polecat}}
{{/each}}
### Skipped (no capacity)
{{#if skipped}}
{{#each skipped}}
- {{issue_id}}: {{title}} (will retry next cycle)
{{/each}}
{{else}}
(none)
{{/if}}
### Errors
{{#if errors}}
{{#each errors}}
- {{issue_id}}: {{error}}
{{/each}}
{{else}}
(none)
{{/if}}
```
**2. Send to Deacon:**
```bash
gt mail send deacon/ -s "Convoy fed: {{convoy}}" -m "$(cat <<EOF
Convoy {{convoy}} feeding complete.
Dispatched: {{dispatch_count}}/{{ready_count}} issues
{{#if errors}}Errors: {{error_count}}{{/if}}
{{report_summary}}
EOF
)"
```
**3. Update convoy (optional):**
If convoy has a notify field, could add a note about feeding activity.
Not required - the dispatch tracking handles visibility.
**Exit criteria:** Report generated and sent."""
[[steps]]
id = "return-to-kennel"
title = "Signal completion and return to kennel"
needs = ["report-results"]
description = """
Signal work complete and return to available pool.
**1. Signal completion to Deacon:**
```bash
gt mail send deacon/ -s "DOG_DONE $(hostname)" -m "Task: convoy-feed
Convoy: {{convoy}}
Ready: {{ready_count}}
Dispatched: {{dispatch_count}}
Status: COMPLETE
Ready for next assignment."
```
**2. Return to kennel:**
Dog returns to available state in the pool. Deacon will assign next work
or retire the dog if pool is oversized.
**Exit criteria:** Deacon notified, dog ready for next work or retirement."""
[vars]
[vars.convoy]
description = "The convoy ID to feed"
required = true