fix: critical issues in wisp hook system

Code review fixes:

1. CRITICAL: Move polecat check to start of runSling
   - Previously wrote wisp THEN failed, leaving orphan
   - Now fails fast before any file operations

2. CRITICAL: Sanitize slashes in agent IDs for filenames
   - Agent IDs like 'gastown/crew/joe' were creating subdirs
   - Now converts '/' to '--' for safe filenames
   - Added sanitizeAgentID/unsanitizeAgentID helpers

3. MODERATE: Use git root instead of WorkDir in prime.go
   - Hooks are written to clone root, not cwd
   - Added getGitRoot() helper for consistency

4. MODERATE: Fix silent error swallowing
   - Now logs non-ErrNoHook errors when reading hooks
   - Warns if bead doesn't exist before burning hook
   - Preserves hook if bead is missing for debugging
This commit is contained in:
Steve Yegge
2025-12-24 16:20:04 -08:00
parent dbec2c3b88
commit 7c7b8b551d
4 changed files with 57 additions and 15 deletions

View File

@@ -9,6 +9,7 @@
package wisp
import (
"strings"
"time"
)
@@ -126,6 +127,23 @@ func NewPatrolCycle(formula, createdBy string) *PatrolCycle {
}
// HookFilename returns the filename for an agent's hook file.
// Agent IDs containing slashes (e.g., "gastown/crew/joe") are sanitized
// by replacing "/" with "--" to create valid filenames.
func HookFilename(agent string) string {
return HookPrefix + agent + HookSuffix
// Sanitize agent ID: replace path separators with double-dash
// This is reversible and avoids creating subdirectories
sanitized := sanitizeAgentID(agent)
return HookPrefix + sanitized + HookSuffix
}
// sanitizeAgentID converts an agent ID to a safe filename component.
// "gastown/crew/joe" -> "gastown--crew--joe"
func sanitizeAgentID(agent string) string {
return strings.ReplaceAll(agent, "/", "--")
}
// unsanitizeAgentID converts a sanitized filename back to an agent ID.
// "gastown--crew--joe" -> "gastown/crew/joe"
func unsanitizeAgentID(sanitized string) string {
return strings.ReplaceAll(sanitized, "--", "/")
}