{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "bosun config",
  "type": "object",
  "additionalProperties": true,
  "properties": {
    "$schema": {
      "type": "string"
    },
    "projectName": {
      "type": "string"
    },
    "mode": {
      "type": "string",
      "enum": ["virtengine", "generic"]
    },
    "orchestratorScript": {
      "type": "string"
    },
    "orchestratorArgs": {
      "type": "string"
    },
    "logDir": {
      "type": "string"
    },
    "logMaxSizeMb": {
      "type": "number",
      "description": "Max total log folder size in MB. 0 = unlimited.",
      "default": 500
    },
    "logCleanupIntervalMin": {
      "type": "number",
      "description": "How often to check log folder size (minutes). 0 = startup only.",
      "default": 30
    },
    "telegramVerbosity": {
      "type": "string",
      "enum": ["minimal", "summary", "detailed"],
      "description": "Notification verbosity: minimal (critical+error), summary (default), detailed (everything)",
      "default": "summary"
    },
    "watchPath": {
      "type": "string"
    },
    "watchEnabled": {
      "type": "boolean"
    },
    "echoLogs": {
      "type": "boolean"
    },
    "autoFixEnabled": {
      "type": "boolean"
    },
    "workflowFirst": {
      "type": "boolean",
      "default": false,
      "description": "When true, all modules start in WORKFLOW mode by default. The task executor lifecycle is fully delegated to workflow templates (workflowOwnsTaskLifecycle). Bosun acts as a thin shell around the workflow engine."
    },
    "workflowOwnsTaskLifecycle": {
      "type": "boolean",
      "default": false,
      "description": "Delegate task finalization and recovery to workflow automation instead of the legacy TaskExecutor. Automatically set to true when workflowFirst is enabled."
    },
    "workflowRiskyActionApprovalsEnabled": {
      "type": "boolean",
      "default": false,
      "description": "Require operator approval before workflows execute irreversible actions such as push, PR creation, destructive git cleanup, and Bosun task deletion."
    },
    "workflowWorktreeRecoveryCooldownMin": {
      "type": "number",
      "default": 15,
      "description": "Minutes to keep a task blocked after a non-retryable worktree acquisition failure before Bosun returns it to todo automatically."
    },
    "worktreeBootstrap": {
      "type": "object",
      "additionalProperties": true,
      "description": "Bootstrap policy for managed worktrees, including optional shared dependency links and per-ecosystem install/restore commands.",
      "properties": {
        "enabled": {
          "type": "boolean",
          "default": true
        },
        "linkSharedPaths": {
          "type": "boolean",
          "default": true,
          "description": "Link reusable dependency directories from the repo root into each managed worktree when possible."
        },
        "commandTimeoutMs": {
          "type": "number",
          "default": 600000,
          "description": "Maximum time to allow each bootstrap command to run inside a managed worktree."
        },
        "setupScript": {
          "type": "string",
          "description": "Optional repo-specific shell command to run inside every managed worktree before stack bootstrap commands. Useful for local environment setup, SDK hook scaffolding, or repository-specific bootstrap fixes."
        },
        "commandsByStack": {
          "type": "object",
          "additionalProperties": {
            "oneOf": [
              { "type": "string" },
              { "type": "array", "items": { "type": "string" } }
            ]
          },
          "description": "Override bootstrap commands by detected ecosystem id such as node, python, go, rust, java, dotnet, ruby, php, or make."
        },
        "sharedPathsByStack": {
          "type": "object",
          "additionalProperties": {
            "oneOf": [
              { "type": "string" },
              { "type": "array", "items": { "type": "string" } }
            ]
          },
          "description": "Override reusable relative paths to link from the repo root into a managed worktree for each detected ecosystem."
        }
      }
    },
    "workflowDefaults": {
      "type": "object",
      "additionalProperties": true,
      "properties": {
        "profile": {
          "type": "string",
          "description": "Default workflow setup profile (for example: balanced, autonomous, workflowFirst)."
        },
        "autoInstall": {
          "type": "boolean",
          "description": "Automatically install requested templates on startup."
        },
        "templates": {
          "oneOf": [
            { "type": "array", "items": { "type": "string" } },
            { "type": "string" }
          ],
          "description": "Explicit template IDs to install/enable."
        },
        "templateOverridesById": {
          "type": "object",
          "additionalProperties": { "type": "object" },
          "description": "Template variable overrides keyed by template id."
        }
      }
    },
    "harness": {
      "type": "object",
      "additionalProperties": true,
      "properties": {
        "enabled": {
          "type": "boolean",
          "default": false
        },
        "source": {
          "type": "string",
          "description": "Path to the internal harness profile source file. Supports JSON or markdown fenced JSON."
        },
        "primaryExecutor": {
          "type": "string",
          "description": "Named Harness executor ID to use as the default interactive/runtime selection."
        },
        "routingMode": {
          "type": "string",
          "enum": ["default-only", "fallback", "spread"],
          "default": "default-only",
          "description": "How the Harness runtime should route across named executors."
        },
        "executors": {
          "type": "array",
          "description": "Named Harness executor instances. These are the Bosun-native runtime selections exposed to chat, workflow, TUI, web UI, and Telegram when Harness is primary.",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": ["id", "providerId"],
            "properties": {
              "id": { "type": "string" },
              "name": { "type": "string" },
              "providerId": {
                "type": "string",
                "enum": ["openai-responses", "openai-codex-subscription", "azure-openai-responses", "anthropic-messages", "claude-subscription-shim", "openai-compatible", "ollama", "copilot-oauth", "openrouter", "perplexity", "deepinfra", "groq", "together", "xai", "fireworks", "cerebras", "sambanova", "nebius", "gemini-generate-content"]
              },
              "enabled": { "type": "boolean", "default": true },
              "weight": {
                "type": "number",
                "minimum": 0,
                "description": "Optional routing weight used when the Harness runtime spreads work across multiple executor instances."
              },
              "defaultModel": { "type": "string" },
              "models": {
                "oneOf": [
                  {
                    "type": "array",
                    "items": {
                      "oneOf": [
                        { "type": "string" },
                        {
                          "type": "object",
                          "additionalProperties": false,
                          "required": ["id"],
                          "properties": {
                            "id": { "type": "string" },
                            "label": { "type": "string" },
                            "enabled": { "type": "boolean", "default": true },
                            "apiStyle": {
                              "type": "string",
                              "enum": ["provider-default", "responses", "chat-completions"]
                            },
                            "reasoningEffort": { "type": "string" },
                            "contextWindow": { "type": "number" }
                          }
                        }
                      ]
                    }
                  },
                  { "type": "string" }
                ]
              },
              "authMode": { "type": "string" },
              "endpoint": { "type": "string" },
              "baseUrl": { "type": "string" },
              "deployment": { "type": "string" },
              "apiVersion": { "type": "string" },
              "workspace": { "type": "string" },
              "organization": { "type": "string" },
              "project": { "type": "string" },
              "authBindings": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "apiKeyEnv": { "type": "string" },
                  "oauthTokenEnv": { "type": "string" },
                  "subscriptionEnv": { "type": "string" }
                }
              },
              "apiStyle": {
                "type": "string",
                "enum": ["provider-default", "responses", "chat-completions"]
              }
            }
          }
        },
        "validation": {
          "type": "object",
          "additionalProperties": true,
          "properties": {
            "mode": {
              "type": "string",
              "enum": ["off", "report", "enforce"],
              "default": "report"
            }
          }
        }
      }
    },
    "workflows": {
      "type": "array",
      "description": "Opt-in typed workflow templates that resolve to built-in workflow definitions.",
      "items": {
        "type": "object",
        "additionalProperties": true,
        "properties": {
          "type": {
            "type": "string",
            "enum": ["continuation-loop"]
          },
          "enabled": { "type": "boolean" },
          "name": { "type": "string" },
          "taskId": { "type": "string" },
          "worktreePath": { "type": "string" },
          "pollIntervalMs": { "type": "number" },
          "maxTurns": { "type": "number" },
          "terminalStates": {
            "oneOf": [
              { "type": "array", "items": { "type": "string" } },
              { "type": "string" }
            ]
          },
          "stuckThresholdMs": { "type": "number" },
          "onStuck": {
            "type": "string",
            "enum": ["retry", "escalate", "pause"]
          },
          "continuePrompt": { "type": "string" },
          "retryPrompt": { "type": "string" },
          "sdk": { "type": "string" },
          "model": { "type": "string" },
          "timeoutMs": { "type": "number" },
          "options": {
            "type": "object",
            "additionalProperties": true,
            "description": "Additional template variable overrides for this typed workflow entry."
          }
        },
        "required": ["type"]
      }
    },
    "prAutomation": {
      "type": "object",
      "additionalProperties": true,
      "description": "Trust policy for PR automation. High-risk actions default to Bosun-created PRs only; trusted human authors are opt-in.",
      "properties": {
        "attachMode": {
          "type": "string",
          "enum": ["all", "trusted-only", "disabled"],
          "default": "all",
          "description": "How broadly Bosun applies its low-trust attachment marker. High-risk actions remain separately gated."
        },
        "trustedAuthors": {
          "oneOf": [
            { "type": "array", "items": { "type": "string" } },
            { "type": "string" }
          ],
          "description": "GitHub logins that Bosun may treat as trusted for optional non-Bosun PR automation. The currently connected GitHub OAuth login is also trusted automatically when present."
        },
        "allowTrustedFixes": {
          "type": "boolean",
          "default": false,
          "description": "Allow Bosun to auto-repair attached PRs from trusted authors."
        },
        "allowTrustedMerges": {
          "type": "boolean",
          "default": false,
          "description": "Allow Bosun to auto-merge attached PRs from trusted authors after the normal review and CI gates."
        },
        "assistiveActions": {
          "type": "object",
          "additionalProperties": true,
          "description": "Optional repo-local GitHub Actions that add labels and comments. Bosun works without them.",
          "properties": {
            "installOnSetup": {
              "type": "boolean",
              "default": false,
              "description": "If true, Bosun setup may copy the assistive PR attach and CI signal workflows into configured repos."
            }
          }
        }
      }
    },
    "gates": {
      "type": "object",
      "additionalProperties": true,
      "description": "Unified safeguards for PR policy, CI/CD merge gates, executor isolation, and runtime safety posture.",
      "properties": {
        "prs": {
          "type": "object",
          "additionalProperties": true,
          "properties": {
            "repoVisibility": {
              "type": "string",
              "enum": ["public", "private", "unknown"],
              "default": "unknown",
              "description": "Detected or operator-confirmed repository visibility used to recommend automation posture during setup."
            },
            "automationPreference": {
              "type": "string",
              "enum": ["runtime-first", "actions-first"],
              "default": "runtime-first",
              "description": "Whether Bosun should favor runtime-driven automation or heavier GitHub Actions assistance when both are available."
            },
            "githubActionsBudget": {
              "type": "string",
              "enum": ["ask-user", "available", "limited"],
              "default": "ask-user",
              "description": "Operator-supplied indication of whether GitHub Actions runtime is available for heavier PR automation."
            }
          }
        },
        "checks": {
          "type": "object",
          "additionalProperties": true,
          "properties": {
            "mode": {
              "type": "string",
              "enum": ["all", "required-only"],
              "default": "all",
              "description": "When 'all', every non-ignored check is treated as blocking unless explicitly optional. When 'required-only', only checks matching requiredPatterns block merge."
            },
            "requiredPatterns": {
              "oneOf": [
                { "type": "array", "items": { "type": "string" } },
                { "type": "string" }
              ],
              "description": "Check-name patterns Bosun must treat as required before merge when using required-only gating."
            },
            "optionalPatterns": {
              "oneOf": [
                { "type": "array", "items": { "type": "string" } },
                { "type": "string" }
              ],
              "description": "Check-name patterns Bosun may ignore for merge blocking, even if they fail or remain absent."
            },
            "ignorePatterns": {
              "oneOf": [
                { "type": "array", "items": { "type": "string" } },
                { "type": "string" }
              ],
              "description": "Check-name patterns Bosun should exclude from merge-gate evaluation entirely."
            },
            "requireAnyRequiredCheck": {
              "type": "boolean",
              "default": true,
              "description": "If true, Bosun blocks merge when no required checks are present after filtering."
            },
            "treatPendingRequiredAsBlocking": {
              "type": "boolean",
              "default": true,
              "description": "If true, pending required checks block merge."
            },
            "treatNeutralAsPass": {
              "type": "boolean",
              "default": false,
              "description": "If true, neutral or skipped required checks count as passing for merge gating."
            }
          }
        },
        "execution": {
          "type": "object",
          "additionalProperties": true,
          "properties": {
            "sandboxMode": {
              "type": "string",
              "description": "Operator-facing snapshot of the preferred executor sandbox mode."
            },
            "containerIsolationEnabled": {
              "type": "boolean",
              "default": false,
              "description": "Whether container isolation is part of the expected safety posture."
            },
            "containerRuntime": {
              "type": "string",
              "description": "Preferred runtime for container isolation when enabled."
            },
            "networkAccess": {
              "type": "string",
              "description": "High-level network access posture for isolated execution."
            }
          }
        },
        "worktrees": {
          "type": "object",
          "additionalProperties": true,
          "description": "Readiness safeguards for Bosun-managed task worktrees only. These settings document whether Node-style bootstrap/readiness checks and push-hook enforcement are expected before task work proceeds.",
          "properties": {
            "requireBootstrap": {
              "type": "boolean",
              "description": "Whether Bosun-managed task worktrees should require bootstrap before execution. Defaults to explicit worktreeBootstrap.enabled when provided, otherwise true."
            },
            "requireReadiness": {
              "type": "boolean",
              "description": "Whether Bosun-managed task worktrees should require a readiness check before execution. Defaults to explicit worktreeBootstrap.enabled when provided, otherwise true."
            },
            "enforcePushHook": {
              "type": "boolean",
              "default": true,
              "description": "Whether Bosun-managed task worktrees should enforce the repository push hook before handoff or push."
            }
          }
        },
        "runtime": {
          "type": "object",
          "additionalProperties": true,
          "properties": {
            "enforceBacklog": {
              "type": "boolean",
              "default": true,
              "description": "Whether newly created work should be forced through backlog safeguards before direct execution."
            },
            "agentTriggerControl": {
              "type": "boolean",
              "default": true,
              "description": "Whether agent-trigger safeguards remain enabled for untrusted or indirect sources."
            }
          }
        }
      }
    },
    "markdownSafety": {
      "type": "object",
      "additionalProperties": true,
      "description": "Safety controls for imported or runtime-ingested markdown, including allowlisted documentation exceptions and audit logging.",
      "properties": {
        "enabled": {
          "type": "boolean",
          "default": true,
          "description": "When false, markdown safety blocking is disabled while audit logging configuration remains available."
        },
        "auditLogPath": {
          "type": "string",
          "description": "Relative or absolute path for JSONL audit events describing blocked markdown content."
        },
        "allowlist": {
          "type": "array",
          "description": "Optional exceptions for known-safe repositories or paths. Documentation-only exceptions should set context=documentation.",
          "items": {
            "type": "object",
            "additionalProperties": true,
            "properties": {
              "repo": {
                "type": "string",
                "description": "Repository path, slug, or identifier substring to match."
              },
              "repoUrl": {
                "type": "string",
                "description": "Repository URL substring to match."
              },
              "path": {
                "type": "string",
                "description": "Exact normalized path to allow."
              },
              "pathPrefix": {
                "type": "string",
                "description": "Leading path segment to allow."
              },
              "pathSuffix": {
                "type": "string",
                "description": "Trailing path segment or filename to allow."
              },
              "context": {
                "type": "string",
                "enum": ["any", "documentation"],
                "default": "any"
              },
              "reason": {
                "type": "string",
                "description": "Operator note explaining why the exception is trusted."
              }
            }
          }
        }
      }
    },
    "interactiveShellEnabled": { "type": "boolean" },
    "shellEnabled": { "type": "boolean" },
    "codexEnabled": { "type": "boolean" },
    "primaryAgent": {
      "type": "string",
      "enum": [
        "codex-sdk",
        "copilot-sdk",
        "claude-sdk",
        "gemini-sdk",
        "opencode-sdk"
      ]
    },
    "telegramUiTunnel": {
      "type": "string",
      "enum": ["named", "quick", "auto", "cloudflared", "disabled"],
      "default": "named",
      "description": "Mini App tunnel mode. named is the default permanent hostname mode."
    },
    "telegramUiAllowQuickTunnelFallback": {
      "type": "boolean",
      "default": false,
      "description": "Allow quick trycloudflare fallback only when named tunnel startup fails."
    },
    "cloudflareTunnelName": {
      "type": "string",
      "description": "Named Cloudflare tunnel identifier."
    },
    "cloudflareTunnelCredentials": {
      "type": "string",
      "description": "Path to cloudflared tunnel credentials JSON."
    },
    "cloudflareBaseDomain": {
      "type": "string",
      "description": "Base domain used for deterministic per-user tunnel hostnames."
    },
    "cloudflareTunnelHostname": {
      "type": "string",
      "description": "Explicit tunnel hostname override."
    },
    "cloudflareUsernameHostnamePolicy": {
      "type": "string",
      "enum": ["per-user-fixed", "fixed"],
      "default": "per-user-fixed",
      "description": "Policy for deriving named tunnel hostname from workstation identity."
    },
    "cloudflareZoneId": {
      "type": "string",
      "description": "Cloudflare zone ID used for DNS orchestration."
    },
    "cloudflareApiToken": {
      "type": "string",
      "description": "Cloudflare API token scoped to Zone DNS edit."
    },
    "cloudflareDnsSyncEnabled": {
      "type": "boolean",
      "default": true,
      "description": "Enable Cloudflare DNS idempotent create/verify/update during named tunnel startup."
    },
    "cloudflareDnsMaxRetries": {
      "type": "number",
      "default": 3,
      "description": "Retry attempts for Cloudflare DNS API operations."
    },
    "cloudflareDnsRetryBaseMs": {
      "type": "number",
      "default": 750,
      "description": "Base backoff delay for Cloudflare DNS API retries."
    },
    "telegramUiFallbackAuthEnabled": {
      "type": "boolean",
      "default": true,
      "description": "Enable admin fallback PIN/password auth when Telegram/session auth is unavailable."
    },
    "telegramUiFallbackAuthRateLimitIpPerMin": {
      "type": "number",
      "default": 10,
      "description": "Per-IP fallback auth attempt rate limit per minute."
    },
    "telegramUiFallbackAuthRateLimitGlobalPerMin": {
      "type": "number",
      "default": 60,
      "description": "Global fallback auth attempt rate limit per minute."
    },
    "telegramUiFallbackAuthMaxFailures": {
      "type": "number",
      "default": 5,
      "description": "Failed fallback auth attempts before temporary lockout."
    },
    "telegramUiFallbackAuthLockoutMs": {
      "type": "number",
      "default": 600000,
      "description": "Temporary lockout duration in milliseconds after max fallback auth failures."
    },
    "telegramUiFallbackAuthRotateDays": {
      "type": "number",
      "default": 30,
      "description": "Target credential rotation interval for fallback auth."
    },
    "telegramUiFallbackAuthTransientCooldownMs": {
      "type": "number",
      "default": 5000,
      "description": "Cooldown when fallback auth backend has transient errors."
    },
    "voice": {
      "type": "object",
      "description": "Voice assistant configuration for real-time voice interaction",
      "additionalProperties": false,
      "properties": {
        "enabled": {
          "type": "boolean",
          "default": true,
          "description": "Enable voice assistant features"
        },
        "provider": {
          "type": "string",
          "enum": ["openai", "azure", "claude", "gemini", "fallback", "auto"],
          "default": "auto",
          "description": "Voice provider: openai/azure (Tier 1 realtime), claude/gemini (Tier 2 voice + provider vision), fallback (browser STT/TTS), auto (detect from env)"
        },
        "providers": {
          "type": "array",
          "description": "Ordered provider candidates for voice routing/failover. First match with credentials is used.",
          "items": {
            "anyOf": [
              {
                "type": "string",
                "enum": ["openai", "azure", "claude", "gemini", "fallback"]
              },
              {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "provider": {
                    "type": "string",
                    "enum": ["openai", "azure", "claude", "gemini", "fallback"]
                  },
                  "model": {
                    "type": "string"
                  },
                  "visionModel": {
                    "type": "string"
                  },
                  "voiceId": {
                    "type": "string",
                    "enum": [
                      "alloy",
                      "ash",
                      "ballad",
                      "coral",
                      "echo",
                      "fable",
                      "onyx",
                      "nova",
                      "sage",
                      "shimmer",
                      "verse"
                    ]
                  },
                  "azureDeployment": {
                    "type": "string"
                  },
                  "endpointId": {
                    "type": "string",
                    "description": "ID of the voice endpoint to use for this provider slot"
                  }
                },
                "required": ["provider"]
              }
            ]
          }
        },
        "model": {
          "type": "string",
          "default": "gpt-4o-realtime-preview-2024-12-17",
          "description": "Realtime API model name"
        },
        "visionModel": {
          "type": "string",
          "default": "gpt-4.1-mini",
          "description": "Vision model used for live screen/camera frame analysis"
        },
        "openaiApiKey": {
          "type": "string",
          "description": "OpenAI API key for Realtime API (overrides OPENAI_API_KEY env)"
        },
        "openaiAccessToken": {
          "type": "string",
          "description": "OpenAI OAuth access token for voice (OAuth preferred over API key when present)"
        },
        "azureApiKey": {
          "type": "string",
          "description": "Azure OpenAI API key for Realtime API"
        },
        "azureAccessToken": {
          "type": "string",
          "description": "Azure OAuth/AAD access token for voice realtime"
        },
        "azureEndpoint": {
          "type": "string",
          "description": "Azure OpenAI endpoint URL"
        },
        "azureDeployment": {
          "type": "string",
          "default": "gpt-4o-realtime-preview",
          "description": "Azure OpenAI deployment name"
        },
        "claudeApiKey": {
          "type": "string",
          "description": "Anthropic API key for Claude voice/vision provider mode"
        },
        "claudeAccessToken": {
          "type": "string",
          "description": "Claude OAuth access token for voice provider mode"
        },
        "geminiApiKey": {
          "type": "string",
          "description": "Gemini API key for Gemini voice/vision provider mode"
        },
        "geminiAccessToken": {
          "type": "string",
          "description": "Gemini OAuth access token for voice provider mode"
        },
        "voiceId": {
          "type": "string",
          "enum": [
            "alloy",
            "ash",
            "ballad",
            "coral",
            "echo",
            "fable",
            "onyx",
            "nova",
            "sage",
            "shimmer",
            "verse"
          ],
          "default": "alloy",
          "description": "Voice ID for TTS output"
        },
        "turnDetection": {
          "type": "string",
          "enum": ["server_vad", "semantic_vad", "none"],
          "default": "semantic_vad",
          "description": "Turn detection mode for voice activity detection"
        },
        "instructions": {
          "type": "string",
          "description": "Custom system instructions for the voice assistant"
        },
        "fallbackMode": {
          "type": "string",
          "enum": ["browser", "disabled"],
          "default": "browser",
          "description": "Fallback when Realtime API unavailable: browser (Web Speech API) or disabled"
        },
        "failover": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "enabled": {
              "type": "boolean",
              "default": true,
              "description": "Enable automatic realtime failover across configured voice providers"
            },
            "maxAttempts": {
              "type": "number",
              "default": 2,
              "description": "Maximum realtime provider attempts per voice session token request"
            }
          }
        },
        "voiceEndpoints": {
          "type": "array",
          "description": "Named realtime voice endpoints, each with its own credentials. Multiple endpoints enable automatic failover with context preservation.",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": ["provider"],
            "properties": {
              "id": {
                "type": "string",
                "description": "Unique identifier for this endpoint"
              },
              "name": {
                "type": "string",
                "description": "Friendly label for this endpoint"
              },
              "provider": {
                "type": "string",
                "enum": ["azure", "openai", "claude", "gemini"],
                "description": "Provider type"
              },
              "endpoint": {
                "type": "string",
                "description": "Azure OpenAI endpoint URL (required for azure)"
              },
              "deployment": {
                "type": "string",
                "description": "Azure deployment name (required for azure)"
              },
              "apiKey": {
                "type": "string",
                "description": "API key for this endpoint"
              },
              "model": {
                "type": "string",
                "description": "Model name (for openai provider)"
              },
              "voiceId": {
                "type": "string"
              },
              "visionModel": {
                "type": "string"
              },
              "role": {
                "type": "string",
                "enum": ["primary", "backup"],
                "default": "primary"
              },
              "weight": {
                "type": "number",
                "default": 100,
                "description": "Priority weight — higher = tried first"
              },
              "enabled": {
                "type": "boolean",
                "default": true
              }
            }
          }
        },
        "delegateExecutor": {
          "type": "string",
          "enum": [
            "codex-sdk",
            "copilot-sdk",
            "claude-sdk",
            "gemini-sdk",
            "opencode-sdk"
          ],
          "description": "Which executor to use for delegate_to_agent calls. Defaults to primaryAgent."
        }
      }
    },
    "kanban": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "backend": {
          "type": "string",
          "enum": ["internal", "github", "jira", "repo-mirror"]
        },
        "syncPolicy": {
          "type": "string",
          "enum": ["internal-primary", "bidirectional"],
          "default": "internal-primary"
        },
        "projectId": {
          "type": "string"
        },
        "github": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "project": {
              "type": "object",
              "additionalProperties": false,
              "description": "GitHub Projects v2 integration settings",
              "properties": {
                "mode": {
                  "type": "string",
                  "enum": ["issues", "kanban"],
                  "default": "issues",
                  "description": "Task source mode: 'issues' for repo issues only, 'kanban' for project board sync"
                },
                "owner": {
                  "type": "string",
                  "description": "GitHub org/user that owns the project board"
                },
                "number": {
                  "type": ["string", "number"],
                  "description": "GitHub project number"
                },
                "title": {
                  "type": "string",
                  "description": "Project title for auto-detection"
                },
                "autoSync": {
                  "type": "boolean",
                  "default": true,
                  "description": "Auto-sync task status to project board Status field"
                },
                "statusMapping": {
                  "type": "object",
                  "additionalProperties": false,
                  "description": "Map internal statuses to project board column names",
                  "properties": {
                    "todo": {
                      "type": "string",
                      "default": "Todo"
                    },
                    "inprogress": {
                      "type": "string",
                      "default": "In Progress"
                    },
                    "inreview": {
                      "type": "string",
                      "default": "In Review"
                    },
                    "done": {
                      "type": "string",
                      "default": "Done"
                    },
                    "cancelled": {
                      "type": "string",
                      "default": "Cancelled"
                    }
                  }
                },
                "webhook": {
                  "type": "object",
                  "additionalProperties": false,
                  "description": "GitHub project webhook settings for near-real-time sync triggers",
                  "properties": {
                    "path": {
                      "type": "string",
                      "description": "HTTP path exposed by ui-server for GitHub webhook deliveries"
                    },
                    "secret": {
                      "type": "string",
                      "description": "Shared secret used to validate X-Hub-Signature-256"
                    },
                    "requireSignature": {
                      "type": "boolean",
                      "description": "Require a valid webhook signature before accepting payloads"
                    }
                  }
                },
                "syncMonitoring": {
                  "type": "object",
                  "additionalProperties": false,
                  "description": "Monitoring and alert thresholds for project-sync failures and rate-limits",
                  "properties": {
                    "alertFailureThreshold": {
                      "type": "number",
                      "description": "Consecutive webhook/sync failures that trigger an alert",
                      "default": 3
                    },
                    "rateLimitAlertThreshold": {
                      "type": "number",
                      "description": "Rate-limit events counted before triggering an alert",
                      "default": 3
                    }
                  }
                }
              }
            }
          }
        },
        "jira": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "baseUrl": {
              "type": "string",
              "description": "Jira Cloud base URL (e.g. https://your-domain.atlassian.net)"
            },
            "email": {
              "type": "string",
              "description": "Jira account email used for API authentication"
            },
            "apiToken": {
              "type": "string",
              "description": "Jira API token used for Basic authentication"
            },
            "projectKey": {
              "type": "string",
              "description": "Default Jira project key used for list/create operations"
            },
            "issueType": {
              "type": "string",
              "default": "Task",
              "description": "Default Jira issue type for new tasks"
            },
            "statusMapping": {
              "type": "object",
              "additionalProperties": false,
              "description": "Map internal statuses to Jira workflow status names",
              "properties": {
                "todo": {
                  "type": "string",
                  "default": "To Do"
                },
                "inprogress": {
                  "type": "string",
                  "default": "In Progress"
                },
                "inreview": {
                  "type": "string",
                  "default": "In Review"
                },
                "done": {
                  "type": "string",
                  "default": "Done"
                },
                "cancelled": {
                  "type": "string",
                  "default": "Cancelled"
                }
              }
            },
            "labels": {
              "type": "object",
              "additionalProperties": false,
              "description": "Jira labels used to mark codex shared-state lifecycle",
              "properties": {
                "claimed": {
                  "type": "string",
                  "default": "codex:claimed"
                },
                "working": {
                  "type": "string",
                  "default": "codex:working"
                },
                "stale": {
                  "type": "string",
                  "default": "codex:stale"
                },
                "ignore": {
                  "type": "string",
                  "default": "codex:ignore"
                }
              }
            },
            "sharedStateFields": {
              "type": "object",
              "additionalProperties": false,
              "description": "Custom field IDs used to persist shared-state payload",
              "properties": {
                "ownerId": {
                  "type": "string",
                  "description": "Custom field ID for sharedState.ownerId"
                },
                "attemptToken": {
                  "type": "string",
                  "description": "Custom field ID for sharedState.attemptToken"
                },
                "attemptStarted": {
                  "type": "string",
                  "description": "Custom field ID for sharedState.attemptStarted (ISO timestamp)"
                },
                "heartbeat": {
                  "type": "string",
                  "description": "Custom field ID for sharedState.heartbeat (ISO timestamp)"
                },
                "retryCount": {
                  "type": "string",
                  "description": "Custom field ID for sharedState.retryCount"
                },
                "ignoreReason": {
                  "type": "string",
                  "description": "Optional custom field ID for ignore reason"
                }
              }
            }
          }
        },
        "repoMirror": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "enabled": {
              "type": "boolean",
              "default": false,
              "description": "Enable the optional RepoMirror projection backend. Must be true before selecting KANBAN_BACKEND=repo-mirror."
            },
            "repoPath": {
              "type": "string",
              "description": "Absolute path to the repo or clone that will host RepoMirror projection data."
            },
            "syncMode": {
              "type": "string",
              "enum": ["projection"],
              "default": "projection",
              "description": "Projection-only RepoMirror synchronization mode. Bosun keeps live runtime state in private storage."
            },
            "runStorage": {
              "type": "string",
              "enum": ["git", "local"],
              "default": "git",
              "description": "Where RepoMirror run metadata is stored when projection export is enabled."
            },
            "messageStorage": {
              "type": "string",
              "enum": ["off", "git", "local"],
              "default": "off",
              "description": "Where RepoMirror message projections are stored. 'off' keeps agent-to-agent traffic private by default."
            },
            "publicRoadmapEnabled": {
              "type": "boolean",
              "default": false,
              "description": "Allow sanitized public RepoMirror roadmap projection when explicitly enabled."
            }
          }
        }
      }
    },
    "plannerMode": {
      "type": "string",
      "enum": ["codex-sdk", "kanban", "disabled"]
    },
    "triggerSystem": {
      "type": "object",
      "additionalProperties": true,
      "properties": {
        "enabled": {
          "type": "boolean",
          "default": false
        },
        "templates": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": true,
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "description": {
                "type": "string"
              },
              "enabled": {
                "type": "boolean",
                "default": false
              },
              "action": {
                "type": "string",
                "enum": ["task-planner", "create-task"]
              },
              "minIntervalMinutes": {
                "type": "number",
                "minimum": 1
              },
              "trigger": {
                "type": "object",
                "additionalProperties": true,
                "properties": {
                  "anyOf": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "additionalProperties": true,
                      "properties": {
                        "kind": {
                          "type": "string",
                          "enum": ["metric", "interval"]
                        },
                        "metric": {
                          "type": "string"
                        },
                        "operator": {
                          "type": "string",
                          "enum": ["lt", "lte", "gt", "gte", "eq", "neq"]
                        },
                        "value": {
                          "type": ["number", "string", "boolean"]
                        },
                        "minutes": {
                          "type": "number",
                          "minimum": 1
                        }
                      }
                    }
                  }
                }
              },
              "config": {
                "type": "object",
                "additionalProperties": true,
                "properties": {
                  "plannerMode": {
                    "type": "string",
                    "enum": ["codex-sdk", "kanban", "disabled"]
                  },
                  "defaultTaskCount": {
                    "type": "number",
                    "minimum": 1
                  },
                  "title": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  },
                  "priority": {
                    "type": "string"
                  },
                  "executor": {
                    "type": "string"
                  },
                  "model": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "defaults": {
          "type": "object",
          "additionalProperties": true,
          "properties": {
            "executor": {
              "type": "string"
            },
            "model": {
              "type": "string"
            }
          }
        }
      }
    },
    "activeWorkspace": {
      "type": "string",
      "description": "ID of the currently active workspace"
    },
    "workspaces": {
      "type": "array",
      "description": "Multi-repo workspace definitions",
      "items": {
        "type": "object",
        "additionalProperties": true,
        "required": ["id", "name"],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique workspace identifier (lowercase, alphanumeric, dashes)"
          },
          "name": {
            "type": "string",
            "description": "Human-readable workspace name"
          },
          "repos": {
            "type": "array",
            "description": "Repositories in this workspace",
            "items": {
              "type": "object",
              "additionalProperties": true,
              "required": ["name"],
              "properties": {
                "name": {
                  "type": "string",
                  "description": "Repository directory name"
                },
                "url": {
                  "type": "string",
                  "description": "Git clone URL"
                },
                "slug": {
                  "type": "string",
                  "description": "GitHub slug (org/repo)"
                },
                "primary": {
                  "type": "boolean",
                  "description": "Whether this is the primary repo"
                },
                "branch": {
                  "type": "string",
                  "description": "Default branch to track"
                }
              }
            }
          },
          "activeRepo": {
            "type": ["string", "null"],
            "description": "Currently active repository name within the workspace"
          },
          "createdAt": {
            "type": "string",
            "description": "ISO 8601 creation timestamp"
          }
        }
      }
    },
    "defaultRepository": {
      "type": "string"
    },
    "repositoryDefaults": {
      "$ref": "#/$defs/repositoryDefaults"
    },
    "repositories": {
      "oneOf": [
        {
          "type": "array",
          "items": {
            "$ref": "#/$defs/repository"
          }
        },
        {
          "type": "object",
          "additionalProperties": true,
          "properties": {
            "default": {
              "type": "string"
            },
            "defaults": {
              "$ref": "#/$defs/repositoryDefaults"
            },
            "items": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/repository"
              }
            },
            "list": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/repository"
              }
            }
          }
        }
      ]
    },
    "internalExecutor": {
      "type": "object",
      "additionalProperties": true,
      "properties": {
        "mode": {
          "type": "string",
          "enum": ["internal", "hybrid"]
        },
        "maxParallel": {
          "type": "number"
        },
        "baseBranchParallelLimit": {
          "type": "number"
        },
        "pollIntervalMs": {
          "type": "number"
        },
        "sdk": {
          "type": "string",
          "enum": ["auto", "codex", "copilot", "claude", "gemini", "opencode"]
        },
        "taskTimeoutMs": {
          "type": "number"
        },
        "maxRetries": {
          "type": "number"
        },
        "reviewAgentEnabled": {
          "type": "boolean"
        },
        "reviewMaxConcurrent": {
          "type": "number"
        },
        "reviewTimeoutMs": {
          "type": "number"
        },
        "stream": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "maxRetries": {
              "type": "number",
              "description": "Transient stream retry attempts per run"
            },
            "retryBaseMs": {
              "type": "number",
              "description": "Base stream retry delay in milliseconds"
            },
            "retryMaxMs": {
              "type": "number",
              "description": "Maximum stream retry delay in milliseconds"
            },
            "firstEventTimeoutMs": {
              "type": "number",
              "description": "Abort/retry if no stream events arrive within this timeout"
            },
            "maxItemsPerTurn": {
              "type": "number",
              "description": "Maximum completed stream items retained per turn"
            },
            "maxItemChars": {
              "type": "number",
              "description": "Maximum characters retained per string field in stored stream items"
            }
          }
        }
      }
    },
    "providers": {
      "type": "object",
      "additionalProperties": false,
      "description": "Unified provider-kernel settings for auth mode, enablement, and model selection across chat, workflow, TUI, and Telegram surfaces.",
      "properties": {
        "defaultProvider": {
          "type": "string",
          "enum": ["openai-responses", "openai-codex-subscription", "azure-openai-responses", "anthropic-messages", "claude-subscription-shim", "openai-compatible", "ollama", "copilot-oauth", "openrouter", "perplexity", "deepinfra", "groq", "together", "xai", "fireworks", "cerebras", "sambanova", "nebius", "gemini-generate-content"],
          "default": "openai-responses"
        },
        "defaultModel": {
          "type": "string"
        },
        "openai": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "enabled": { "type": "boolean", "default": true },
            "defaultModel": { "type": "string" }
          }
        },
        "chatgptCodex": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "enabled": { "type": "boolean", "default": false },
            "mode": {
              "type": "string",
              "enum": ["subscription", "oauth", "apiKey"],
              "default": "subscription"
            },
            "defaultModel": { "type": "string" },
            "workspace": { "type": "string" }
          }
        },
        "azureOpenai": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "enabled": { "type": "boolean", "default": false },
            "mode": {
              "type": "string",
              "enum": ["apiKey", "oauth"],
              "default": "apiKey"
            },
            "defaultModel": { "type": "string" },
            "endpoint": { "type": "string" },
            "deployment": { "type": "string" },
            "apiVersion": { "type": "string" }
          }
        },
        "anthropic": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "enabled": { "type": "boolean", "default": true },
            "defaultModel": { "type": "string" }
          }
        },
        "claudeSubscription": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "enabled": { "type": "boolean", "default": false },
            "mode": {
              "type": "string",
              "enum": ["subscription", "oauth"],
              "default": "subscription"
            },
            "defaultModel": { "type": "string" },
            "workspace": { "type": "string" }
          }
        },
        "openaiCompatible": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "enabled": { "type": "boolean", "default": false },
            "mode": {
              "type": "string",
              "enum": ["apiKey", "local"],
              "default": "apiKey"
            },
            "defaultModel": { "type": "string" },
            "baseUrl": { "type": "string" }
          }
        },
        "ollama": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "enabled": { "type": "boolean", "default": false },
            "defaultModel": { "type": "string" },
            "baseUrl": { "type": "string" }
          }
        },
        "copilot": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "enabled": { "type": "boolean", "default": false },
            "defaultModel": { "type": "string" }
          }
        },
        "openrouter": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "enabled": { "type": "boolean", "default": false },
            "defaultModel": { "type": "string" },
            "baseUrl": { "type": "string" }
          }
        },
        "perplexity": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "enabled": { "type": "boolean", "default": false },
            "defaultModel": { "type": "string" },
            "baseUrl": { "type": "string" }
          }
        },
        "deepinfra": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "enabled": { "type": "boolean", "default": false },
            "defaultModel": { "type": "string" },
            "baseUrl": { "type": "string" }
          }
        },
        "groq": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "enabled": { "type": "boolean", "default": false },
            "defaultModel": { "type": "string" },
            "baseUrl": { "type": "string" }
          }
        },
        "together": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "enabled": { "type": "boolean", "default": false },
            "defaultModel": { "type": "string" },
            "baseUrl": { "type": "string" }
          }
        },
        "xai": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "enabled": { "type": "boolean", "default": false },
            "defaultModel": { "type": "string" },
            "baseUrl": { "type": "string" }
          }
        },
        "fireworks": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "enabled": { "type": "boolean", "default": false },
            "defaultModel": { "type": "string" },
            "baseUrl": { "type": "string" }
          }
        },
        "cerebras": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "enabled": { "type": "boolean", "default": false },
            "defaultModel": { "type": "string" },
            "baseUrl": { "type": "string" }
          }
        },
        "sambanova": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "enabled": { "type": "boolean", "default": false },
            "defaultModel": { "type": "string" },
            "baseUrl": { "type": "string" }
          }
        },
        "nebius": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "enabled": { "type": "boolean", "default": false },
            "defaultModel": { "type": "string" },
            "baseUrl": { "type": "string" }
          }
        },
        "gemini": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "enabled": { "type": "boolean", "default": true },
            "defaultModel": { "type": "string" },
            "baseUrl": { "type": "string" }
          }
        }
      }
    },
    "profiles": {
      "$ref": "#/$defs/profiles"
    },
    "envProfiles": {
      "$ref": "#/$defs/profiles"
    },
    "executors": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/executor"
      }
    },
    "failover": {
      "$ref": "#/$defs/failover"
    },
    "distribution": {
      "type": "string",
      "enum": ["weighted", "round-robin", "primary-only"]
    },
    "agentPrompts": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "orchestrator": {
          "type": "string"
        },
        "planner": {
          "type": "string"
        },
        "monitorMonitor": {
          "type": "string"
        },
        "taskExecutor": {
          "type": "string"
        },
        "taskExecutorRetry": {
          "type": "string"
        },
        "taskExecutorContinueHasCommits": {
          "type": "string"
        },
        "taskExecutorContinueHasEdits": {
          "type": "string"
        },
        "taskExecutorContinueNoProgress": {
          "type": "string"
        },
        "reviewer": {
          "type": "string"
        },
        "conflictResolver": {
          "type": "string"
        },
        "sdkConflictResolver": {
          "type": "string"
        },
        "mergeStrategy": {
          "type": "string"
        },
        "mergeStrategyFix": {
          "type": "string"
        },
        "mergeStrategyReAttempt": {
          "type": "string"
        },
        "autofixFix": {
          "type": "string"
        },
        "autofixFallback": {
          "type": "string"
        },
        "autofixLoop": {
          "type": "string"
        },
        "monitorCrashFix": {
          "type": "string"
        },
        "monitorRestartLoopFix": {
          "type": "string"
        }
      }
    },
    "hookProfiles": {
      "$ref": "#/$defs/hookProfiles"
    },
    "agentHooks": {
      "$ref": "#/$defs/agentHooks"
    },
    "auth": {
      "type": "object",
      "description": "Authentication configuration for agent SDKs",
      "additionalProperties": false,
      "properties": {
        "copilot": {
          "type": "object",
          "properties": {
            "sources": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": ["env", "cli", "vscode", "interactive"]
              },
              "description": "Auth source priority: env (tokens), cli (gh auth), vscode (extension), interactive (prompt)"
            },
            "fallbackToInteractive": {
              "type": "boolean",
              "description": "Allow interactive login if all other sources fail"
            }
          }
        },
        "claude": {
          "type": "object",
          "properties": {
            "sources": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": ["env", "cli", "interactive"]
              },
              "description": "Auth source priority: env (API key), cli (config file), interactive (prompt)"
            },
            "fallbackToInteractive": {
              "type": "boolean",
              "description": "Allow interactive API key prompt if all other sources fail"
            }
          }
        },
        "codex": {
          "type": "object",
          "properties": {
            "sources": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": ["config", "env", "interactive"]
              },
              "description": "Auth source priority: config (config.toml), env (API key), interactive (prompt)"
            },
            "fallbackToInteractive": {
              "type": "boolean",
              "description": "Allow interactive configuration if all other sources fail"
            }
          }
        }
      }
    },
    "workflows": {
      "type": "object",
      "description": "Declarative multi-agent pipeline workflows runnable via bosun workflow run <name>.",
      "additionalProperties": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": ["sequential", "fanout", "race"]
          },
          "description": {
            "type": "string"
          },
          "stages": {
            "type": "array",
            "items": {
              "oneOf": [
                {
                  "type": "string"
                },
                {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "stage": {
                      "type": "string"
                    },
                    "prompt": {
                      "type": "string"
                    },
                    "promptTemplate": {
                      "type": "string"
                    },
                    "sdk": {
                      "type": "string"
                    },
                    "model": {
                      "type": "string"
                    },
                    "cwd": {
                      "type": "string"
                    },
                    "timeoutMs": {
                      "type": "number"
                    }
                  }
                }
              ]
            }
          },
          "agents": {
            "type": "array",
            "items": {
              "oneOf": [
                {
                  "type": "string"
                },
                {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "stage": {
                      "type": "string"
                    },
                    "prompt": {
                      "type": "string"
                    },
                    "promptTemplate": {
                      "type": "string"
                    },
                    "sdk": {
                      "type": "string"
                    },
                    "model": {
                      "type": "string"
                    },
                    "cwd": {
                      "type": "string"
                    },
                    "timeoutMs": {
                      "type": "number"
                    }
                  }
                }
              ]
            }
          }
        }
      }
    }
  },
  "$defs": {
    "executor": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "name": {
          "type": "string"
        },
        "executor": {
          "type": "string"
        },
        "variant": {
          "type": "string"
        },
        "models": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "weight": {
          "type": "number"
        },
        "role": {
          "type": "string"
        },
        "enabled": {
          "type": "boolean"
        },
        "provider": {
          "type": "string",
          "description": "AI provider for this executor (e.g. anthropic, openai, ollama, nebius, scaleway, deepinfra, qiniu, cloudflare, xiaomi, synthetic, perplexity)"
        },
        "providerConfig": {
          "type": "object",
          "description": "Provider-specific configuration for this executor",
          "properties": {
            "apiKey": {
              "type": "string",
              "description": "API key for this provider (overrides env)"
            },
            "baseUrl": {
              "type": "string",
              "description": "API base URL for this provider"
            },
            "model": {
              "type": "string",
              "description": "Model ID to use with this provider (e.g. claude-sonnet-4-20250514)"
            },
            "port": {
              "type": "number",
              "description": "Port for local server (OpenCode)"
            },
            "timeoutMs": {
              "type": "number",
              "description": "Request timeout in milliseconds"
            }
          }
        }
      }
    },
    "failover": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "strategy": {
          "type": "string",
          "enum": ["next-in-line", "weighted-random", "round-robin"]
        },
        "maxRetries": {
          "type": "number"
        },
        "cooldownMinutes": {
          "type": "number"
        },
        "disableOnConsecutiveFailures": {
          "type": "number"
        }
      }
    },
    "repositoryDefaults": {
      "type": "object",
      "additionalProperties": true,
      "properties": {
        "path": {
          "type": "string"
        },
        "slug": {
          "type": "string"
        },
        "projectName": {
          "type": "string"
        },
        "orchestratorScript": {
          "type": "string"
        },
        "orchestratorArgs": {
          "type": "string"
        },
        "logDir": {
          "type": "string"
        },
        "watchPath": {
          "type": "string"
        },
        "profile": {
          "type": "string"
        },
        "envProfile": {
          "type": "string"
        },
        "mode": {
          "type": "string"
        }
      }
    },
    "repository": {
      "type": "object",
      "additionalProperties": true,
      "properties": {
        "name": {
          "type": "string"
        },
        "id": {
          "type": "string"
        },
        "aliases": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "path": {
          "type": "string"
        },
        "repoRoot": {
          "type": "string"
        },
        "slug": {
          "type": "string"
        },
        "repo": {
          "type": "string"
        },
        "repoUrlBase": {
          "type": "string"
        },
        "projectName": {
          "type": "string"
        },
        "primary": {
          "type": "boolean"
        },
        "orchestratorScript": {
          "type": "string"
        },
        "orchestratorArgs": {
          "type": "string"
        },
        "logDir": {
          "type": "string"
        },
        "watchPath": {
          "type": "string"
        },
        "profile": {
          "type": "string"
        },
        "envProfile": {
          "type": "string"
        },
        "mode": {
          "type": "string"
        },
        "cacheDir": {
          "type": "string"
        },
        "statusPath": {
          "type": "string"
        },
        "telegramPollLockPath": {
          "type": "string"
        }
      }
    },
    "profiles": {
      "type": "object",
      "additionalProperties": {
        "type": "object",
        "additionalProperties": true,
        "properties": {
          "description": {
            "type": "string"
          },
          "env": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "envFile": {
            "type": "string"
          },
          "envOverride": {
            "type": "boolean"
          },
          "repository": {
            "type": "string"
          },
          "repo": {
            "type": "string"
          },
          "defaultRepository": {
            "type": "string"
          },
          "overrides": {
            "type": "object"
          },
          "config": {
            "type": "object"
          },
          "settings": {
            "type": "object"
          }
        }
      }
    },
    "hookProfiles": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "enabled": {
          "type": "boolean"
        },
        "profile": {
          "type": "string",
          "enum": ["strict", "balanced", "lightweight", "none"]
        },
        "targets": {
          "type": "array",
          "items": {
            "type": "string",
            "enum": ["codex", "claude", "copilot"]
          }
        },
        "overwriteExisting": {
          "type": "boolean"
        }
      }
    },
    "agentHooks": {
      "type": "object",
      "description": "Hook definitions loaded by agent-hooks.mjs (event -> hook list).",
      "additionalProperties": true
    },
    "mcpServers": {
      "type": "object",
      "description": "MCP (Model Context Protocol) server management. Controls which MCP servers are available to agents.",
      "additionalProperties": false,
      "properties": {
        "enabled": {
          "type": "boolean",
          "default": true,
          "description": "Enable MCP server integration for agent launches"
        },
        "defaultServers": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "MCP server IDs attached to every agent launch by default (e.g. [\"context7\", \"microsoft-docs\"])"
        },
        "catalogOverrides": {
          "type": "object",
          "additionalProperties": {
            "type": "object",
            "description": "Per-server environment variable overrides",
            "additionalProperties": {
              "type": "string"
            }
          },
          "description": "Environment variable overrides keyed by MCP server ID"
        },
        "useDiscoveryProxy": {
          "type": "boolean",
          "default": true,
          "description": "Wrap resolved MCP servers behind Bosun's compact search/schema/call discovery proxy to reduce tool-definition prompt overhead."
        },
        "includeCustomToolsInDiscoveryProxy": {
          "type": "boolean",
          "default": true,
          "description": "Expose Bosun custom tools through the discovery proxy alongside external MCP servers."
        },
        "discoveryProxyCacheTtlMs": {
          "type": "integer",
          "minimum": 1000,
          "default": 60000,
          "description": "How long Bosun caches wrapped MCP tool catalogs inside the discovery proxy before refreshing them."
        },
        "discoveryProxyExecuteTimeoutMs": {
          "type": "integer",
          "minimum": 1000,
          "default": 10000,
          "description": "Default timeout for the discovery proxy execute tool, which runs short orchestration code against discovered tools."
        },
        "autoInstallDefaults": {
          "type": "boolean",
          "default": true,
          "description": "Automatically install defaultServers from catalog if not already installed"
        }
      }
    },
    "contextShredding": {
      "type": "object",
      "description": "Context Shredding — configurable tiered compression of agent context windows. Reduces token usage while preserving what matters.",
      "additionalProperties": false,
      "properties": {
        "enabled": {
          "type": "boolean",
          "default": true,
          "description": "Master switch for context shredding. When false, agents receive full history every turn."
        },
        "fullContextTurns": {
          "type": "integer",
          "minimum": 1,
          "maximum": 20,
          "default": 3,
          "description": "Number of most-recent turns to keep completely uncompressed (Tier 0)."
        },
        "tier1MaxAge": {
          "type": "integer",
          "minimum": 1,
          "maximum": 50,
          "default": 5,
          "description": "Turns threshold for Tier 1 (light) compression."
        },
        "tier2MaxAge": {
          "type": "integer",
          "minimum": 2,
          "maximum": 100,
          "default": 9,
          "description": "Turns threshold for Tier 2 (moderate) compression. Items older enter Tier 3 (skeleton)."
        },
        "tier1HeadChars": {
          "type": "integer",
          "minimum": 100,
          "maximum": 10000,
          "default": 2000,
          "description": "Maximum characters kept from the start of a tool output in Tier 1 compression."
        },
        "tier1TailChars": {
          "type": "integer",
          "minimum": 0,
          "maximum": 5000,
          "default": 800,
          "description": "Maximum characters kept from the end of a tool output in Tier 1 compression."
        },
        "tier2HeadChars": {
          "type": "integer",
          "minimum": 50,
          "maximum": 5000,
          "default": 600,
          "description": "Maximum characters kept from the start of a tool output in Tier 2 compression."
        },
        "tier2TailChars": {
          "type": "integer",
          "minimum": 0,
          "maximum": 2000,
          "default": 300,
          "description": "Maximum characters kept from the end of a tool output in Tier 2 compression."
        },
        "scoreHighThreshold": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 70,
          "description": "Items scored >= this value are protected from compression (tier shifted down)."
        },
        "scoreLowThreshold": {
          "type": "integer",
          "minimum": 0,
          "maximum": 99,
          "default": 30,
          "description": "Items scored < this value are compressed more aggressively."
        },
        "compressToolOutputs": {
          "type": "boolean",
          "default": true,
          "description": "Enable tiered compression for tool call outputs."
        },
        "compressMessages": {
          "type": "boolean",
          "default": true,
          "description": "Enable compression for agent reasoning and user prompt messages."
        },
        "compressAgentMessages": {
          "type": "boolean",
          "default": true,
          "description": "Enable compression for verbose agent thinking/planning messages."
        },
        "compressUserMessages": {
          "type": "boolean",
          "default": true,
          "description": "Compress old user prompt messages to a short breadcrumb. Current turn always kept full."
        },
        "msgTier0MaxAge": {
          "type": "integer",
          "minimum": 0,
          "maximum": 10,
          "default": 1,
          "description": "Number of most-recent turns to keep agent messages in full text."
        },
        "msgTier1MaxAge": {
          "type": "integer",
          "minimum": 1,
          "maximum": 20,
          "default": 4,
          "description": "Turns within which agent messages get a moderate summary. Older messages become one-line breadcrumbs."
        },
        "msgMinCompressChars": {
          "type": "integer",
          "minimum": 0,
          "maximum": 2000,
          "default": 120,
          "description": "Agent messages shorter than this are never compressed."
        },
        "userMsgFullTurns": {
          "type": "integer",
          "minimum": 0,
          "maximum": 10,
          "default": 1,
          "description": "Turns during which the full user prompt is preserved."
        },
        "liveToolCompactionEnabled": {
          "type": "boolean",
          "default": false,
          "description": "Enable command-aware live compaction of large tool outputs before they are stored in the active turn."
        },
        "liveToolCompactionMode": {
          "type": "string",
          "enum": ["off", "auto", "aggressive"],
          "default": "auto",
          "description": "off disables live compaction, auto compacts only when pressure or signal justify it, and aggressive favors stronger reduction for noisy command families."
        },
        "liveToolCompactionMinChars": {
          "type": "integer",
          "minimum": 500,
          "maximum": 500000,
          "default": 4000,
          "description": "Minimum output size before live compaction is considered."
        },
        "liveToolCompactionTargetChars": {
          "type": "integer",
          "minimum": 200,
          "maximum": 50000,
          "default": 1800,
          "description": "Target upper bound for compacted live command output before retrieval hints and metadata."
        },
        "liveToolCompactionMinSavingsPct": {
          "type": "integer",
          "minimum": 0,
          "maximum": 95,
          "default": 15,
          "description": "Discard compacted output if it does not save at least this much space."
        },
        "liveToolCompactionMinRuntimeMs": {
          "type": "integer",
          "minimum": 0,
          "maximum": 3600000,
          "default": 2000,
          "description": "When command duration metadata is present, require at least this runtime before compacting in auto mode."
        },
        "liveToolCompactionBlockStructured": {
          "type": "boolean",
          "default": true,
          "description": "Avoid live compaction for likely JSON or other structured outputs where exact bytes matter more than size."
        },
        "liveToolCompactionAllowCommands": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [
            "grep",
            "rg",
            "find",
            "git",
            "go",
            "npm",
            "pnpm",
            "yarn",
            "node",
            "python",
            "python3",
            "pytest",
            "docker",
            "kubectl",
            "cargo",
            "gradle",
            "maven",
            "mvn",
            "javac",
            "tsc",
            "jest",
            "vitest",
            "deno"
          ],
          "description": "Command or tool families eligible for live compaction."
        },
        "perType": {
          "type": "object",
          "description": "Per-interaction-type config overrides. Keys: task, manual, primary, chat, voice, flow.",
          "additionalProperties": {
            "type": "object"
          }
        },
        "perAgent": {
          "type": "object",
          "description": "Per-agent-SDK config overrides. Keys: codex-sdk, copilot-sdk, claude-sdk, gemini-sdk, opencode-sdk.",
          "additionalProperties": {
            "type": "object"
          }
        }
      }
    },
    "toolLogCache": {
      "type": "object",
      "description": "In-memory caching of full tool log content for fast agent retrieval during active sessions. Reduces disk I/O on repeated context lookups.",
      "additionalProperties": false,
      "properties": {
        "enabled": {
          "type": "boolean",
          "default": false,
          "description": "When true, full tool log content is kept in-process memory for fast retrieval (avoids disk reads). Improves context retrieval speed during long agent sessions."
        },
        "maxSizeBytes": {
          "type": "integer",
          "minimum": 1048576,
          "default": 52428800,
          "description": "Maximum total bytes to hold in the in-memory tool-log cache (default: 50 MB). Oldest entries are evicted (LRU order) when this limit is exceeded."
        },
        "archiveSizeLimitBytes": {
          "type": "integer",
          "minimum": 10485760,
          "default": 209715200,
          "description": "Disk prune trigger: when the .cache/tool-logs/ directory exceeds this size, pruneToolLogCache is run automatically to reclaim space (default: 200 MB)."
        }
      }
    }
  }
}
