Witness: Reduce chattiness, increase autonomy (gt-lxdn7)

Remove routine POLECAT_PROCESSED and WITNESS_REPORT/REFINERY_REPORT
mail types from Witness→Mayor communication.

Changes:
- Remove Notify Mayor step for routine polecat processing from
  witness-CLAUDE.md template
- Remove WITNESS_REPORT and REFINERY_REPORT callback types from
  callbacks.go (pattern matching, handlers, constants)
- Update callback help text to reflect new behavior

Witness now handles routine lifecycle autonomously. Only genuine
problems that require human/Mayor intervention are escalated:
- ESCALATION (problems Witness cannot resolve)
- BLOCKED (needs human decision)
- CRASH_RECOVERY (informational)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
gastown/polecats/dag
2025-12-30 22:14:39 -08:00
committed by Steve Yegge
parent c2a33be4e6
commit 58a7615801
2 changed files with 11 additions and 84 deletions

View File

@@ -34,11 +34,9 @@ var (
// SLING_REQUEST: <bead-id> - request to sling work
patternSling = regexp.MustCompile(`^SLING_REQUEST:\s+(\S+)`)
// WITNESS_REPORT: <rig> - periodic health report from witness
patternWitnessReport = regexp.MustCompile(`^WITNESS_REPORT:\s+(\S+)`)
// REFINERY_REPORT: <rig> - periodic status from refinery
patternRefineryReport = regexp.MustCompile(`^REFINERY_REPORT:\s+(\S+)`)
// NOTE: WITNESS_REPORT and REFINERY_REPORT removed.
// Witnesses and Refineries handle their duties autonomously.
// They only escalate genuine problems, not routine status updates.
)
// CallbackType identifies the type of callback message.
@@ -51,9 +49,9 @@ const (
CallbackHelp CallbackType = "help"
CallbackEscalation CallbackType = "escalation"
CallbackSling CallbackType = "sling"
CallbackWitnessReport CallbackType = "witness_report"
CallbackRefineryReport CallbackType = "refinery_report"
CallbackUnknown CallbackType = "unknown"
// NOTE: CallbackWitnessReport and CallbackRefineryReport removed.
// Routine status reports are no longer sent to Mayor.
)
// CallbackResult tracks the result of processing a callback.
@@ -97,8 +95,9 @@ its type:
HELP: - Route to human or handle if possible
ESCALATION: - Log and route to human
SLING_REQUEST: - Spawn polecat for the work
WITNESS_REPORT: - Log health status
REFINERY_REPORT: - Log queue status
Note: Witnesses and Refineries handle routine operations autonomously.
They only send escalations for genuine problems, not status reports.
Unknown message types are logged but left unprocessed.`,
RunE: runCallbacksProcess,
@@ -237,14 +236,6 @@ func processCallback(townRoot string, msg *mail.Message, dryRun bool) CallbackRe
result.Action, result.Error = handleSling(townRoot, msg, dryRun)
result.Handled = result.Error == nil
case CallbackWitnessReport:
result.Action, result.Error = handleWitnessReport(townRoot, msg, dryRun)
result.Handled = result.Error == nil
case CallbackRefineryReport:
result.Action, result.Error = handleRefineryReport(townRoot, msg, dryRun)
result.Handled = result.Error == nil
default:
result.Action = "unknown message type, skipped"
result.Handled = false
@@ -276,10 +267,6 @@ func classifyCallback(subject string) CallbackType {
return CallbackEscalation
case patternSling.MatchString(subject):
return CallbackSling
case patternWitnessReport.MatchString(subject):
return CallbackWitnessReport
case patternRefineryReport.MatchString(subject):
return CallbackRefineryReport
default:
return CallbackUnknown
}
@@ -492,64 +479,6 @@ func handleSling(townRoot string, msg *mail.Message, dryRun bool) (string, error
beadID, targetRig, beadID, targetRig), nil
}
// handleWitnessReport processes a WITNESS_REPORT from a rig's Witness.
func handleWitnessReport(townRoot string, msg *mail.Message, dryRun bool) (string, error) {
matches := patternWitnessReport.FindStringSubmatch(msg.Subject)
rig := ""
if len(matches) > 1 {
rig = matches[1]
}
// Extract stats from body
var healthy, unhealthy, stuck int
for _, line := range strings.Split(msg.Body, "\n") {
line = strings.TrimSpace(line)
fmt.Sscanf(line, "Healthy: %d", &healthy)
fmt.Sscanf(line, "Unhealthy: %d", &unhealthy)
fmt.Sscanf(line, "Stuck: %d", &stuck)
}
if dryRun {
return fmt.Sprintf("would log witness report for %s (healthy=%d, unhealthy=%d)",
rig, healthy, unhealthy), nil
}
// Log the report
logCallback(townRoot, fmt.Sprintf("witness_report: rig %s: healthy=%d, unhealthy=%d, stuck=%d",
rig, healthy, unhealthy, stuck))
return fmt.Sprintf("logged witness report for %s", rig), nil
}
// handleRefineryReport processes a REFINERY_REPORT from a rig's Refinery.
func handleRefineryReport(townRoot string, msg *mail.Message, dryRun bool) (string, error) {
matches := patternRefineryReport.FindStringSubmatch(msg.Subject)
rig := ""
if len(matches) > 1 {
rig = matches[1]
}
// Extract stats from body
var pending, processed, failed int
for _, line := range strings.Split(msg.Body, "\n") {
line = strings.TrimSpace(line)
fmt.Sscanf(line, "Pending: %d", &pending)
fmt.Sscanf(line, "Processed: %d", &processed)
fmt.Sscanf(line, "Failed: %d", &failed)
}
if dryRun {
return fmt.Sprintf("would log refinery report for %s (pending=%d, processed=%d)",
rig, pending, processed), nil
}
// Log the report
logCallback(townRoot, fmt.Sprintf("refinery_report: rig %s: pending=%d, processed=%d, failed=%d",
rig, pending, processed, failed))
return fmt.Sprintf("logged refinery report for %s", rig), nil
}
// logCallback logs a callback processing event to the town log.
func logCallback(townRoot, context string) {
logger := townlog.NewLogger(townRoot)

View File

@@ -111,11 +111,9 @@ Before killing ANY polecat session, verify:
NOTE: Use `gt polecat nuke` instead of raw git commands. It knows the correct
worktree parent repo (mayor/rig or .repo.git) and handles cleanup properly.
The nuke will automatically block if cleanup_status indicates unpushed work.
3. **Notify Mayor** (for tracking):
```bash
gt mail send mayor/ -s "Polecat <name> processed" -m "Work: <issue>
MR sent to refinery for branch: <branch>"
```
**NOTE:** Do NOT notify Mayor about routine polecat processing. The Witness handles
all routine lifecycle autonomously. Only escalate genuine problems to Mayor.
---