{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://github.com/mmerterden/multi-agent-pipeline/pipeline/schemas/design-check-config.schema.json",
  "title": "Design Check Configuration",
  "description": "Optional per-project config for /multi-agent:design-check. Stored at ~/.claude/projects/{slug}/design-check-config.json. Never committed. Everything here is optional: design_mock_detect auto-detects mock support and design_scenario_inventory auto-enumerates state drivers at run time; this file only overrides or augments that detection (extra mock switch keys, extra launch args / targets no source signal reveals, explicit variant->Figma-node mappings, status-bar crop, coverage floor, Confluence toggle). Keeps the engine generic - project specifics live here, never in shipped code.",
  "type": "object",
  "additionalProperties": false,
  "required": ["schemaVersion"],
  "properties": {
    "schemaVersion": { "type": "string", "const": "1.0.0" },
    "platform": {
      "type": "string",
      "enum": ["ios", "android"],
      "description": "Override auto platform detection."
    },
    "mock": {
      "type": "object",
      "additionalProperties": false,
      "description": "Mock-mode overrides. Omit to rely purely on auto-detection.",
      "properties": {
        "keys": {
          "type": "array",
          "items": { "type": "string" },
          "description": "Extra UserDefaults / launch-arg switch keys to look for (passed as extra_keys to design_mock_detect)."
        },
        "launchArg": {
          "type": "string",
          "description": "Explicit iOS launch argument to force mock mode, e.g. '-debugMockMode YES'. Overrides the detected one."
        },
        "intentExtra": {
          "type": "string",
          "description": "Explicit Android intent extra, e.g. '--ez mockEnabled true'."
        },
        "buildConfig": {
          "type": "string",
          "description": "Build configuration that compiles the mocks (default 'Debug')."
        }
      }
    },
    "inventory": {
      "type": "object",
      "additionalProperties": false,
      "description": "Augments design_scenario_inventory, which decides the audit's target set. Only for states no source signal can reveal - everything detectable is detected.",
      "properties": {
        "targetsFile": {
          "type": "string",
          "description": "Path to a JSON target catalog (a bare array, or { version: 1, platform?, description?, targets }) passed to design_scenario_inventory as targets_file. When set, source scanning is skipped and the catalog is the target set; plan, groups, relaunch count and the coverage gate work unchanged. For repos whose state drivers no source signal reveals, such as a debug menu over a stub library."
        },
        "extraLaunchArgs": {
          "type": "array",
          "items": { "type": "string" },
          "description": "Launch args (iOS) / boolean intent-extra keys (Android) that drive a distinct state but appear in no scanned literal."
        },
        "extraTargets": {
          "type": "array",
          "description": "Fully hand-declared targets, for states reachable only by a documented manual step.",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": ["id"],
            "properties": {
              "id": {
                "type": "string",
                "description": "Stable target id, e.g. 'config:gallery-3d'."
              },
              "kind": { "type": "string", "description": "Target kind label (default 'config')." },
              "label": { "type": "string" },
              "screen": {
                "type": "string",
                "description": "Screen this target belongs to (groups the coverage report)."
              },
              "driver": {
                "type": "object",
                "additionalProperties": true,
                "description": "How to reach it: { type: 'manual', note } or any driver shape the runner understands."
              }
            }
          }
        },
        "ignoreTargets": {
          "type": "array",
          "items": { "type": "string" },
          "description": "Target ids to drop from the inventory entirely (dead drivers, states retired in code but still referenced). Unlike a skip, these never enter the coverage gate - use sparingly and prefer a skip with a reason."
        }
      }
    },
    "coverage": {
      "type": "object",
      "additionalProperties": false,
      "description": "Coverage gate tuning. The gate itself is not optional: a target is audited, or skipped with an explicit reason.",
      "properties": {
        "floor": {
          "type": "number",
          "minimum": 0,
          "maximum": 1,
          "description": "Additional hard floor on audited/target ratio (e.g. 0.9). Below it the gate fails even when every skip carries a reason."
        },
        "confirmAbove": {
          "type": "integer",
          "default": 25,
          "description": "Relaunch count (inventory.relaunchCount for the scoped set, NOT the target count) above which Phase 0 asks for confirmation. Relaunches are the run's real cost: one relaunch serves every in-app target on that screen. Whole-module remains the intended default - this threshold estimates cost, it does not invite shrinking the audit."
        }
      }
    },
    "figma": {
      "type": "object",
      "additionalProperties": false,
      "description": "Figma frame + variant mapping overrides.",
      "properties": {
        "url": {
          "type": "string",
          "description": "Default Figma MCP URL for this module's frame/page."
        },
        "frameSize": {
          "type": "object",
          "additionalProperties": false,
          "properties": { "w": { "type": "number" }, "h": { "type": "number" } },
          "description": "Figma frame size the spec coordinates are in (usually auto-read)."
        }
      }
    },
    "variants": {
      "type": "array",
      "description": "Explicit mock-variant -> Figma-node mappings. When present, the picker skips name-similarity guessing for these.",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": ["id", "figmaNodeId"],
        "properties": {
          "id": {
            "type": "string",
            "description": "Mock variant id (matches a variantsHint / fixture name)."
          },
          "label": { "type": "string" },
          "figmaNodeId": {
            "type": "string",
            "description": "Figma node id for this variant's frame."
          },
          "activation": {
            "type": "object",
            "additionalProperties": true,
            "description": "How to put the app into this variant (launch arg / UserDefaults values / navigation path)."
          }
        }
      }
    },
    "capture": {
      "type": "object",
      "additionalProperties": false,
      "description": "Capture / comparison tuning.",
      "properties": {
        "cropTopLive": {
          "type": "number",
          "description": "Pixels to crop from the top of the live capture (status bar)."
        },
        "tolerancePx": { "type": "number", "default": 2 },
        "colorTolerance": { "type": "number", "default": 3 },
        "maxDiffPct": { "type": "number", "default": 1.0 }
      }
    },
    "report": {
      "type": "object",
      "additionalProperties": false,
      "description": "Report output + export.",
      "properties": {
        "outputRoot": {
          "type": "string",
          "description": "Report root dir (default ~/DesignChecks)."
        },
        "formats": {
          "type": "array",
          "items": { "type": "string", "enum": ["html", "pdf", "confluence"] },
          "default": ["html", "pdf"]
        },
        "confluence": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "enabled": { "type": "boolean", "default": false },
            "space": { "type": "string" },
            "parentId": { "type": "string" }
          }
        }
      }
    }
  }
}
