From 58a7615801b4b209b64eda022181977b69113ff5 Mon Sep 17 00:00:00 2001 From: gastown/polecats/dag Date: Tue, 30 Dec 2025 22:14:39 -0800 Subject: [PATCH] Witness: Reduce chattiness, increase autonomy (gt-lxdn7) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- internal/cmd/callbacks.go | 87 ++++--------------------------------- templates/witness-CLAUDE.md | 8 ++-- 2 files changed, 11 insertions(+), 84 deletions(-) diff --git a/internal/cmd/callbacks.go b/internal/cmd/callbacks.go index 308e9c2e..77ec74e6 100644 --- a/internal/cmd/callbacks.go +++ b/internal/cmd/callbacks.go @@ -34,11 +34,9 @@ var ( // SLING_REQUEST: - request to sling work patternSling = regexp.MustCompile(`^SLING_REQUEST:\s+(\S+)`) - // WITNESS_REPORT: - periodic health report from witness - patternWitnessReport = regexp.MustCompile(`^WITNESS_REPORT:\s+(\S+)`) - - // REFINERY_REPORT: - 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) diff --git a/templates/witness-CLAUDE.md b/templates/witness-CLAUDE.md index c515a983..260e8918 100644 --- a/templates/witness-CLAUDE.md +++ b/templates/witness-CLAUDE.md @@ -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 processed" -m "Work: - MR sent to refinery for branch: " - ``` + +**NOTE:** Do NOT notify Mayor about routine polecat processing. The Witness handles +all routine lifecycle autonomously. Only escalate genuine problems to Mayor. ---