package config_test

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"testing"

	"iop/packages/go/config"
)

// validSingleRequestYAML is a baseline valid single-request preset YAML used
// by multiple sub-tests. It uses an opaque workspace_ref, bounded limits, and
// the approved plan→work→review stage bindings with high reasoning on selector
// and plan/review, no high reasoning on work.
const validSingleRequestYAML = `
server:
  listen: "0.0.0.0:9090"
models:
  - id: "gemini-plan"
    providers:
      prov-a: "gemini-plan"
  - id: "ornith-fast"
    providers:
      prov-a: "ornith-fast"
  - id: "gemini-review"
    providers:
      prov-a: "gemini-review"
execution_presets:
  - id: "fixed-single-request"
    selector:
      model: "gemini-plan"
      options:
        reasoning_effort: "high"
    allowed_modes:
      - "light"
    routes:
      light:
        stages:
          - role: "plan"
            model: "gemini-plan"
            options:
              reasoning_effort: "high"
          - role: "work"
            model: "ornith-fast"
            options:
              temperature: 0.2
          - role: "review"
            model: "gemini-review"
            options:
              reasoning_effort: "high"
    single_request:
      workspace_ref: "ws-capability-ref-001"
      limits:
        wall_clock_ms: 1800000
        timeout_ms: 600000
        max_tool_iterations: 32
        max_output_bytes: 8388608
      stages:
        plan:
          model: "gemini-plan"
          options:
            reasoning_effort: "high"
        work:
          model: "ornith-fast"
          options:
            temperature: 0.2
        review:
          model: "gemini-review"
          options:
            reasoning_effort: "high"
nodes:
  - id: "node-01"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        models: ["gemini-plan", "ornith-fast", "gemini-review"]
        capacity: 2
`

// TestLoadEdgeSingleRequestExecutionPreset verifies that a valid single-request
// preset decodes, normalizes, and survives LoadEdge alongside ordinary presets.
func TestLoadEdgeSingleRequestExecutionPreset(t *testing.T) {
	dir := t.TempDir()
	f := filepath.Join(dir, "edge.yaml")

	t.Run("valid single-request preset loads", func(t *testing.T) {
		if err := os.WriteFile(f, []byte(validSingleRequestYAML), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		cfg, err := config.LoadEdge(f)
		if err != nil {
			t.Fatalf("load: %v", err)
		}
		if len(cfg.ExecutionPresets) != 1 {
			t.Fatalf("expected 1 preset, got %d", len(cfg.ExecutionPresets))
		}
		p := cfg.ExecutionPresets[0]
		if p.ID != "fixed-single-request" {
			t.Errorf("preset id = %q, want %q", p.ID, "fixed-single-request")
		}
		if p.SingleRequest == nil {
			t.Fatal("expected SingleRequest to be set")
		}
		sr := p.SingleRequest
		if sr.WorkspaceRef != "ws-capability-ref-001" {
			t.Errorf("workspace_ref = %q, want ws-capability-ref-001", sr.WorkspaceRef)
		}
		if sr.Limits.WallClockMS != 1800000 {
			t.Errorf("wall_clock_ms = %d, want 1800000", sr.Limits.WallClockMS)
		}
		if sr.Limits.StageTimeoutMS != 600000 {
			t.Errorf("timeout_ms = %d, want 600000", sr.Limits.StageTimeoutMS)
		}
		if sr.Limits.MaxToolIterations != 32 {
			t.Errorf("max_tool_iterations = %d, want 32", sr.Limits.MaxToolIterations)
		}
		if sr.Limits.MaxOutputBytes != 8388608 {
			t.Errorf("max_output_bytes = %d, want 8388608", sr.Limits.MaxOutputBytes)
		}
		if sr.Stages.Plan.Model != "gemini-plan" {
			t.Errorf("plan model = %q, want gemini-plan", sr.Stages.Plan.Model)
		}
		if sr.Stages.Work.Model != "ornith-fast" {
			t.Errorf("work model = %q, want ornith-fast", sr.Stages.Work.Model)
		}
		if sr.Stages.Review.Model != "gemini-review" {
			t.Errorf("review model = %q, want gemini-review", sr.Stages.Review.Model)
		}
		// Allowed modes must be exactly ["light"].
		if len(p.AllowedModes) != 1 || p.AllowedModes[0] != "light" {
			t.Errorf("allowed_modes = %v, want [light]", p.AllowedModes)
		}
		// Workspace tools must be nil (rejected for single-request).
		if p.WorkspaceTools != nil {
			t.Errorf("workspace_tools = %v, want nil", p.WorkspaceTools)
		}
		// Route must have exactly plan→work→review.
		route := p.Routes["light"]
		if len(route.Stages) != 3 {
			t.Fatalf("expected 3 route stages, got %d", len(route.Stages))
		}
		if route.Stages[0].Role != "plan" || route.Stages[1].Role != "work" || route.Stages[2].Role != "review" {
			t.Errorf("route stages roles = %v, want [plan, work, review]", routeStagesRoles(route.Stages))
		}
	})

	t.Run("exact cap values load", func(t *testing.T) {
		yaml := singleRequestYAMLWithLimits(
			config.MaxSingleRequestWallClockMS,
			config.MaxSingleRequestStageTimeoutMS,
			config.MaxSingleRequestToolIterations,
			config.MaxSingleRequestOutputBytes,
		)
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		cfg, err := config.LoadEdge(f)
		if err != nil {
			t.Fatalf("load: %v", err)
		}
		p := cfg.ExecutionPresets[0]
		sr := p.SingleRequest
		if sr.Limits.WallClockMS != config.MaxSingleRequestWallClockMS {
			t.Errorf("wall_clock_ms = %d, want %d", sr.Limits.WallClockMS, config.MaxSingleRequestWallClockMS)
		}
		if sr.Limits.StageTimeoutMS != config.MaxSingleRequestStageTimeoutMS {
			t.Errorf("timeout_ms = %d, want %d", sr.Limits.StageTimeoutMS, config.MaxSingleRequestStageTimeoutMS)
		}
		if sr.Limits.MaxToolIterations != config.MaxSingleRequestToolIterations {
			t.Errorf("max_tool_iterations = %d, want %d", sr.Limits.MaxToolIterations, config.MaxSingleRequestToolIterations)
		}
		if sr.Limits.MaxOutputBytes != config.MaxSingleRequestOutputBytes {
			t.Errorf("max_output_bytes = %d, want %d", sr.Limits.MaxOutputBytes, config.MaxSingleRequestOutputBytes)
		}
	})

	t.Run("minimum limit values load", func(t *testing.T) {
		yaml := singleRequestYAMLWithLimits(1, 1, 1, 1)
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		cfg, err := config.LoadEdge(f)
		if err != nil {
			t.Fatalf("load: %v", err)
		}
		p := cfg.ExecutionPresets[0]
		sr := p.SingleRequest
		if sr.Limits.WallClockMS != 1 || sr.Limits.StageTimeoutMS != 1 ||
			sr.Limits.MaxToolIterations != 1 || sr.Limits.MaxOutputBytes != 1 {
			t.Errorf("limits = %+v, want all 1", sr.Limits)
		}
	})

	t.Run("single-request preset coexists with ordinary presets", func(t *testing.T) {
		yaml := `
server:
  listen: "0.0.0.0:9090"
models:
  - id: "model-a"
    providers:
      prov-a: "model-a"
  - id: "model-b"
    providers:
      prov-a: "model-b"
  - id: "gemini-plan"
    providers:
      prov-a: "gemini-plan"
  - id: "ornith-fast"
    providers:
      prov-a: "ornith-fast"
  - id: "gemini-review"
    providers:
      prov-a: "gemini-review"
execution_presets:
  - id: "direct-default"
    selector:
      model: "model-a"
    allowed_modes:
      - "direct"
    routes:
      direct:
        stages: []
  - id: "fixed-single-request"
    selector:
      model: "gemini-plan"
      options:
        reasoning_effort: "high"
    allowed_modes:
      - "light"
    routes:
      light:
        stages:
          - role: "plan"
            model: "gemini-plan"
            options:
              reasoning_effort: "high"
          - role: "work"
            model: "ornith-fast"
          - role: "review"
            model: "gemini-review"
            options:
              reasoning_effort: "high"
    single_request:
      workspace_ref: "ws-capability-ref-002"
      limits:
        wall_clock_ms: 300000
        timeout_ms: 120000
        max_tool_iterations: 16
        max_output_bytes: 4194304
      stages:
        plan:
          model: "gemini-plan"
          options:
            reasoning_effort: "high"
        work:
          model: "ornith-fast"
        review:
          model: "gemini-review"
          options:
            reasoning_effort: "high"
nodes:
  - id: "node-01"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        models: ["model-a", "model-b", "gemini-plan", "ornith-fast", "gemini-review"]
        capacity: 2
`
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		cfg, err := config.LoadEdge(f)
		if err != nil {
			t.Fatalf("load: %v", err)
		}
		if len(cfg.ExecutionPresets) != 2 {
			t.Fatalf("expected 2 presets, got %d", len(cfg.ExecutionPresets))
		}
		byID := map[string]config.ExecutionPreset{}
		for _, p := range cfg.ExecutionPresets {
			byID[p.ID] = p
		}
		if _, ok := byID["direct-default"]; !ok {
			t.Fatal("expected direct-default preset")
		}
		if _, ok := byID["fixed-single-request"]; !ok {
			t.Fatal("expected fixed-single-request preset")
		}
		// Ordinary preset must not have SingleRequest set.
		if byID["direct-default"].SingleRequest != nil {
			t.Error("direct-default should not have SingleRequest set")
		}
		// Single-request preset must not have workspace_tools.
		if byID["fixed-single-request"].WorkspaceTools != nil {
			t.Error("fixed-single-request should not have workspace_tools")
		}
	})
}

// TestLoadEdgeSingleRequestExecutionPresetRejectsDivergentEffectiveBindings verifies that every
// single-request role (plan/work/review) fails closed when route and single_request bindings diverge.
func TestLoadEdgeSingleRequestExecutionPresetRejectsDivergentEffectiveBindings(t *testing.T) {
	dir := t.TempDir()
	f := filepath.Join(dir, "edge.yaml")

	const (
		planOptions        = "\n            options:\n              reasoning_effort: \"high\""
		workOptions        = ""
		reviewOptions      = "\n            options:\n              reasoning_effort: \"high\""
		planLeakOptions    = "\n            options:\n              reasoning_effort: \"high\"\n              temperature: 0.8"
		workRouteLeakModel = "\n            options:\n              temperature: 0.8"
		workRouteLeakMatch = "\n          options:\n            temperature: 0.2"
		workReasoningLeak  = "\n            options:\n              reasoning_effort: \"high\""
	)

	for _, tc := range []struct {
		name       string
		yaml       string
		wantErrors []string
	}{
		{
			name:       "plan route stage model must match single_request plan stage",
			yaml:       singleRequestYAMLWithRouteBindingDiff("gemini-review", "ornith-fast", "gemini-review", planOptions, workOptions, reviewOptions, ""),
			wantErrors: []string{"single_request preset light route stage[0] role=\"plan\" binding must match single_request stage"},
		},
		{
			name:       "work route stage model must match single_request work stage",
			yaml:       singleRequestYAMLWithRouteBindingDiff("gemini-plan", "gemini-review", "gemini-review", planOptions, workOptions, reviewOptions, ""),
			wantErrors: []string{"single_request preset light route stage[1] role=\"work\" binding must match single_request stage"},
		},
		{
			name:       "review route stage model must match single_request review stage",
			yaml:       singleRequestYAMLWithRouteBindingDiff("gemini-plan", "ornith-fast", "gemini-plan", planOptions, workOptions, reviewOptions, ""),
			wantErrors: []string{"single_request preset light route stage[2] role=\"review\" binding must match single_request stage"},
		},
		{
			name:       "plan route option mismatch must be rejected",
			yaml:       singleRequestYAMLWithRouteBindingDiff("gemini-plan", "ornith-fast", "gemini-review", planLeakOptions, workOptions, reviewOptions, ""),
			wantErrors: []string{"single_request preset light route stage[0] role=\"plan\" binding must match single_request stage"},
		},
		{
			name:       "work route option mismatch must be rejected",
			yaml:       singleRequestYAMLWithRouteBindingDiff("gemini-plan", "ornith-fast", "gemini-review", planOptions, workRouteLeakModel, reviewOptions, workRouteLeakMatch),
			wantErrors: []string{"single_request preset light route stage[1] role=\"work\" binding must match single_request stage"},
		},
		{
			name:       "review route option mismatch must be rejected",
			yaml:       singleRequestYAMLWithRouteBindingDiff("gemini-plan", "ornith-fast", "gemini-review", planOptions, workOptions, planLeakOptions, ""),
			wantErrors: []string{"single_request preset light route stage[2] role=\"review\" binding must match single_request stage"},
		},
		{
			name:       "route-only dangling model must be rejected",
			yaml:       singleRequestYAMLWithRouteBindingDiff("gemini-plan", "dangling-model-id", "gemini-review", planOptions, workOptions, reviewOptions, ""),
			wantErrors: []string{"single_request preset light route stage[1] role=\"work\" model", "not found in models catalog"},
		},
		{
			name:       "route-only work reasoning_effort leakage must be rejected",
			yaml:       singleRequestYAMLWithRouteBindingDiff("gemini-plan", "ornith-fast", "gemini-review", planOptions, workReasoningLeak, reviewOptions, ""),
			wantErrors: []string{"single_request preset light route stage[1] role=\"work\" binding must match single_request stage"},
		},
	} {
		t.Run(tc.name, func(t *testing.T) {
			requireSingleRequestLoadError(t, f, tc.yaml, tc.wantErrors...)
		})
	}
}

// TestLoadEdgeSingleRequestExecutionPresetRejectsInvalidShape verifies that
// invalid single-request shapes fail closed with descriptive errors.
func TestLoadEdgeSingleRequestExecutionPresetRejectsInvalidShape(t *testing.T) {
	dir := t.TempDir()
	f := filepath.Join(dir, "edge.yaml")

	t.Run("empty workspace_ref rejected", func(t *testing.T) {
		yaml := srYAMLWithWorkspaceRef("", 300000, 120000, 16, 4194304)
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for empty workspace_ref")
		}
		if !strings.Contains(err.Error(), "workspace_ref must not be empty") {
			t.Fatalf("expected error mentioning workspace_ref must not be empty, got %v", err)
		}
	})

	t.Run("zero wall_clock_ms rejected", func(t *testing.T) {
		yaml := srYAMLWithWorkspaceRef("ws-ref", 0, 120000, 16, 4194304)
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for zero wall_clock_ms")
		}
		if !strings.Contains(err.Error(), "wall_clock_ms must be in") {
			t.Fatalf("expected error mentioning wall_clock_ms range, got %v", err)
		}
	})

	t.Run("wall_clock_ms over cap rejected", func(t *testing.T) {
		yaml := srYAMLWithWorkspaceRef("ws-ref", config.MaxSingleRequestWallClockMS+1, 120000, 16, 4194304)
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for wall_clock_ms over cap")
		}
		if !strings.Contains(err.Error(), "wall_clock_ms must be in") {
			t.Fatalf("expected error mentioning wall_clock_ms range, got %v", err)
		}
	})

	t.Run("zero timeout_ms rejected", func(t *testing.T) {
		yaml := srYAMLWithWorkspaceRef("ws-ref", 300000, 0, 16, 4194304)
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for zero timeout_ms")
		}
		if !strings.Contains(err.Error(), "timeout_ms must be in") {
			t.Fatalf("expected error mentioning timeout_ms range, got %v", err)
		}
	})

	t.Run("timeout_ms over cap rejected", func(t *testing.T) {
		yaml := srYAMLWithWorkspaceRef("ws-ref", 300000, config.MaxSingleRequestStageTimeoutMS+1, 16, 4194304)
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for timeout_ms over cap")
		}
		if !strings.Contains(err.Error(), "timeout_ms must be in") {
			t.Fatalf("expected error mentioning timeout_ms range, got %v", err)
		}
	})

	t.Run("timeout_ms greater than wall_clock_ms rejected", func(t *testing.T) {
		yaml := srYAMLWithWorkspaceRef("ws-ref", 100000, 200000, 16, 4194304)
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for timeout_ms > wall_clock_ms")
		}
		if !strings.Contains(err.Error(), "must not exceed wall_clock_ms") {
			t.Fatalf("expected error mentioning must not exceed wall_clock_ms, got %v", err)
		}
	})

	t.Run("legacy wall_clock_sec key rejected", func(t *testing.T) {
		yaml := `server:
  listen: "0.0.0.0:9090"
models:
  - id: "gemini-plan"
    providers:
      prov-a: "gemini-plan"
  - id: "ornith-fast"
    providers:
      prov-a: "ornith-fast"
  - id: "gemini-review"
    providers:
      prov-a: "gemini-review"
execution_presets:
  - id: "fixed-single-request"
    selector:
      model: "gemini-plan"
      options:
        reasoning_effort: "high"
    allowed_modes:
      - "light"
    routes:
      light:
        stages:
          - role: "plan"
            model: "gemini-plan"
            options:
              reasoning_effort: "high"
          - role: "work"
            model: "ornith-fast"
          - role: "review"
            model: "gemini-review"
            options:
              reasoning_effort: "high"
    single_request:
      workspace_ref: "ws-ref"
      limits:
        wall_clock_sec: 1800
        timeout_ms: 600000
        max_tool_iterations: 16
        max_output_bytes: 4194304
      stages:
        plan:
          model: "gemini-plan"
          options:
            reasoning_effort: "high"
        work:
          model: "ornith-fast"
        review:
          model: "gemini-review"
          options:
            reasoning_effort: "high"
nodes:
  - id: "node-01"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        models: ["gemini-plan", "ornith-fast", "gemini-review"]
        capacity: 2
`
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for legacy wall_clock_sec key")
		}
		if !strings.Contains(err.Error(), "invalid keys") && !strings.Contains(err.Error(), "unknown fields") {
			t.Fatalf("expected error mentioning invalid keys or unknown fields, got %v", err)
		}
	})

	t.Run("legacy stage_timeout_sec key rejected", func(t *testing.T) {
		yaml := `server:
  listen: "0.0.0.0:9090"
models:
  - id: "gemini-plan"
    providers:
      prov-a: "gemini-plan"
  - id: "ornith-fast"
    providers:
      prov-a: "ornith-fast"
  - id: "gemini-review"
    providers:
      prov-a: "gemini-review"
execution_presets:
  - id: "fixed-single-request"
    selector:
      model: "gemini-plan"
      options:
        reasoning_effort: "high"
    allowed_modes:
      - "light"
    routes:
      light:
        stages:
          - role: "plan"
            model: "gemini-plan"
            options:
              reasoning_effort: "high"
          - role: "work"
            model: "ornith-fast"
          - role: "review"
            model: "gemini-review"
            options:
              reasoning_effort: "high"
    single_request:
      workspace_ref: "ws-ref"
      limits:
        wall_clock_ms: 300000
        stage_timeout_sec: 1800
        timeout_ms: 600000
        max_tool_iterations: 16
        max_output_bytes: 4194304
      stages:
        plan:
          model: "gemini-plan"
          options:
            reasoning_effort: "high"
        work:
          model: "ornith-fast"
        review:
          model: "gemini-review"
          options:
            reasoning_effort: "high"
nodes:
  - id: "node-01"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        models: ["gemini-plan", "ornith-fast", "gemini-review"]
        capacity: 2
`
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for legacy stage_timeout_sec key")
		}
		if !strings.Contains(err.Error(), "invalid keys") && !strings.Contains(err.Error(), "unknown fields") {
			t.Fatalf("expected error mentioning invalid keys or unknown fields, got %v", err)
		}
		if !strings.Contains(err.Error(), "stage_timeout_sec") {
			t.Fatalf("expected error mentioning stage_timeout_sec, got %v", err)
		}
	})

	t.Run("zero max_tool_iterations rejected", func(t *testing.T) {
		yaml := srYAMLWithWorkspaceRef("ws-ref", 300000, 120000, 0, 4194304)
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for zero max_tool_iterations")
		}
		if !strings.Contains(err.Error(), "max_tool_iterations must be in") {
			t.Fatalf("expected error mentioning max_tool_iterations range, got %v", err)
		}
	})

	t.Run("max_tool_iterations over cap rejected", func(t *testing.T) {
		yaml := srYAMLWithWorkspaceRef("ws-ref", 300000, 120000, config.MaxSingleRequestToolIterations+1, 4194304)
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for max_tool_iterations over cap")
		}
		if !strings.Contains(err.Error(), "max_tool_iterations must be in") {
			t.Fatalf("expected error mentioning max_tool_iterations range, got %v", err)
		}
	})

	t.Run("zero max_output_bytes rejected", func(t *testing.T) {
		yaml := srYAMLWithWorkspaceRef("ws-ref", 300000, 120000, 16, 0)
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for zero max_output_bytes")
		}
		if !strings.Contains(err.Error(), "max_output_bytes must be in") {
			t.Fatalf("expected error mentioning max_output_bytes range, got %v", err)
		}
	})

	t.Run("max_output_bytes over cap rejected", func(t *testing.T) {
		yaml := srYAMLWithWorkspaceRef("ws-ref", 300000, 120000, 16, config.MaxSingleRequestOutputBytes+1)
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for max_output_bytes over cap")
		}
		if !strings.Contains(err.Error(), "max_output_bytes must be in") {
			t.Fatalf("expected error mentioning max_output_bytes range, got %v", err)
		}
	})

	t.Run("empty plan model rejected", func(t *testing.T) {
		yaml := srYAMLWithPlanModel("", 300000, 120000, 16, 4194304)
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for empty plan model")
		}
		if !strings.Contains(err.Error(), "plan.model must not be empty") {
			t.Fatalf("expected error mentioning plan.model must not be empty, got %v", err)
		}
	})

	t.Run("empty work model rejected", func(t *testing.T) {
		yaml := srYAMLWithWorkModel("", 300000, 120000, 16, 4194304)
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for empty work model")
		}
		if !strings.Contains(err.Error(), "work.model must not be empty") {
			t.Fatalf("expected error mentioning work.model must not be empty, got %v", err)
		}
	})

	t.Run("empty review model rejected", func(t *testing.T) {
		yaml := srYAMLWithReviewModel("", 300000, 120000, 16, 4194304)
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for empty review model")
		}
		if !strings.Contains(err.Error(), "review.model must not be empty") {
			t.Fatalf("expected error mentioning review.model must not be empty, got %v", err)
		}
	})

	t.Run("dangling stage model rejected", func(t *testing.T) {
		yaml := srYAMLWithWorkModel("non-existent-model", 300000, 120000, 16, 4194304)
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for dangling stage model")
		}
		if !strings.Contains(err.Error(), "not found in models catalog") {
			t.Fatalf("expected error mentioning not found in models catalog, got %v", err)
		}
	})

	t.Run("divergent route stage model rejected", func(t *testing.T) {
		// Route work stage model ("gemini-plan") differs from single_request work stage model ("ornith-fast").
		yaml := `server:
  listen: "0.0.0.0:9090"
models:
  - id: "gemini-plan"
    providers:
      prov-a: "gemini-plan"
  - id: "ornith-fast"
    providers:
      prov-a: "ornith-fast"
  - id: "gemini-review"
    providers:
      prov-a: "gemini-review"
execution_presets:
  - id: "fixed-single-request"
    selector:
      model: "gemini-plan"
      options:
        reasoning_effort: "high"
    allowed_modes:
      - "light"
    routes:
      light:
        stages:
          - role: "plan"
            model: "gemini-plan"
            options:
              reasoning_effort: "high"
          - role: "work"
            model: "gemini-plan"
          - role: "review"
            model: "gemini-review"
            options:
              reasoning_effort: "high"
    single_request:
      workspace_ref: "ws-ref"
      limits:
        wall_clock_ms: 300000
        timeout_ms: 120000
        max_tool_iterations: 16
        max_output_bytes: 4194304
      stages:
        plan:
          model: "gemini-plan"
          options:
            reasoning_effort: "high"
        work:
          model: "ornith-fast"
        review:
          model: "gemini-review"
          options:
            reasoning_effort: "high"
nodes:
  - id: "node-01"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        models: ["gemini-plan", "ornith-fast", "gemini-review"]
        capacity: 2
`
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for divergent route stage model")
		}
		if !strings.Contains(err.Error(), "binding must match single_request stage") {
			t.Fatalf("expected error mentioning binding must match single_request stage, got %v", err)
		}
	})

	t.Run("divergent route stage options rejected", func(t *testing.T) {
		// Route work stage has temperature 0.8, single_request work stage has temperature 0.2.
		yaml := `server:
  listen: "0.0.0.0:9090"
models:
  - id: "gemini-plan"
    providers:
      prov-a: "gemini-plan"
  - id: "ornith-fast"
    providers:
      prov-a: "ornith-fast"
  - id: "gemini-review"
    providers:
      prov-a: "gemini-review"
execution_presets:
  - id: "fixed-single-request"
    selector:
      model: "gemini-plan"
      options:
        reasoning_effort: "high"
    allowed_modes:
      - "light"
    routes:
      light:
        stages:
          - role: "plan"
            model: "gemini-plan"
            options:
              reasoning_effort: "high"
          - role: "work"
            model: "ornith-fast"
            options:
              temperature: 0.8
          - role: "review"
            model: "gemini-review"
            options:
              reasoning_effort: "high"
    single_request:
      workspace_ref: "ws-ref"
      limits:
        wall_clock_ms: 300000
        timeout_ms: 120000
        max_tool_iterations: 16
        max_output_bytes: 4194304
      stages:
        plan:
          model: "gemini-plan"
          options:
            reasoning_effort: "high"
        work:
          model: "ornith-fast"
          options:
            temperature: 0.2
        review:
          model: "gemini-review"
          options:
            reasoning_effort: "high"
nodes:
  - id: "node-01"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        models: ["gemini-plan", "ornith-fast", "gemini-review"]
        capacity: 2
`
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for divergent route stage options")
		}
		if !strings.Contains(err.Error(), "binding must match single_request stage") {
			t.Fatalf("expected error mentioning binding must match single_request stage, got %v", err)
		}
	})

	t.Run("dangling route stage model rejected", func(t *testing.T) {
		yaml := `server:
  listen: "0.0.0.0:9090"
models:
  - id: "gemini-plan"
    providers:
      prov-a: "gemini-plan"
  - id: "ornith-fast"
    providers:
      prov-a: "ornith-fast"
  - id: "gemini-review"
    providers:
      prov-a: "gemini-review"
execution_presets:
  - id: "fixed-single-request"
    selector:
      model: "gemini-plan"
      options:
        reasoning_effort: "high"
    allowed_modes:
      - "light"
    routes:
      light:
        stages:
          - role: "plan"
            model: "gemini-plan"
            options:
              reasoning_effort: "high"
          - role: "work"
            model: "dangling-model-id"
          - role: "review"
            model: "gemini-review"
            options:
              reasoning_effort: "high"
    single_request:
      workspace_ref: "ws-ref"
      limits:
        wall_clock_ms: 300000
        timeout_ms: 120000
        max_tool_iterations: 16
        max_output_bytes: 4194304
      stages:
        plan:
          model: "gemini-plan"
          options:
            reasoning_effort: "high"
        work:
          model: "dangling-model-id"
        review:
          model: "gemini-review"
          options:
            reasoning_effort: "high"
nodes:
  - id: "node-01"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        models: ["gemini-plan", "ornith-fast", "gemini-review"]
        capacity: 2
`
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for dangling route stage model")
		}
		if !strings.Contains(err.Error(), "not found in models catalog") {
			t.Fatalf("expected error mentioning not found in models catalog, got %v", err)
		}
	})

	t.Run("divergent selector model rejected", func(t *testing.T) {
		yaml := `server:
  listen: "0.0.0.0:9090"
models:
  - id: "gemini-plan"
    providers:
      prov-a: "gemini-plan"
  - id: "ornith-fast"
    providers:
      prov-a: "ornith-fast"
  - id: "gemini-review"
    providers:
      prov-a: "gemini-review"
execution_presets:
  - id: "fixed-single-request"
    selector:
      model: "ornith-fast"
      options:
        reasoning_effort: "high"
    allowed_modes:
      - "light"
    routes:
      light:
        stages:
          - role: "plan"
            model: "gemini-plan"
            options:
              reasoning_effort: "high"
          - role: "work"
            model: "ornith-fast"
          - role: "review"
            model: "gemini-review"
            options:
              reasoning_effort: "high"
    single_request:
      workspace_ref: "ws-ref"
      limits:
        wall_clock_ms: 300000
        timeout_ms: 120000
        max_tool_iterations: 16
        max_output_bytes: 4194304
      stages:
        plan:
          model: "gemini-plan"
          options:
            reasoning_effort: "high"
        work:
          model: "ornith-fast"
        review:
          model: "gemini-review"
          options:
            reasoning_effort: "high"
nodes:
  - id: "node-01"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        models: ["gemini-plan", "ornith-fast", "gemini-review"]
        capacity: 2
`
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for divergent selector model")
		}
		if !strings.Contains(err.Error(), "selector binding must match single_request plan stage") {
			t.Fatalf("expected error mentioning selector binding must match single_request plan stage, got %v", err)
		}
	})

	t.Run("missing high reasoning on selector rejected", func(t *testing.T) {
		yaml := `server:
  listen: "0.0.0.0:9090"
models:
  - id: "gemini-plan"
    providers:
      prov-a: "gemini-plan"
  - id: "ornith-fast"
    providers:
      prov-a: "ornith-fast"
  - id: "gemini-review"
    providers:
      prov-a: "gemini-review"
execution_presets:
  - id: "fixed-single-request"
    selector:
      model: "gemini-plan"
    allowed_modes:
      - "light"
    routes:
      light:
        stages:
          - role: "plan"
            model: "gemini-plan"
            options:
              reasoning_effort: "high"
          - role: "work"
            model: "ornith-fast"
          - role: "review"
            model: "gemini-review"
            options:
              reasoning_effort: "high"
    single_request:
      workspace_ref: "ws-ref"
      limits:
        wall_clock_ms: 300000
        timeout_ms: 120000
        max_tool_iterations: 16
        max_output_bytes: 4194304
      stages:
        plan:
          model: "gemini-plan"
          options:
            reasoning_effort: "high"
        work:
          model: "ornith-fast"
        review:
          model: "gemini-review"
          options:
            reasoning_effort: "high"
nodes:
  - id: "node-01"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        models: ["gemini-plan", "ornith-fast", "gemini-review"]
        capacity: 2
`
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for missing high reasoning on selector")
		}
		if !strings.Contains(err.Error(), "selector.options must have reasoning_effort") {
			t.Fatalf("expected error mentioning selector.options reasoning_effort, got %v", err)
		}
	})

	t.Run("high reasoning on work stage rejected", func(t *testing.T) {
		yaml := `server:
  listen: "0.0.0.0:9090"
models:
  - id: "gemini-plan"
    providers:
      prov-a: "gemini-plan"
  - id: "ornith-fast"
    providers:
      prov-a: "ornith-fast"
  - id: "gemini-review"
    providers:
      prov-a: "gemini-review"
execution_presets:
  - id: "fixed-single-request"
    selector:
      model: "gemini-plan"
      options:
        reasoning_effort: "high"
    allowed_modes:
      - "light"
    routes:
      light:
        stages:
          - role: "plan"
            model: "gemini-plan"
            options:
              reasoning_effort: "high"
          - role: "work"
            model: "ornith-fast"
            options:
              reasoning_effort: "high"
          - role: "review"
            model: "gemini-review"
            options:
              reasoning_effort: "high"
    single_request:
      workspace_ref: "ws-ref"
      limits:
        wall_clock_ms: 300000
        timeout_ms: 120000
        max_tool_iterations: 16
        max_output_bytes: 4194304
      stages:
        plan:
          model: "gemini-plan"
          options:
            reasoning_effort: "high"
        work:
          model: "ornith-fast"
          options:
            reasoning_effort: "high"
        review:
          model: "gemini-review"
          options:
            reasoning_effort: "high"
nodes:
  - id: "node-01"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        models: ["gemini-plan", "ornith-fast", "gemini-review"]
        capacity: 2
`
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for high reasoning on work stage")
		}
		if !strings.Contains(err.Error(), "work.options must not declare reasoning_effort") {
			t.Fatalf("expected error mentioning work.options must not declare reasoning_effort, got %v", err)
		}
	})

	t.Run("medium reasoning on work stage rejected", func(t *testing.T) {
		yaml := `server:
  listen: "0.0.0.0:9090"
models:
  - id: "gemini-plan"
    providers:
      prov-a: "gemini-plan"
  - id: "ornith-fast"
    providers:
      prov-a: "ornith-fast"
  - id: "gemini-review"
    providers:
      prov-a: "gemini-review"
execution_presets:
  - id: "fixed-single-request"
    selector:
      model: "gemini-plan"
      options:
        reasoning_effort: "high"
    allowed_modes:
      - "light"
    routes:
      light:
        stages:
          - role: "plan"
            model: "gemini-plan"
            options:
              reasoning_effort: "high"
          - role: "work"
            model: "ornith-fast"
            options:
              reasoning_effort: "medium"
          - role: "review"
            model: "gemini-review"
            options:
              reasoning_effort: "high"
    single_request:
      workspace_ref: "ws-ref"
      limits:
        wall_clock_ms: 300000
        timeout_ms: 120000
        max_tool_iterations: 16
        max_output_bytes: 4194304
      stages:
        plan:
          model: "gemini-plan"
          options:
            reasoning_effort: "high"
        work:
          model: "ornith-fast"
          options:
            reasoning_effort: "medium"
        review:
          model: "gemini-review"
          options:
            reasoning_effort: "high"
nodes:
  - id: "node-01"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        models: ["gemini-plan", "ornith-fast", "gemini-review"]
        capacity: 2
`
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for medium reasoning on work stage")
		}
		if !strings.Contains(err.Error(), "work.options must not declare reasoning_effort") {
			t.Fatalf("expected error mentioning work.options must not declare reasoning_effort, got %v", err)
		}
	})

	t.Run("non-string reasoning on work stage rejected", func(t *testing.T) {
		yaml := `server:
  listen: "0.0.0.0:9090"
models:
  - id: "gemini-plan"
    providers:
      prov-a: "gemini-plan"
  - id: "ornith-fast"
    providers:
      prov-a: "ornith-fast"
  - id: "gemini-review"
    providers:
      prov-a: "gemini-review"
execution_presets:
  - id: "fixed-single-request"
    selector:
      model: "gemini-plan"
      options:
        reasoning_effort: "high"
    allowed_modes:
      - "light"
    routes:
      light:
        stages:
          - role: "plan"
            model: "gemini-plan"
            options:
              reasoning_effort: "high"
          - role: "work"
            model: "ornith-fast"
            options:
              reasoning_effort: 10
          - role: "review"
            model: "gemini-review"
            options:
              reasoning_effort: "high"
    single_request:
      workspace_ref: "ws-ref"
      limits:
        wall_clock_ms: 300000
        timeout_ms: 120000
        max_tool_iterations: 16
        max_output_bytes: 4194304
      stages:
        plan:
          model: "gemini-plan"
          options:
            reasoning_effort: "high"
        work:
          model: "ornith-fast"
          options:
            reasoning_effort: 10
        review:
          model: "gemini-review"
          options:
            reasoning_effort: "high"
nodes:
  - id: "node-01"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        models: ["gemini-plan", "ornith-fast", "gemini-review"]
        capacity: 2
`
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for non-string reasoning on work stage")
		}
		if !strings.Contains(err.Error(), "work.options must not declare reasoning_effort") {
			t.Fatalf("expected error mentioning work.options must not declare reasoning_effort, got %v", err)
		}
	})

	t.Run("missing high reasoning on review rejected", func(t *testing.T) {
		yaml := `server:
  listen: "0.0.0.0:9090"
models:
  - id: "gemini-plan"
    providers:
      prov-a: "gemini-plan"
  - id: "ornith-fast"
    providers:
      prov-a: "ornith-fast"
  - id: "gemini-review"
    providers:
      prov-a: "gemini-review"
execution_presets:
  - id: "fixed-single-request"
    selector:
      model: "gemini-plan"
      options:
        reasoning_effort: "high"
    allowed_modes:
      - "light"
    routes:
      light:
        stages:
          - role: "plan"
            model: "gemini-plan"
            options:
              reasoning_effort: "high"
          - role: "work"
            model: "ornith-fast"
          - role: "review"
            model: "gemini-review"
    single_request:
      workspace_ref: "ws-ref"
      limits:
        wall_clock_ms: 300000
        timeout_ms: 120000
        max_tool_iterations: 16
        max_output_bytes: 4194304
      stages:
        plan:
          model: "gemini-plan"
          options:
            reasoning_effort: "high"
        work:
          model: "ornith-fast"
        review:
          model: "gemini-review"
nodes:
  - id: "node-01"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        models: ["gemini-plan", "ornith-fast", "gemini-review"]
        capacity: 2
`
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for missing high reasoning on review")
		}
		if !strings.Contains(err.Error(), "review.options must have reasoning_effort") {
			t.Fatalf("expected error mentioning review.options reasoning_effort, got %v", err)
		}
	})

	t.Run("non-light allowed mode rejected", func(t *testing.T) {
		// Use allowed_modes=["direct"] with a direct route; single_request validation
		// rejects non-light allowed_modes before route checks complete.
		yaml := `server:
  listen: "0.0.0.0:9090"
models:
  - id: "gemini-plan"
    providers:
      prov-a: "gemini-plan"
  - id: "ornith-fast"
    providers:
      prov-a: "ornith-fast"
  - id: "gemini-review"
    providers:
      prov-a: "gemini-review"
execution_presets:
  - id: "fixed-single-request"
    selector:
      model: "gemini-plan"
      options:
        reasoning_effort: "high"
    allowed_modes:
      - "direct"
    routes:
      direct:
        stages: []
    single_request:
      workspace_ref: "ws-ref"
      limits:
        wall_clock_ms: 300000
        timeout_ms: 120000
        max_tool_iterations: 16
        max_output_bytes: 4194304
      stages:
        plan:
          model: "gemini-plan"
          options:
            reasoning_effort: "high"
        work:
          model: "ornith-fast"
        review:
          model: "gemini-review"
          options:
            reasoning_effort: "high"
nodes:
  - id: "node-01"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        models: ["gemini-plan", "ornith-fast", "gemini-review"]
        capacity: 2
`
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for non-light allowed mode")
		}
		if !strings.Contains(err.Error(), "allowed_modes must be exactly") {
			t.Fatalf("expected error mentioning allowed_modes must be exactly, got %v", err)
		}
	})

	t.Run("direct+light allowed modes rejected", func(t *testing.T) {
		// allowed_modes=["direct", "light"] with both routes; single_request rejects
		// because allowed_modes is not exactly ["light"].
		yaml := `server:
  listen: "0.0.0.0:9090"
models:
  - id: "gemini-plan"
    providers:
      prov-a: "gemini-plan"
  - id: "ornith-fast"
    providers:
      prov-a: "ornith-fast"
  - id: "gemini-review"
    providers:
      prov-a: "gemini-review"
execution_presets:
  - id: "fixed-single-request"
    selector:
      model: "gemini-plan"
      options:
        reasoning_effort: "high"
    allowed_modes:
      - "direct"
      - "light"
    routes:
      direct:
        stages: []
      light:
        stages:
          - role: "plan"
            model: "gemini-plan"
            options:
              reasoning_effort: "high"
          - role: "work"
            model: "ornith-fast"
          - role: "review"
            model: "gemini-review"
            options:
              reasoning_effort: "high"
    single_request:
      workspace_ref: "ws-ref"
      limits:
        wall_clock_ms: 300000
        timeout_ms: 120000
        max_tool_iterations: 16
        max_output_bytes: 4194304
      stages:
        plan:
          model: "gemini-plan"
          options:
            reasoning_effort: "high"
        work:
          model: "ornith-fast"
        review:
          model: "gemini-review"
          options:
            reasoning_effort: "high"
nodes:
  - id: "node-01"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        models: ["gemini-plan", "ornith-fast", "gemini-review"]
        capacity: 2
`
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for direct+light allowed modes")
		}
		if !strings.Contains(err.Error(), "allowed_modes must be exactly") {
			t.Fatalf("expected error mentioning allowed_modes must be exactly, got %v", err)
		}
	})

	t.Run("workspace_tools with single_request rejected", func(t *testing.T) {
		yaml := `server:
  listen: "0.0.0.0:9090"
models:
  - id: "gemini-plan"
    providers:
      prov-a: "gemini-plan"
  - id: "ornith-fast"
    providers:
      prov-a: "ornith-fast"
  - id: "gemini-review"
    providers:
      prov-a: "gemini-review"
execution_presets:
  - id: "fixed-single-request"
    selector:
      model: "gemini-plan"
      options:
        reasoning_effort: "high"
    allowed_modes:
      - "light"
    routes:
      light:
        stages:
          - role: "plan"
            model: "gemini-plan"
            options:
              reasoning_effort: "high"
          - role: "work"
            model: "ornith-fast"
          - role: "review"
            model: "gemini-review"
            options:
              reasoning_effort: "high"
    single_request:
      workspace_ref: "ws-ref"
      limits:
        wall_clock_ms: 300000
        timeout_ms: 120000
        max_tool_iterations: 16
        max_output_bytes: 4194304
      stages:
        plan:
          model: "gemini-plan"
          options:
            reasoning_effort: "high"
        work:
          model: "ornith-fast"
        review:
          model: "gemini-review"
          options:
            reasoning_effort: "high"
    workspace_tools:
      - name: "ws1"
        operations:
          read:
            tool_name: "cat"
            schema_matcher:
              type: "object"
            argument_map:
              path: "path"
            result_matcher:
              status: "ok"
          write:
            tool_name: "tee"
            creates_parents: true
            schema_matcher:
              type: "object"
            argument_map:
              path: "path"
            result_matcher:
              status: "ok"
          delete:
            tool_name: "rm"
            schema_matcher:
              type: "object"
            argument_map:
              path: "path"
            result_matcher:
              status: "ok"
nodes:
  - id: "node-01"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        models: ["gemini-plan", "ornith-fast", "gemini-review"]
        capacity: 2
`
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for workspace_tools with single_request")
		}
		if !strings.Contains(err.Error(), "workspace_tools") && !strings.Contains(err.Error(), "single_request") {
			t.Fatalf("expected error mentioning workspace_tools or single_request, got %v", err)
		}
	})

	t.Run("wrong route stage order rejected", func(t *testing.T) {
		// Swap plan and review roles in the light route stages only.
		// The single_request stages still have correct roles, but the route is wrong.
		yaml := `server:
  listen: "0.0.0.0:9090"
models:
  - id: "gemini-plan"
    providers:
      prov-a: "gemini-plan"
  - id: "ornith-fast"
    providers:
      prov-a: "ornith-fast"
  - id: "gemini-review"
    providers:
      prov-a: "gemini-review"
execution_presets:
  - id: "fixed-single-request"
    selector:
      model: "gemini-plan"
      options:
        reasoning_effort: "high"
    allowed_modes:
      - "light"
    routes:
      light:
        stages:
          - role: "review"
            model: "gemini-review"
            options:
              reasoning_effort: "high"
          - role: "work"
            model: "ornith-fast"
          - role: "plan"
            model: "gemini-plan"
            options:
              reasoning_effort: "high"
    single_request:
      workspace_ref: "ws-ref"
      limits:
        wall_clock_ms: 300000
        timeout_ms: 120000
        max_tool_iterations: 16
        max_output_bytes: 4194304
      stages:
        plan:
          model: "gemini-plan"
          options:
            reasoning_effort: "high"
        work:
          model: "ornith-fast"
        review:
          model: "gemini-review"
          options:
            reasoning_effort: "high"
nodes:
  - id: "node-01"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        models: ["gemini-plan", "ornith-fast", "gemini-review"]
        capacity: 2
`
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for wrong route stage order")
		}
		if !strings.Contains(err.Error(), "stage[0] role is") {
			t.Fatalf("expected error mentioning stage role mismatch, got %v", err)
		}
	})

	t.Run("extra route stage rejected", func(t *testing.T) {
		yaml := `server:
  listen: "0.0.0.0:9090"
models:
  - id: "gemini-plan"
    providers:
      prov-a: "gemini-plan"
  - id: "ornith-fast"
    providers:
      prov-a: "ornith-fast"
  - id: "gemini-review"
    providers:
      prov-a: "gemini-review"
execution_presets:
  - id: "fixed-single-request"
    selector:
      model: "gemini-plan"
      options:
        reasoning_effort: "high"
    allowed_modes:
      - "light"
    routes:
      light:
        stages:
          - role: "plan"
            model: "gemini-plan"
            options:
              reasoning_effort: "high"
          - role: "work"
            model: "ornith-fast"
          - role: "review"
            model: "gemini-review"
            options:
              reasoning_effort: "high"
          - role: "extra"
            model: "gemini-plan"
    single_request:
      workspace_ref: "ws-ref"
      limits:
        wall_clock_ms: 300000
        timeout_ms: 120000
        max_tool_iterations: 16
        max_output_bytes: 4194304
      stages:
        plan:
          model: "gemini-plan"
          options:
            reasoning_effort: "high"
        work:
          model: "ornith-fast"
        review:
          model: "gemini-review"
          options:
            reasoning_effort: "high"
nodes:
  - id: "node-01"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        models: ["gemini-plan", "ornith-fast", "gemini-review"]
        capacity: 2
`
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for extra route stage")
		}
		if !strings.Contains(err.Error(), "exactly 3 stages") {
			t.Fatalf("expected error mentioning exactly 3 stages, got %v", err)
		}
	})

	t.Run("missing light route rejected", func(t *testing.T) {
		// No routes section at all; single_request requires a light route.
		yaml := `server:
  listen: "0.0.0.0:9090"
models:
  - id: "gemini-plan"
    providers:
      prov-a: "gemini-plan"
  - id: "ornith-fast"
    providers:
      prov-a: "ornith-fast"
  - id: "gemini-review"
    providers:
      prov-a: "gemini-review"
execution_presets:
  - id: "fixed-single-request"
    selector:
      model: "gemini-plan"
      options:
        reasoning_effort: "high"
    allowed_modes:
      - "light"
    routes: {}
    single_request:
      workspace_ref: "ws-ref"
      limits:
        wall_clock_ms: 300000
        timeout_ms: 120000
        max_tool_iterations: 16
        max_output_bytes: 4194304
      stages:
        plan:
          model: "gemini-plan"
          options:
            reasoning_effort: "high"
        work:
          model: "ornith-fast"
        review:
          model: "gemini-review"
          options:
            reasoning_effort: "high"
nodes:
  - id: "node-01"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        models: ["gemini-plan", "ornith-fast", "gemini-review"]
        capacity: 2
`
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for missing light route")
		}
		if !strings.Contains(err.Error(), "missing route for allowed mode") && !strings.Contains(err.Error(), "must declare a route for mode") {
			t.Fatalf("expected error mentioning missing route or must declare a route for mode, got %v", err)
		}
	})
}

// TestLoadEdgeSingleRequestExecutionPresetRejectsUnknownNestedFields verifies
// that unknown fields fail strict decode at every new policy boundary (R3).
func TestLoadEdgeSingleRequestExecutionPresetRejectsUnknownNestedFields(t *testing.T) {
	dir := t.TempDir()
	f := filepath.Join(dir, "edge.yaml")

	t.Run("unknown field on single_request root rejected", func(t *testing.T) {
		yaml := `server:
  listen: "0.0.0.0:9090"
models:
  - id: "gemini-plan"
    providers:
      prov-a: "gemini-plan"
  - id: "ornith-fast"
    providers:
      prov-a: "ornith-fast"
  - id: "gemini-review"
    providers:
      prov-a: "gemini-review"
execution_presets:
  - id: "fixed-single-request"
    selector:
      model: "gemini-plan"
      options:
        reasoning_effort: "high"
    allowed_modes:
      - "light"
    routes:
      light:
        stages:
          - role: "plan"
            model: "gemini-plan"
            options:
              reasoning_effort: "high"
          - role: "work"
            model: "ornith-fast"
          - role: "review"
            model: "gemini-review"
            options:
              reasoning_effort: "high"
    single_request:
      workspace_ref: "ws-ref"
      unknown_root_field: "unexpected"
      limits:
        wall_clock_ms: 300000
        timeout_ms: 120000
        max_tool_iterations: 16
        max_output_bytes: 4194304
      stages:
        plan:
          model: "gemini-plan"
          options:
            reasoning_effort: "high"
        work:
          model: "ornith-fast"
        review:
          model: "gemini-review"
          options:
            reasoning_effort: "high"
nodes:
  - id: "node-01"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        models: ["gemini-plan", "ornith-fast", "gemini-review"]
        capacity: 2
`
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for unknown field on single_request root")
		}
		if !strings.Contains(err.Error(), "invalid keys") && !strings.Contains(err.Error(), "unknown fields") {
			t.Fatalf("expected error mentioning invalid keys or unknown fields, got %v", err)
		}
		if !strings.Contains(err.Error(), "unknown_root_field") {
			t.Fatalf("expected error mentioning unknown_root_field, got %v", err)
		}
	})

	t.Run("unknown field on single_request.limits rejected", func(t *testing.T) {
		yaml := `server:
  listen: "0.0.0.0:9090"
models:
  - id: "gemini-plan"
    providers:
      prov-a: "gemini-plan"
  - id: "ornith-fast"
    providers:
      prov-a: "ornith-fast"
  - id: "gemini-review"
    providers:
      prov-a: "gemini-review"
execution_presets:
  - id: "fixed-single-request"
    selector:
      model: "gemini-plan"
      options:
        reasoning_effort: "high"
    allowed_modes:
      - "light"
    routes:
      light:
        stages:
          - role: "plan"
            model: "gemini-plan"
            options:
              reasoning_effort: "high"
          - role: "work"
            model: "ornith-fast"
          - role: "review"
            model: "gemini-review"
            options:
              reasoning_effort: "high"
    single_request:
      workspace_ref: "ws-ref"
      limits:
        wall_clock_ms: 300000
        timeout_ms: 120000
        max_tool_iterations: 16
        max_output_bytes: 4194304
        unknown_limit_field: 123
      stages:
        plan:
          model: "gemini-plan"
          options:
            reasoning_effort: "high"
        work:
          model: "ornith-fast"
        review:
          model: "gemini-review"
          options:
            reasoning_effort: "high"
nodes:
  - id: "node-01"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        models: ["gemini-plan", "ornith-fast", "gemini-review"]
        capacity: 2
`
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for unknown field on limits")
		}
		if !strings.Contains(err.Error(), "invalid keys") && !strings.Contains(err.Error(), "unknown fields") {
			t.Fatalf("expected error mentioning invalid keys or unknown fields, got %v", err)
		}
		if !strings.Contains(err.Error(), "unknown_limit_field") {
			t.Fatalf("expected error mentioning unknown_limit_field, got %v", err)
		}
	})

	t.Run("unknown field on single_request.stages rejected", func(t *testing.T) {
		yaml := `server:
  listen: "0.0.0.0:9090"
models:
  - id: "gemini-plan"
    providers:
      prov-a: "gemini-plan"
  - id: "ornith-fast"
    providers:
      prov-a: "ornith-fast"
  - id: "gemini-review"
    providers:
      prov-a: "gemini-review"
execution_presets:
  - id: "fixed-single-request"
    selector:
      model: "gemini-plan"
      options:
        reasoning_effort: "high"
    allowed_modes:
      - "light"
    routes:
      light:
        stages:
          - role: "plan"
            model: "gemini-plan"
            options:
              reasoning_effort: "high"
          - role: "work"
            model: "ornith-fast"
          - role: "review"
            model: "gemini-review"
            options:
              reasoning_effort: "high"
    single_request:
      workspace_ref: "ws-ref"
      limits:
        wall_clock_ms: 300000
        timeout_ms: 120000
        max_tool_iterations: 16
        max_output_bytes: 4194304
      stages:
        plan:
          model: "gemini-plan"
          options:
            reasoning_effort: "high"
        work:
          model: "ornith-fast"
        review:
          model: "gemini-review"
          options:
            reasoning_effort: "high"
        unknown_stage_field: {}
nodes:
  - id: "node-01"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        models: ["gemini-plan", "ornith-fast", "gemini-review"]
        capacity: 2
`
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for unknown field on stages")
		}
		if !strings.Contains(err.Error(), "invalid keys") && !strings.Contains(err.Error(), "unknown fields") {
			t.Fatalf("expected error mentioning invalid keys or unknown fields, got %v", err)
		}
		if !strings.Contains(err.Error(), "unknown_stage_field") {
			t.Fatalf("expected error mentioning unknown_stage_field, got %v", err)
		}
	})

	t.Run("unknown field on single_request stage binding rejected", func(t *testing.T) {
		yaml := `server:
  listen: "0.0.0.0:9090"
models:
  - id: "gemini-plan"
    providers:
      prov-a: "gemini-plan"
  - id: "ornith-fast"
    providers:
      prov-a: "ornith-fast"
  - id: "gemini-review"
    providers:
      prov-a: "gemini-review"
execution_presets:
  - id: "fixed-single-request"
    selector:
      model: "gemini-plan"
      options:
        reasoning_effort: "high"
    allowed_modes:
      - "light"
    routes:
      light:
        stages:
          - role: "plan"
            model: "gemini-plan"
            options:
              reasoning_effort: "high"
          - role: "work"
            model: "ornith-fast"
          - role: "review"
            model: "gemini-review"
            options:
              reasoning_effort: "high"
    single_request:
      workspace_ref: "ws-ref"
      limits:
        wall_clock_ms: 300000
        timeout_ms: 120000
        max_tool_iterations: 16
        max_output_bytes: 4194304
      stages:
        plan:
          model: "gemini-plan"
          options:
            reasoning_effort: "high"
        work:
          model: "ornith-fast"
          unknown_stage_config_field: "invalid"
        review:
          model: "gemini-review"
          options:
            reasoning_effort: "high"
nodes:
  - id: "node-01"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        models: ["gemini-plan", "ornith-fast", "gemini-review"]
        capacity: 2
`
		if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil {
			t.Fatalf("write yaml: %v", err)
		}
		_, err := config.LoadEdge(f)
		if err == nil {
			t.Fatal("expected error for unknown field on stage config")
		}
		if !strings.Contains(err.Error(), "invalid keys") && !strings.Contains(err.Error(), "unknown fields") {
			t.Fatalf("expected error mentioning invalid keys or unknown fields, got %v", err)
		}
		if !strings.Contains(err.Error(), "unknown_stage_config_field") {
			t.Fatalf("expected error mentioning unknown_stage_config_field, got %v", err)
		}
	})
}

// TestCloneExecutionPresetSingleRequestIsolation verifies that deep-cloning a
// single-request preset produces an isolated copy: mutating the clone must not
// affect the source.
func TestCloneExecutionPresetSingleRequestIsolation(t *testing.T) {
	dir := t.TempDir()
	f := filepath.Join(dir, "edge.yaml")

	if err := os.WriteFile(f, []byte(validSingleRequestYAML), 0o600); err != nil {
		t.Fatalf("write yaml: %v", err)
	}
	cfg, err := config.LoadEdge(f)
	if err != nil {
		t.Fatalf("load: %v", err)
	}
	original := cfg.ExecutionPresets[0]
	if original.SingleRequest == nil {
		t.Fatal("expected SingleRequest to be set")
	}

	t.Run("clone isolates workspace_ref", func(t *testing.T) {
		clone := original.Clone()
		if clone.SingleRequest == nil {
			t.Fatal("clone: SingleRequest is nil")
		}
		clone.SingleRequest.WorkspaceRef = "mutated"
		if original.SingleRequest.WorkspaceRef == "mutated" {
			t.Error("source SingleRequest.WorkspaceRef was mutated by clone")
		}
		if clone.SingleRequest.WorkspaceRef != "mutated" {
			t.Error("clone SingleRequest.WorkspaceRef was not set")
		}
	})

	t.Run("clone isolates limits", func(t *testing.T) {
		clone := original.Clone()
		if clone.SingleRequest == nil {
			t.Fatal("clone: SingleRequest is nil")
		}
		clone.SingleRequest.Limits.WallClockMS = 999999
		if original.SingleRequest.Limits.WallClockMS == 999999 {
			t.Error("source SingleRequest.Limits.WallClockMS was mutated by clone")
		}
	})

	t.Run("clone isolates stage plan options", func(t *testing.T) {
		clone := original.Clone()
		if clone.SingleRequest == nil {
			t.Fatal("clone: SingleRequest is nil")
		}
		clone.SingleRequest.Stages.Plan.Options["reasoning_effort"] = "mutated"
		origVal, _ := original.SingleRequest.Stages.Plan.Options["reasoning_effort"]
		if origVal == "mutated" {
			t.Error("source plan options were mutated by clone")
		}
		cloneVal, _ := clone.SingleRequest.Stages.Plan.Options["reasoning_effort"]
		if cloneVal != "mutated" {
			t.Error("clone plan options were not set")
		}
	})

	t.Run("clone isolates stage work options", func(t *testing.T) {
		clone := original.Clone()
		if clone.SingleRequest == nil {
			t.Fatal("clone: SingleRequest is nil")
		}
		clone.SingleRequest.Stages.Work.Options["temperature"] = 99.0
		origVal, hasOrig := original.SingleRequest.Stages.Work.Options["temperature"]
		if hasOrig && origVal == 99.0 {
			t.Error("source work options were mutated by clone")
		}
		cloneVal, hasClone := clone.SingleRequest.Stages.Work.Options["temperature"]
		if !hasClone || cloneVal != 99.0 {
			t.Error("clone work options were not set")
		}
	})

	t.Run("clone isolates stage review options", func(t *testing.T) {
		clone := original.Clone()
		if clone.SingleRequest == nil {
			t.Fatal("clone: SingleRequest is nil")
		}
		clone.SingleRequest.Stages.Review.Options["max_retries"] = 99
		origVal, hasOrig := original.SingleRequest.Stages.Review.Options["max_retries"]
		if hasOrig && origVal == 99 {
			t.Error("source review options were mutated by clone")
		}
		cloneVal, hasClone := clone.SingleRequest.Stages.Review.Options["max_retries"]
		if !hasClone || cloneVal != 99 {
			t.Error("clone review options were not set")
		}
	})

	t.Run("clone isolates route stages", func(t *testing.T) {
		clone := original.Clone()
		if len(clone.Routes["light"].Stages) != 3 {
			t.Fatalf("clone route stages = %d, want 3", len(clone.Routes["light"].Stages))
		}
		clone.Routes["light"].Stages[0].Model = "mutated-model"
		if original.Routes["light"].Stages[0].Model == "mutated-model" {
			t.Error("source route stages were mutated by clone")
		}
		if clone.Routes["light"].Stages[0].Model != "mutated-model" {
			t.Error("clone route stages were not set")
		}
	})

	t.Run("clone isolates allowed_modes", func(t *testing.T) {
		clone := original.Clone()
		clone.AllowedModes[0] = "mutated"
		if original.AllowedModes[0] == "mutated" {
			t.Error("source AllowedModes was mutated by clone")
		}
	})

	t.Run("nil SingleRequest clone returns nil", func(t *testing.T) {
		noSR := original
		noSR.SingleRequest = nil
		clone := noSR.Clone()
		if clone.SingleRequest != nil {
			t.Error("expected nil SingleRequest on clone of preset without SingleRequest")
		}
	})

	t.Run("CloneExecutionPresetCatalog isolates single-request presets", func(t *testing.T) {
		catalog := config.CloneExecutionPresetCatalog(cfg.ExecutionPresets)
		if len(catalog) != 1 {
			t.Fatalf("expected 1 preset in catalog, got %d", len(catalog))
		}
		clone := catalog[0]
		if clone.SingleRequest == nil {
			t.Fatal("clone catalog: SingleRequest is nil")
		}
		clone.SingleRequest.Limits.MaxToolIterations = 0
		if cfg.ExecutionPresets[0].SingleRequest.Limits.MaxToolIterations == 0 {
			t.Error("source catalog preset was mutated by clone")
		}
	})
}

// routeStagesRoles extracts role names from a slice of ExecutionRouteStage.
func routeStagesRoles(stages []config.ExecutionRouteStage) []string {
	roles := make([]string, len(stages))
	for i, s := range stages {
		roles[i] = s.Role
	}
	return roles
}

func requireSingleRequestLoadError(t *testing.T, path, yaml string, wantFragments ...string) {
	t.Helper()
	if err := os.WriteFile(path, []byte(yaml), 0o600); err != nil {
		t.Fatalf("write yaml: %v", err)
	}
	_, err := config.LoadEdge(path)
	if err == nil {
		t.Fatal("expected error for malformed single-request binding")
	}
	for _, want := range wantFragments {
		if !strings.Contains(err.Error(), want) {
			t.Fatalf("expected error mentioning %q, got %v", want, err)
		}
	}
}

func singleRequestYAMLWithRouteBindingDiff(
	routePlanModel, routeWorkModel, routeReviewModel string,
	routePlanOptions, routeWorkOptions, routeReviewOptions, singleWorkOptions string,
) string {
	return `server:
  listen: "0.0.0.0:9090"
models:
  - id: "gemini-plan"
    providers:
      prov-a: "gemini-plan"
  - id: "ornith-fast"
    providers:
      prov-a: "ornith-fast"
  - id: "gemini-review"
    providers:
      prov-a: "gemini-review"
execution_presets:
  - id: "fixed-single-request"
    selector:
      model: "gemini-plan"
      options:
        reasoning_effort: "high"
    allowed_modes:
      - "light"
    routes:
      light:
        stages:
          - role: "plan"
            model: "` + routePlanModel + `"` + routePlanOptions + `
          - role: "work"
            model: "` + routeWorkModel + `"` + routeWorkOptions + `
          - role: "review"
            model: "` + routeReviewModel + `"` + routeReviewOptions + `
    single_request:
      workspace_ref: "ws-ref"
      limits:
        wall_clock_ms: 300000
        timeout_ms: 120000
        max_tool_iterations: 16
        max_output_bytes: 4194304
      stages:
        plan:
          model: "gemini-plan"
          options:
            reasoning_effort: "high"
        work:
          model: "ornith-fast"` + singleWorkOptions + `
        review:
          model: "gemini-review"
          options:
            reasoning_effort: "high"
nodes:
  - id: "node-01"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        models: ["gemini-plan", "ornith-fast", "gemini-review"]
        capacity: 2
`
}

// srYAMLWithWorkspaceRef produces a valid single-request preset YAML with the
// given workspace_ref and limits, using standard plan/work/review stage bindings.
func srYAMLWithWorkspaceRef(workspaceRef string, wallClock, stageTimeout, toolIters, outputBytes int) string {
	return `server:
  listen: "0.0.0.0:9090"
models:
  - id: "gemini-plan"
    providers:
      prov-a: "gemini-plan"
  - id: "ornith-fast"
    providers:
      prov-a: "ornith-fast"
  - id: "gemini-review"
    providers:
      prov-a: "gemini-review"
execution_presets:
  - id: "fixed-single-request"
    selector:
      model: "gemini-plan"
      options:
        reasoning_effort: "high"
    allowed_modes:
      - "light"
    routes:
      light:
        stages:
          - role: "plan"
            model: "gemini-plan"
            options:
              reasoning_effort: "high"
          - role: "work"
            model: "ornith-fast"
          - role: "review"
            model: "gemini-review"
            options:
              reasoning_effort: "high"
    single_request:
      workspace_ref: "` + workspaceRef + `"
      limits:
        wall_clock_ms: ` + itoa(wallClock) + `
        timeout_ms: ` + itoa(stageTimeout) + `
        max_tool_iterations: ` + itoa(toolIters) + `
        max_output_bytes: ` + itoa(outputBytes) + `
      stages:
        plan:
          model: "gemini-plan"
          options:
            reasoning_effort: "high"
        work:
          model: "ornith-fast"
        review:
          model: "gemini-review"
          options:
            reasoning_effort: "high"
nodes:
  - id: "node-01"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        models: ["gemini-plan", "ornith-fast", "gemini-review"]
        capacity: 2
`
}

// srYAMLWithPlanModel produces a valid single-request preset YAML with the
// given plan stage model and standard limits.
func srYAMLWithPlanModel(planModel string, wallClock, stageTimeout, toolIters, outputBytes int) string {
	return `server:
  listen: "0.0.0.0:9090"
models:
  - id: "gemini-plan"
    providers:
      prov-a: "gemini-plan"
  - id: "ornith-fast"
    providers:
      prov-a: "ornith-fast"
  - id: "gemini-review"
    providers:
      prov-a: "gemini-review"
execution_presets:
  - id: "fixed-single-request"
    selector:
      model: "gemini-plan"
      options:
        reasoning_effort: "high"
    allowed_modes:
      - "light"
    routes:
      light:
        stages:
          - role: "plan"
            model: "gemini-plan"
            options:
              reasoning_effort: "high"
          - role: "work"
            model: "ornith-fast"
          - role: "review"
            model: "gemini-review"
            options:
              reasoning_effort: "high"
    single_request:
      workspace_ref: "ws-ref"
      limits:
        wall_clock_ms: ` + itoa(wallClock) + `
        timeout_ms: ` + itoa(stageTimeout) + `
        max_tool_iterations: ` + itoa(toolIters) + `
        max_output_bytes: ` + itoa(outputBytes) + `
      stages:
        plan:
          model: "` + planModel + `"
          options:
            reasoning_effort: "high"
        work:
          model: "ornith-fast"
        review:
          model: "gemini-review"
          options:
            reasoning_effort: "high"
nodes:
  - id: "node-01"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        models: ["gemini-plan", "ornith-fast", "gemini-review"]
        capacity: 2
`
}

// srYAMLWithWorkModel produces a valid single-request preset YAML with the
// given work stage model and standard limits.
func srYAMLWithWorkModel(workModel string, wallClock, stageTimeout, toolIters, outputBytes int) string {
	return `server:
  listen: "0.0.0.0:9090"
models:
  - id: "gemini-plan"
    providers:
      prov-a: "gemini-plan"
  - id: "ornith-fast"
    providers:
      prov-a: "ornith-fast"
  - id: "gemini-review"
    providers:
      prov-a: "gemini-review"
execution_presets:
  - id: "fixed-single-request"
    selector:
      model: "gemini-plan"
      options:
        reasoning_effort: "high"
    allowed_modes:
      - "light"
    routes:
      light:
        stages:
          - role: "plan"
            model: "gemini-plan"
            options:
              reasoning_effort: "high"
          - role: "work"
            model: "` + workModel + `"
          - role: "review"
            model: "gemini-review"
            options:
              reasoning_effort: "high"
    single_request:
      workspace_ref: "ws-ref"
      limits:
        wall_clock_ms: ` + itoa(wallClock) + `
        timeout_ms: ` + itoa(stageTimeout) + `
        max_tool_iterations: ` + itoa(toolIters) + `
        max_output_bytes: ` + itoa(outputBytes) + `
      stages:
        plan:
          model: "gemini-plan"
          options:
            reasoning_effort: "high"
        work:
          model: "` + workModel + `"
        review:
          model: "gemini-review"
          options:
            reasoning_effort: "high"
nodes:
  - id: "node-01"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        models: ["gemini-plan", "ornith-fast", "gemini-review"]
        capacity: 2
`
}

// srYAMLWithReviewModel produces a valid single-request preset YAML with the
// given review stage model and standard limits.
func srYAMLWithReviewModel(reviewModel string, wallClock, stageTimeout, toolIters, outputBytes int) string {
	return `server:
  listen: "0.0.0.0:9090"
models:
  - id: "gemini-plan"
    providers:
      prov-a: "gemini-plan"
  - id: "ornith-fast"
    providers:
      prov-a: "ornith-fast"
  - id: "gemini-review"
    providers:
      prov-a: "gemini-review"
execution_presets:
  - id: "fixed-single-request"
    selector:
      model: "gemini-plan"
      options:
        reasoning_effort: "high"
    allowed_modes:
      - "light"
    routes:
      light:
        stages:
          - role: "plan"
            model: "gemini-plan"
            options:
              reasoning_effort: "high"
          - role: "work"
            model: "ornith-fast"
          - role: "review"
            model: "` + reviewModel + `"
            options:
              reasoning_effort: "high"
    single_request:
      workspace_ref: "ws-ref"
      limits:
        wall_clock_ms: ` + itoa(wallClock) + `
        timeout_ms: ` + itoa(stageTimeout) + `
        max_tool_iterations: ` + itoa(toolIters) + `
        max_output_bytes: ` + itoa(outputBytes) + `
      stages:
        plan:
          model: "gemini-plan"
          options:
            reasoning_effort: "high"
        work:
          model: "ornith-fast"
        review:
          model: "` + reviewModel + `"
          options:
            reasoning_effort: "high"
nodes:
  - id: "node-01"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        models: ["gemini-plan", "ornith-fast", "gemini-review"]
        capacity: 2
`
}

// singleRequestYAMLWithLimits produces a valid single-request preset YAML with
// the given limits and the standard plan/work/review stage bindings.
func singleRequestYAMLWithLimits(wallClock, stageTimeout, toolIters, outputBytes int) string {
	return `
server:
  listen: "0.0.0.0:9090"
models:
  - id: "gemini-plan"
    providers:
      prov-a: "gemini-plan"
  - id: "ornith-fast"
    providers:
      prov-a: "ornith-fast"
  - id: "gemini-review"
    providers:
      prov-a: "gemini-review"
execution_presets:
  - id: "fixed-single-request"
    selector:
      model: "gemini-plan"
      options:
        reasoning_effort: "high"
    allowed_modes:
      - "light"
    routes:
      light:
        stages:
          - role: "plan"
            model: "gemini-plan"
            options:
              reasoning_effort: "high"
          - role: "work"
            model: "ornith-fast"
            options:
              temperature: 0.2
          - role: "review"
            model: "gemini-review"
            options:
              reasoning_effort: "high"
    single_request:
      workspace_ref: "ws-capability-ref-001"
      limits:
        wall_clock_ms: ` + itoa(wallClock) + `
        timeout_ms: ` + itoa(stageTimeout) + `
        max_tool_iterations: ` + itoa(toolIters) + `
        max_output_bytes: ` + itoa(outputBytes) + `
      stages:
        plan:
          model: "gemini-plan"
          options:
            reasoning_effort: "high"
        work:
          model: "ornith-fast"
          options:
            temperature: 0.2
        review:
          model: "gemini-review"
          options:
            reasoning_effort: "high"
nodes:
  - id: "node-01"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        models: ["gemini-plan", "ornith-fast", "gemini-review"]
        capacity: 2
`
}

func itoa(v int) string {
	return fmt.Sprintf("%d", v)
}
