package mining import ( "encoding/json" "testing" "crypto-miner-server/internal/strategy" ) func TestObserveHopFreezesWinner(t *testing.T) { o := NewContingencyOrchestrator(OrchestratorDeps{AIControl: true, Persona: "balanced"}) push, ok := o.ObserveHop("a1", OnionHop{ Method: "inprocess", Outcome: "won", Depth: 3, }) if ok || push.Reason != "" { t.Fatalf("unexpected push on win: ok=%v push=%+v", ok, push) } st, _ := o.State("a1") if st.FrozenMethod != "inprocess" || st.Depth != 3 { t.Fatalf("state=%+v", st) } } func TestObserveHopExhaustionRequestsBranchParams(t *testing.T) { var seerAgent string o := NewContingencyOrchestrator(OrchestratorDeps{ AIControl: true, Persona: "silent", GraftFor: func(agentID string) (*strategy.GraftPolicy, bool) { return &strategy.GraftPolicy{GraftTier: "docker", TierOrder: []string{"docker"}}, true }, OnSeer: func(agentID string, payload map[string]interface{}) { seerAgent = agentID }, }) push, ok := o.ObserveHop("agent-x", OnionHop{ Method: "contingency_tree", Outcome: "exhausted", Exhausted: true, Depth: 8, }) if !ok { t.Fatal("expected branch params push") } if push.ForceMethod != "container" { t.Fatalf("force=%q", push.ForceMethod) } if seerAgent != "agent-x" { t.Fatalf("seer agent=%q", seerAgent) } } func TestParseOnionHop(t *testing.T) { raw, _ := json.Marshal(map[string]interface{}{ "method": "container", "outcome": "trying", "contingency_depth": 2, }) hop, err := ParseOnionHop(raw) if err != nil || hop.Method != "container" || hop.Depth != 2 { t.Fatalf("hop=%+v err=%v", hop, err) } } func TestOrchestratorDisabled(t *testing.T) { o := NewContingencyOrchestrator(OrchestratorDeps{AIControl: false}) _, ok := o.ObserveHop("a", OnionHop{Outcome: "exhausted", Exhausted: true}) if ok { t.Fatal("expected no push when disabled") } }