refactor: ZFC cleanup - move Go heuristics to Deacon molecule (gt-gaxo)

Remove Go code that makes workflow decisions. All health checking,
staleness detection, nudging, and escalation belongs in the Deacon
molecule where Claude executes it.

Removed:
- internal/daemon/backoff.go (190 lines) - exponential backoff decisions
- internal/doctor/stale_check.go (284 lines) - staleness detection
- IsFresh/IsStale/IsVeryStale from keepalive.go
- pokeMayor, pokeWitnesses, pokeWitness from daemon.go
- Heartbeat staleness classification from pokeDeacon

Changed:
- Lifecycle parsing now uses structured body (JSON or simple text)
  instead of keyword matching on subject line
- Daemon now only ensures Deacon is running and sends simple heartbeats
- No backoff, no staleness classification, no decision-making

Total: ~800 lines removed from Go code

The Deacon molecule will handle all health checking, nudging, and
escalation. Go is now just a message router.

See gt-gaxo epic for full rationale.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Steve Yegge
2025-12-24 00:11:15 -08:00
parent 0f88c793f8
commit b6817899b4
13 changed files with 145 additions and 1224 deletions

View File

@@ -86,26 +86,7 @@ func Read(workspaceRoot string) *State {
// Returns a very large duration if the state is nil.
func (s *State) Age() time.Duration {
if s == nil {
return 24 * time.Hour * 365 // Very stale
return 24 * time.Hour * 365 // No keepalive
}
return time.Since(s.Timestamp)
}
// IsFresh returns true if the keepalive is less than 2 minutes old.
func (s *State) IsFresh() bool {
return s != nil && s.Age() < 2*time.Minute
}
// IsStale returns true if the keepalive is 2-5 minutes old.
func (s *State) IsStale() bool {
if s == nil {
return false
}
age := s.Age()
return age >= 2*time.Minute && age < 5*time.Minute
}
// IsVeryStale returns true if the keepalive is more than 5 minutes old.
func (s *State) IsVeryStale() bool {
return s == nil || s.Age() >= 5*time.Minute
}

View File

@@ -39,47 +39,29 @@ func TestReadNonExistent(t *testing.T) {
}
func TestStateAge(t *testing.T) {
// Test nil state
// Test nil state returns very large age
var nilState *State
if nilState.Age() < 24*time.Hour {
t.Error("nil state should have very large age")
}
// Test fresh state
// Test fresh state returns accurate age
freshState := &State{Timestamp: time.Now().Add(-30 * time.Second)}
if !freshState.IsFresh() {
t.Error("30-second-old state should be fresh")
}
if freshState.IsStale() {
t.Error("30-second-old state should not be stale")
}
if freshState.IsVeryStale() {
t.Error("30-second-old state should not be very stale")
age := freshState.Age()
if age < 29*time.Second || age > 31*time.Second {
t.Errorf("expected ~30s age, got %v", age)
}
// Test stale state (3 minutes)
staleState := &State{Timestamp: time.Now().Add(-3 * time.Minute)}
if staleState.IsFresh() {
t.Error("3-minute-old state should not be fresh")
}
if !staleState.IsStale() {
t.Error("3-minute-old state should be stale")
}
if staleState.IsVeryStale() {
t.Error("3-minute-old state should not be very stale")
// Test older state returns accurate age
olderState := &State{Timestamp: time.Now().Add(-5 * time.Minute)}
age = olderState.Age()
if age < 4*time.Minute+55*time.Second || age > 5*time.Minute+5*time.Second {
t.Errorf("expected ~5m age, got %v", age)
}
// Test very stale state (10 minutes)
veryStaleState := &State{Timestamp: time.Now().Add(-10 * time.Minute)}
if veryStaleState.IsFresh() {
t.Error("10-minute-old state should not be fresh")
}
if veryStaleState.IsStale() {
t.Error("10-minute-old state should not be stale (it's very stale)")
}
if !veryStaleState.IsVeryStale() {
t.Error("10-minute-old state should be very stale")
}
// NOTE: IsFresh(), IsStale(), IsVeryStale() were removed as part of ZFC cleanup.
// Staleness classification belongs in Deacon molecule, not Go code.
// See gt-gaxo epic for rationale.
}
func TestDirectoryCreation(t *testing.T) {