{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://ecoclouddev.com/schemas/constitution.schema.json",
  "title": "EcoCloud Agent Constitution",
  "description": "Canonical, machine-readable schema for an EcoCloud Agent Constitution — the deterministic policy a workspace declares and that the constitution-kernel enforces BEFORE an agent's tool call executes (the action-layer gate, not model-layer alignment). Vendor-neutral and dependency-free: the same rules object validates here, runs in the browser/edge/Node kernel, and is enforced server-side. Apache-2.0. Prose spec: /constitution-spec/. Reference implementation: /kernel/flowdesk-constitution-kernel.js (window.FlowDeskConstitution.enforce).",
  "$comment": "Stable identifier for the v0.1 line. Adopt freely; this file is the source of truth for the rules object. Versioning is additive within v0.x; a breaking change bumps to a new $id.",
  "license": "Apache-2.0",
  "version": "0.1.0",
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "max_priority": {
      "description": "The highest task priority the agent may create or escalate to without human approval. An action above this is denied.",
      "enum": ["low", "medium", "high", "critical"]
    },
    "forbidden_terms": {
      "description": "Case-insensitive substrings that, if present in an action's text, deny it (e.g. 'wire transfer', 'delete production'). Per-agent lists union with the workspace list.",
      "type": "array",
      "items": { "type": "string", "minLength": 1 },
      "uniqueItems": true
    },
    "forbidden_assignees": {
      "description": "Identities an agent may never assign work to or act on behalf of (e.g. 'CEO').",
      "type": "array",
      "items": { "type": "string", "minLength": 1 },
      "uniqueItems": true
    },
    "forbidden_tags": {
      "description": "Tags that mark a task as out-of-bounds for autonomous action.",
      "type": "array",
      "items": { "type": "string", "minLength": 1 },
      "uniqueItems": true
    },
    "objective_tags": {
      "description": "Tags the agent is explicitly authorized to operate within (an allowlist complement to forbidden_tags).",
      "type": "array",
      "items": { "type": "string", "minLength": 1 },
      "uniqueItems": true
    },
    "quiet_hours_utc": {
      "description": "A UTC window during which autonomous writes are blocked (routed to human approval). start and end are hours 0–23; a window may wrap midnight (start > end).",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "start": { "type": "integer", "minimum": 0, "maximum": 23 },
        "end": { "type": "integer", "minimum": 0, "maximum": 23 }
      },
      "required": ["start", "end"]
    },
    "max_creates_per_day": {
      "description": "Hard daily cap on the number of create actions an agent may take in the workspace. 0 disables autonomous creates.",
      "type": "integer",
      "minimum": 0
    },
    "require_approval_below_confidence": {
      "description": "If the agent's self-reported confidence for an action is below this threshold, the action is staged for human approval rather than executed. 0 disables the gate; 1 requires approval for everything.",
      "type": "number",
      "minimum": 0,
      "maximum": 1
    },
    "require_approval_above_amount": {
      "description": "Route to human approval when the action carries a monetary amount above this threshold (e.g. a billing dispute over $10,000 needs a manager). Compared against action.amount when action.currency matches. Currency is a 3-letter ISO 4217 code (USD/EUR/GBP/…). amount is a positive integer in the MAJOR unit (dollars, not cents).",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "currency": { "type": "string", "minLength": 3, "maxLength": 3 },
        "amount": { "type": "integer", "minimum": 0 }
      },
      "required": ["currency", "amount"]
    },
    "approval_routes_to": {
      "description": "When an approval gate fires (value-threshold or confidence), pre-route the task to a specific approver. Single-step: { to: 'manager' | 'team', team_slug? }. Multi-step (Maker → Reviewer → CFO): { steps: [{ to, team_slug? }, …] }. 'manager' uses workspace_members.manager_id of the would-be assignee; 'team' uses the named team's current on-call / lightest-loaded member.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "to": { "enum": ["manager", "team"] },
        "team_slug": { "type": "string", "minLength": 1, "maxLength": 40 },
        "steps": {
          "type": "array",
          "minItems": 1,
          "maxItems": 8,
          "items": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "to": { "enum": ["manager", "team"] },
              "team_slug": { "type": "string", "minLength": 1, "maxLength": 40 }
            },
            "required": ["to"]
          }
        }
      }
    }
  },
  "examples": [
    {
      "max_priority": "high",
      "forbidden_terms": ["delete all", "wire transfer"],
      "forbidden_assignees": ["CEO"],
      "quiet_hours_utc": { "start": 22, "end": 6 },
      "max_creates_per_day": 200,
      "require_approval_below_confidence": 0.7
    }
  ]
}
