fix: create mayor/daemon.json during gt start and gt doctor --fix (#225)

* fix: create mayor/daemon.json during gt start and gt doctor --fix (#5)

- Add DaemonPatrolConfig type with heartbeat and patrol settings
- Add Load/Save/Ensure functions for daemon patrol config
- Create daemon.json in gt start (non-fatal if fails)
- Make PatrolHooksWiredCheck fixable with Fix() method
- Add comprehensive tests for both config and doctor checks

This fixes the issue where gt doctor expects mayor/daemon.json to exist
but it was never created by gt start or any other command.

* refactor: use constants.DirMayor instead of hardcoded string
This commit is contained in:
Subhrajit Makur
2026-01-07 02:29:41 +05:30
committed by GitHub
parent 9d7dcde1e2
commit 7fe505d673
6 changed files with 555 additions and 44 deletions

View File

@@ -66,6 +66,63 @@ type DaemonConfig struct {
PollInterval string `json:"poll_interval,omitempty"` // e.g., "10s"
}
// DaemonPatrolConfig represents the daemon patrol configuration (mayor/daemon.json).
// This configures how patrols are triggered and managed.
type DaemonPatrolConfig struct {
Type string `json:"type"` // "daemon-patrol-config"
Version int `json:"version"` // schema version
Heartbeat *HeartbeatConfig `json:"heartbeat,omitempty"` // heartbeat settings
Patrols map[string]PatrolConfig `json:"patrols,omitempty"` // named patrol configurations
}
// HeartbeatConfig represents heartbeat settings for daemon.
type HeartbeatConfig struct {
Enabled bool `json:"enabled"` // whether heartbeat is enabled
Interval string `json:"interval,omitempty"` // e.g., "3m"
}
// PatrolConfig represents a single patrol configuration.
type PatrolConfig struct {
Enabled bool `json:"enabled"` // whether this patrol is enabled
Interval string `json:"interval,omitempty"` // e.g., "5m"
Agent string `json:"agent,omitempty"` // agent that runs this patrol
}
// CurrentDaemonPatrolConfigVersion is the current schema version for DaemonPatrolConfig.
const CurrentDaemonPatrolConfigVersion = 1
// DaemonPatrolConfigFileName is the filename for daemon patrol configuration.
const DaemonPatrolConfigFileName = "daemon.json"
// NewDaemonPatrolConfig creates a new DaemonPatrolConfig with sensible defaults.
func NewDaemonPatrolConfig() *DaemonPatrolConfig {
return &DaemonPatrolConfig{
Type: "daemon-patrol-config",
Version: CurrentDaemonPatrolConfigVersion,
Heartbeat: &HeartbeatConfig{
Enabled: true,
Interval: "3m",
},
Patrols: map[string]PatrolConfig{
"deacon": {
Enabled: true,
Interval: "5m",
Agent: "deacon",
},
"witness": {
Enabled: true,
Interval: "5m",
Agent: "witness",
},
"refinery": {
Enabled: true,
Interval: "5m",
Agent: "refinery",
},
},
}
}
// DeaconConfig represents deacon process settings.
type DeaconConfig struct {
PatrolInterval string `json:"patrol_interval,omitempty"` // e.g., "5m"
@@ -113,10 +170,10 @@ const CurrentRigSettingsVersion = 1
// RigConfig represents per-rig identity (rig/config.json).
// This contains only identity - behavioral config is in settings/config.json.
type RigConfig struct {
Type string `json:"type"` // "rig"
Version int `json:"version"` // schema version
Name string `json:"name"` // rig name
GitURL string `json:"git_url"` // git repository URL
Type string `json:"type"` // "rig"
Version int `json:"version"` // schema version
Name string `json:"name"` // rig name
GitURL string `json:"git_url"` // git repository URL
LocalRepo string `json:"local_repo,omitempty"`
CreatedAt time.Time `json:"created_at"` // when the rig was created
Beads *BeadsConfig `json:"beads,omitempty"`
@@ -264,8 +321,8 @@ type TownThemeConfig struct {
// These are used when no explicit configuration is provided.
func BuiltinRoleThemes() map[string]string {
return map[string]string{
"witness": "rust", // Red/rust - watchful, alert
"refinery": "plum", // Purple - processing, refining
"witness": "rust", // Red/rust - watchful, alert
"refinery": "plum", // Purple - processing, refining
// crew and polecat use rig theme by default (no override)
}
}