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:
@@ -136,6 +136,7 @@ func HasHook(root, agent string) bool {
|
||||
}
|
||||
|
||||
// ListHooks returns a list of agents with active hooks.
|
||||
// Agent IDs are returned in their original form (with slashes).
|
||||
func ListHooks(root string) ([]string, error) {
|
||||
dir := filepath.Join(root, WispDir)
|
||||
entries, err := os.ReadDir(dir)
|
||||
@@ -152,7 +153,8 @@ func ListHooks(root string) ([]string, error) {
|
||||
if len(name) > len(HookPrefix)+len(HookSuffix) &&
|
||||
name[:len(HookPrefix)] == HookPrefix &&
|
||||
name[len(name)-len(HookSuffix):] == HookSuffix {
|
||||
agent := name[len(HookPrefix) : len(name)-len(HookSuffix)]
|
||||
sanitized := name[len(HookPrefix) : len(name)-len(HookSuffix)]
|
||||
agent := unsanitizeAgentID(sanitized)
|
||||
agents = append(agents, agent)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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, "--", "/")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user