{
 "info": {
  "description": "Verifier-grounded evaluation tools for AI systems. Workbench and report-card requests are stateless and unauthenticated; payloads and results are not persisted. Open Promotion Bench may persist only an opt-in public manifest and sanitized receipt, never task contents or answers. Operational counters and standard access logs are retained.",
  "license": {
   "name": "AGPL-3.0-or-later",
   "url": "https://www.gnu.org/licenses/agpl-3.0.html"
  },
  "title": "Whetstone Tools",
  "version": "0.8.0",
  "x-build-commit": "780558024ed039fc19bd626d956b4bd3267d61f5"
 },
 "openapi": "3.1.0",
 "paths": {
  "/api/catalog": {
   "get": {
    "operationId": "listTools",
    "responses": {
     "200": {
      "description": "OK"
     }
    },
    "summary": "Catalog of the eight stateless verifier tools."
   }
  },
  "/api/counterexample": {
   "post": {
    "operationId": "counterexample",
    "requestBody": {
     "content": {
      "application/json": {
       "example": {
        "expression": "is_connected and is_triangle_free and not is_bipartite",
        "ns": [
         8,
         9,
         10,
         11
        ],
        "restarts": 4,
        "seed": 0,
        "steps": 800
       },
       "schema": {
        "additionalProperties": false,
        "description": "Run a bounded graph search against one Whetstone predicate expression.",
        "properties": {
         "expression": {
          "description": "Graph predicate in the Whetstone DSL, for example: is_connected and is_triangle_free and not is_bipartite",
          "maxLength": 500,
          "minLength": 1,
          "type": "string"
         },
         "ns": {
          "default": [
           8,
           9,
           10,
           11
          ],
          "description": "Graph sizes searched.",
          "items": {
           "maximum": 12,
           "minimum": 4,
           "type": "integer"
          },
          "maxItems": 5,
          "minItems": 1,
          "type": "array"
         },
         "restarts": {
          "default": 4,
          "maximum": 6,
          "minimum": 1,
          "type": "integer"
         },
         "seed": {
          "default": 0,
          "type": "integer"
         },
         "steps": {
          "default": 800,
          "maximum": 1500,
          "minimum": 50,
          "type": "integer"
         }
        },
        "required": [
         "expression"
        ],
        "type": "object"
       }
      }
     },
     "required": true
    },
    "responses": {
     "200": {
      "description": "Deterministic receipt with item-level decision path and SHA-256 hashes."
     },
     "400": {
      "description": "Input error (a hint points at /api/examples)."
     },
     "429": {
      "description": "Rate limited."
     }
    },
    "summary": "Search the supported graph DSL and return an exact witness when found."
   }
  },
  "/api/examples": {
   "get": {
    "operationId": "getExamples",
    "responses": {
     "200": {
      "description": "OK"
     }
    },
    "summary": "A complete, valid request payload for every tool."
   }
  },
  "/api/gate": {
   "post": {
    "operationId": "gate",
    "requestBody": {
     "content": {
      "application/json": {
       "example": {
        "baseline": {
         "item-1": false,
         "item-2": false,
         "item-3": false,
         "item-4": false,
         "item-5": false,
         "item-6": false,
         "item-7": false
        },
        "baseline_name": "v1",
        "candidate": {
         "item-1": true,
         "item-2": true,
         "item-3": true,
         "item-4": true,
         "item-5": true,
         "item-6": true,
         "item-7": false
        },
        "candidate_name": "v2",
        "domains": {
         "item-1": "code",
         "item-2": "code",
         "item-3": "code",
         "item-4": "code",
         "item-5": "support",
         "item-6": "support",
         "item-7": "support"
        },
        "policy": {
         "confidence_alpha": 0.05,
         "max_regressions": 0,
         "min_gains": 1
        }
       },
       "schema": {
        "additionalProperties": false,
        "description": "Compare identical baseline and candidate item cohorts under an explicit policy.",
        "properties": {
         "baseline": {
          "additionalProperties": {
           "type": "boolean"
          },
          "description": "item_id -> boolean pass/fail result for the baseline system.",
          "maxProperties": 5000,
          "minProperties": 1,
          "type": "object"
         },
         "baseline_name": {
          "default": "baseline",
          "type": "string"
         },
         "candidate": {
          "additionalProperties": {
           "type": "boolean"
          },
          "description": "item_id -> boolean pass/fail result for the candidate system.",
          "maxProperties": 5000,
          "minProperties": 1,
          "type": "object"
         },
         "candidate_name": {
          "default": "candidate",
          "type": "string"
         },
         "domains": {
          "additionalProperties": {
           "type": "string"
          },
          "description": "Optional item_id -> domain label mapping.",
          "type": "object"
         },
         "policy": {
          "additionalProperties": false,
          "description": "Explicit promotion policy. Omitted fields use the documented defaults.",
          "properties": {
           "confidence_alpha": {
            "default": 0.05,
            "exclusiveMinimum": 0,
            "maximum": 1,
            "type": "number"
           },
           "max_regressions": {
            "default": 0,
            "minimum": 0,
            "type": "integer"
           },
           "min_gains": {
            "default": 1,
            "minimum": 0,
            "type": "integer"
           },
           "require_retained_probe": {
            "default": false,
            "type": "boolean"
           }
          },
          "type": "object"
         },
         "retained_probe": {
          "additionalProperties": false,
          "description": "Optional retained-capability result checked alongside the paired cohort.",
          "properties": {
           "base_verified": {
            "minimum": 0,
            "type": "integer"
           },
           "candidate_verified": {
            "minimum": 0,
            "type": "integer"
           },
           "items": {
            "minimum": 0,
            "type": "integer"
           }
          },
          "required": [
           "base_verified",
           "candidate_verified",
           "items"
          ],
          "type": "object"
         }
        },
        "required": [
         "baseline",
         "candidate"
        ],
        "type": "object"
       }
      }
     },
     "required": true
    },
    "responses": {
     "200": {
      "description": "Deterministic receipt with item-level decision path and SHA-256 hashes."
     },
     "400": {
      "description": "Input error (a hint points at /api/examples)."
     },
     "429": {
      "description": "Rate limited."
     }
    },
    "summary": "PASS, HOLD, or BLOCK from paired item-level results."
   }
  },
  "/api/health": {
   "get": {
    "operationId": "health",
    "responses": {
     "200": {
      "description": "OK"
     }
    },
    "summary": "Service health, version, and report-card readiness."
   }
  },
  "/api/health-report": {
   "post": {
    "operationId": "health",
    "requestBody": {
     "content": {
      "application/json": {
       "example": {
        "history": [
         {
          "domain": "code",
          "item_id": "stable",
          "passed": true,
          "system": "small"
         },
         {
          "domain": "code",
          "item_id": "stable",
          "passed": true,
          "system": "medium"
         },
         {
          "domain": "code",
          "item_id": "stable",
          "passed": true,
          "system": "large"
         },
         {
          "domain": "code",
          "item_id": "frontier",
          "passed": false,
          "system": "small"
         },
         {
          "domain": "code",
          "item_id": "frontier",
          "passed": false,
          "system": "medium"
         },
         {
          "domain": "code",
          "item_id": "frontier",
          "passed": true,
          "system": "large"
         },
         {
          "domain": "support",
          "item_id": "hard",
          "passed": false,
          "system": "small"
         },
         {
          "domain": "support",
          "item_id": "hard",
          "passed": false,
          "system": "medium"
         },
         {
          "domain": "support",
          "item_id": "noisy",
          "passed": true,
          "system": "medium"
         },
         {
          "domain": "support",
          "item_id": "noisy",
          "passed": false,
          "system": "medium"
         },
         {
          "domain": "support",
          "item_id": "noisy",
          "passed": true,
          "system": "large"
         }
        ],
        "items": [
         {
          "domain": "code",
          "item_id": "stable"
         },
         {
          "domain": "code",
          "item_id": "frontier"
         },
         {
          "domain": "support",
          "item_id": "hard"
         },
         {
          "domain": "support",
          "item_id": "noisy"
         }
        ]
       },
       "schema": {
        "additionalProperties": false,
        "description": "Diagnose item lifecycle health from one or more grading-history rows.",
        "properties": {
         "history": {
          "description": "Observed item/system outcomes.",
          "items": {
           "additionalProperties": true,
           "properties": {
            "domain": {
             "type": "string"
            },
            "item_id": {
             "minLength": 1,
             "type": "string"
            },
            "passed": {
             "type": "boolean"
            },
            "system": {
             "minLength": 1,
             "type": "string"
            }
           },
           "required": [
            "item_id",
            "system",
            "passed"
           ],
           "type": "object"
          },
          "maxItems": 5000,
          "minItems": 1,
          "type": "array"
         },
         "items": {
          "description": "Optional item definitions.",
          "items": {
           "additionalProperties": true,
           "properties": {
            "domain": {
             "type": "string"
            },
            "item_id": {
             "minLength": 1,
             "type": "string"
            }
           },
           "required": [
            "item_id"
           ],
           "type": "object"
          },
          "maxItems": 5000,
          "minItems": 0,
          "type": "array"
         }
        },
        "required": [
         "history"
        ],
        "type": "object"
       }
      }
     },
     "required": true
    },
    "responses": {
     "200": {
      "description": "Deterministic receipt with item-level decision path and SHA-256 hashes."
     },
     "400": {
      "description": "Input error (a hint points at /api/examples)."
     },
     "429": {
      "description": "Rate limited."
     }
    },
    "summary": "Find discriminators, saturation, flakiness, and frontier gaps."
   }
  },
  "/api/inspect": {
   "post": {
    "operationId": "inspector",
    "requestBody": {
     "content": {
      "application/json": {
       "example": {
        "baseline": {
         "item-1": false,
         "item-2": false,
         "item-3": false,
         "item-4": false,
         "item-5": false,
         "item-6": false,
         "item-7": false,
         "item-8": false
        },
        "baseline_name": "v1",
        "candidate": {
         "item-1": true,
         "item-2": true,
         "item-3": true,
         "item-4": true,
         "item-5": true,
         "item-6": true,
         "item-7": false,
         "item-8": true
        },
        "candidate_name": "v2",
        "exam": [
         {
          "domain": "code",
          "item_id": "item-1",
          "prompt": "Repair a Python retry loop without changing its public return type."
         },
         {
          "domain": "code",
          "item_id": "item-2",
          "prompt": "Reject a malformed JSON payload while preserving valid zero values."
         },
         {
          "domain": "code",
          "item_id": "item-3",
          "prompt": "Identify the smallest safe patch for an off-by-one pagination bug."
         },
         {
          "domain": "code",
          "item_id": "item-4",
          "prompt": "Keep an asynchronous worker idempotent after a duplicate delivery."
         },
         {
          "domain": "support",
          "item_id": "item-5",
          "prompt": "Explain a delayed shipment without inventing a delivery date."
         },
         {
          "domain": "support",
          "item_id": "item-6",
          "prompt": "Apply the refund policy while preserving the stated eligibility window."
         },
         {
          "domain": "support",
          "item_id": "item-7",
          "prompt": "Reset a locked customer password after identity verification."
         },
         {
          "domain": "support",
          "item_id": "item-8",
          "prompt": "Summarize a refund policy without changing eligibility dates."
         }
        ],
        "exposure": [
         {
          "item_id": "item-8",
          "source": "training.jsonl:42"
         },
         {
          "prompt": "After identity verification, safely reset the locked customer password.",
          "source": "support-sft.jsonl:91"
         }
        ],
        "policy": {
         "confidence_alpha": 0.05,
         "max_regressions": 0,
         "min_gains": 1
        }
       },
       "schema": {
        "additionalProperties": false,
        "description": "Audit exposure, prove a complete clean cohort, then gate baseline versus candidate.",
        "properties": {
         "baseline": {
          "additionalProperties": {
           "type": "boolean"
          },
          "description": "item_id -> boolean pass/fail result for the baseline system.",
          "maxProperties": 5000,
          "minProperties": 1,
          "type": "object"
         },
         "baseline_name": {
          "default": "baseline",
          "type": "string"
         },
         "candidate": {
          "additionalProperties": {
           "type": "boolean"
          },
          "description": "item_id -> boolean pass/fail result for the candidate system.",
          "maxProperties": 5000,
          "minProperties": 1,
          "type": "object"
         },
         "candidate_name": {
          "default": "candidate",
          "type": "string"
         },
         "domains": {
          "additionalProperties": {
           "type": "string"
          },
          "description": "Optional item_id -> domain label mapping.",
          "type": "object"
         },
         "enable_behavioral_fingerprint": {
          "default": true,
          "type": "boolean"
         },
         "enable_text_similarity": {
          "default": true,
          "type": "boolean"
         },
         "exam": {
          "description": "Exam rows. Each row needs item_id (or id) plus prompt/content/input/task/question/expression.",
          "items": {
           "additionalProperties": true,
           "properties": {},
           "type": "object"
          },
          "maxItems": 5000,
          "minItems": 1,
          "type": "array"
         },
         "exposure": {
          "description": "Declared exposure rows carrying identity/content fields and an optional source or path.",
          "items": {
           "additionalProperties": true,
           "properties": {},
           "type": "object"
          },
          "maxItems": 5000,
          "minItems": 0,
          "type": "array"
         },
         "fingerprint_max_n": {
          "default": 4,
          "maximum": 5,
          "minimum": 3,
          "type": "integer"
         },
         "policy": {
          "additionalProperties": false,
          "description": "Explicit promotion policy. Omitted fields use the documented defaults.",
          "properties": {
           "confidence_alpha": {
            "default": 0.05,
            "exclusiveMinimum": 0,
            "maximum": 1,
            "type": "number"
           },
           "max_regressions": {
            "default": 0,
            "minimum": 0,
            "type": "integer"
           },
           "min_gains": {
            "default": 1,
            "minimum": 0,
            "type": "integer"
           },
           "require_retained_probe": {
            "default": false,
            "type": "boolean"
           }
          },
          "type": "object"
         },
         "retained_probe": {
          "additionalProperties": false,
          "description": "Optional retained-capability result checked alongside the paired cohort.",
          "properties": {
           "base_verified": {
            "minimum": 0,
            "type": "integer"
           },
           "candidate_verified": {
            "minimum": 0,
            "type": "integer"
           },
           "items": {
            "minimum": 0,
            "type": "integer"
           }
          },
          "required": [
           "base_verified",
           "candidate_verified",
           "items"
          ],
          "type": "object"
         },
         "similarity_threshold": {
          "default": 0.6,
          "maximum": 1,
          "minimum": 0.5,
          "type": "number"
         }
        },
        "required": [
         "exam",
         "baseline",
         "candidate"
        ],
        "type": "object"
       }
      }
     },
     "required": true
    },
    "responses": {
     "200": {
      "description": "Deterministic receipt with item-level decision path and SHA-256 hashes."
     },
     "400": {
      "description": "Input error (a hint points at /api/examples)."
     },
     "429": {
      "description": "Rate limited."
     }
    },
    "summary": "Quarantine exposure, compare paired outcomes, and issue a receipt."
   }
  },
  "/api/leakage": {
   "post": {
    "operationId": "leakage",
    "requestBody": {
     "content": {
      "application/json": {
       "example": {
        "exam": [
         {
          "item_id": "exact-row",
          "prompt": "Summarize the refund policy without changing eligibility dates."
         },
         {
          "expression": "is_connected and not is_bipartite",
          "item_id": "behavioral-row"
         },
         {
          "item_id": "review-row",
          "prompt": "Reset a locked customer password after identity verification."
         },
         {
          "item_id": "clean-row",
          "prompt": "Calculate shipment tax for a declared destination."
         }
        ],
        "exposure": [
         {
          "prompt": "Summarize the refund policy without changing eligibility dates.",
          "source": "declared-training.jsonl:7"
         },
         {
          "expression": "not is_bipartite and is_connected",
          "source": "graph-sft.jsonl:19"
         },
         {
          "prompt": "After identity verification, safely reset the locked customer password.",
          "source": "support-sft.jsonl:91"
         }
        ],
        "fingerprint_max_n": 4,
        "similarity_threshold": 0.78
       },
       "schema": {
        "additionalProperties": false,
        "description": "Audit declared exposure against an exam and export the clean remainder.",
        "properties": {
         "enable_behavioral_fingerprint": {
          "default": true,
          "type": "boolean"
         },
         "enable_text_similarity": {
          "default": true,
          "type": "boolean"
         },
         "exam": {
          "description": "Exam rows. Each row needs item_id (or id) plus prompt/content/input/task/question/expression.",
          "items": {
           "additionalProperties": true,
           "properties": {},
           "type": "object"
          },
          "maxItems": 5000,
          "minItems": 1,
          "type": "array"
         },
         "exposure": {
          "description": "Declared exposure rows carrying identity/content fields and an optional source or path.",
          "items": {
           "additionalProperties": true,
           "properties": {},
           "type": "object"
          },
          "maxItems": 5000,
          "minItems": 0,
          "type": "array"
         },
         "fingerprint_max_n": {
          "default": 4,
          "maximum": 5,
          "minimum": 3,
          "type": "integer"
         },
         "similarity_threshold": {
          "default": 0.6,
          "maximum": 1,
          "minimum": 0.5,
          "type": "number"
         }
        },
        "required": [
         "exam"
        ],
        "type": "object"
       }
      }
     },
     "required": true
    },
    "responses": {
     "200": {
      "description": "Deterministic receipt with item-level decision path and SHA-256 hashes."
     },
     "400": {
      "description": "Input error (a hint points at /api/examples)."
     },
     "429": {
      "description": "Rate limited."
     }
    },
    "summary": "Exact declared-exposure audit with a clean exam export."
   }
  },
  "/api/memory": {
   "post": {
    "operationId": "memory",
    "requestBody": {
     "content": {
      "application/json": {
       "example": {
        "context_entities": [
         "comet",
         "harbor"
        ],
        "memories": [
         {
          "confidence": 1.0,
          "content": "URGENT: the crimson comet appeared over Harbor City.",
          "entities": [
           "comet",
           "harbor"
          ]
         },
         {
          "confidence": 0.9,
          "content": "Mara hands the obsidian key to Ivo at the archive.",
          "entities": [
           "obsidian_key",
           "ivo"
          ]
         },
         {
          "confidence": 0.8,
          "content": "The archive elevator was repainted blue.",
          "entities": [
           "archive",
           "elevator"
          ]
         },
         {
          "confidence": 0.95,
          "content": "STATE: Ivo currently holds the obsidian key.",
          "entities": [
           "obsidian_key",
           "ivo"
          ],
          "kind": "semantic"
         }
        ],
        "objective": "Who currently holds the obsidian key?",
        "objective_entities": [
         "obsidian_key"
        ],
        "token_budget": 18
       },
       "schema": {
        "additionalProperties": false,
        "description": "Rank caller-supplied memories against a concrete objective under a token budget.",
        "properties": {
         "context_entities": {
          "description": "Entities already active in context.",
          "items": {
           "type": "string"
          },
          "maxItems": 100,
          "type": "array"
         },
         "current_step": {
          "minimum": 0,
          "type": "integer"
         },
         "memories": {
          "description": "Memories to rank.",
          "items": {
           "additionalProperties": false,
           "properties": {
            "age": {
             "default": 0,
             "minimum": 0,
             "type": "integer"
            },
            "confidence": {
             "default": 0.8,
             "maximum": 1,
             "minimum": 0,
             "type": "number"
            },
            "content": {
             "minLength": 1,
             "type": "string"
            },
            "entities": {
             "description": "Entities explicitly present in this memory.",
             "items": {
              "type": "string"
             },
             "maxItems": 100,
             "type": "array"
            },
            "kind": {
             "default": "episodic",
             "type": "string"
            },
            "source": {
             "default": "uploaded",
             "type": "string"
            },
            "use_count": {
             "default": 0,
             "minimum": 0,
             "type": "integer"
            }
           },
           "required": [
            "content"
           ],
           "type": "object"
          },
          "maxItems": 1000,
          "minItems": 1,
          "type": "array"
         },
         "objective": {
          "minLength": 1,
          "type": "string"
         },
         "objective_entities": {
          "description": "Optional explicit entities when the objective text is not self-describing.",
          "items": {
           "type": "string"
          },
          "maxItems": 100,
          "type": "array"
         },
         "question_kind": {
          "default": "generic",
          "type": "string"
         },
         "token_budget": {
          "default": 90,
          "maximum": 10000,
          "minimum": 1,
          "type": "integer"
         }
        },
        "required": [
         "objective",
         "memories"
        ],
        "type": "object"
       }
      }
     },
     "required": true
    },
    "responses": {
     "200": {
      "description": "Deterministic receipt with item-level decision path and SHA-256 hashes."
     },
     "400": {
      "description": "Input error (a hint points at /api/examples)."
     },
     "429": {
      "description": "Rate limited."
     }
    },
    "summary": "Compare query-free salience against objective-conditioned relevance."
   }
  },
  "/api/open-bench/leaderboard": {
   "get": {
    "operationId": "openBenchLeaderboard",
    "responses": {
     "200": {
      "description": "OK"
     }
    },
    "summary": "Opt-in, self-attested public Open Promotion Bench receipts."
   }
  },
  "/api/open-bench/receipt/{public_id}": {
   "get": {
    "operationId": "openBenchReceipt",
    "parameters": [
     {
      "in": "path",
      "name": "public_id",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK"
     },
     "404": {
      "description": "Not found"
     }
    },
    "summary": "One sanitized public benchmark receipt."
   }
  },
  "/api/open-bench/start": {
   "post": {
    "operationId": "openBenchStart",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "additionalProperties": false,
        "properties": {
         "challenge": {
          "maxLength": 128,
          "minLength": 8,
          "type": "string"
         }
        },
        "type": "object"
       }
      }
     },
     "required": true
    },
    "responses": {
     "200": {
      "description": "One-shot session and tasks"
     },
     "429": {
      "description": "Rate limited"
     }
    },
    "summary": "Start a paired six-item scope-integrity cohort."
   }
  },
  "/api/open-bench/submit": {
   "post": {
    "operationId": "openBenchSubmit",
    "responses": {
     "200": {
      "description": "PASS/HOLD/BLOCK receipt"
     },
     "400": {
      "description": "Input error"
     },
     "429": {
      "description": "Rate limited"
     }
    },
    "summary": "Grade paired baseline/candidate patches and optionally publish a sanitized receipt."
   }
  },
  "/api/replay": {
   "post": {
    "operationId": "replay",
    "requestBody": {
     "content": {
      "application/json": {
       "example": {
        "events": [
         {
          "detail": "SAVE first_try",
          "kind": "control",
          "step": 1
         },
         {
          "detail": "CHECK is_tree",
          "kind": "control",
          "step": 2
         },
         {
          "detail": "REJECT counterexample n=6",
          "kind": "verifier",
          "step": 3
         },
         {
          "detail": "LOAD first_try :: tree hypothesis failed",
          "kind": "control",
          "step": 4
         },
         {
          "detail": "CHECK is_tree and max_degree <= 2",
          "kind": "control",
          "step": 5
         },
         {
          "detail": "ACCEPT",
          "kind": "verifier",
          "step": 6
         },
         {
          "detail": "ANSWER is_tree and max_degree <= 2",
          "kind": "control",
          "step": 7
         }
        ],
        "notes": []
       },
       "schema": {
        "additionalProperties": false,
        "description": "Reconstruct checkpoints, rewinds, branches, and verifier outcomes from control events.",
        "properties": {
         "events": {
          "description": "Ordered reasoning-emulator events.",
          "items": {
           "additionalProperties": false,
           "properties": {
            "detail": {
             "type": "string"
            },
            "kind": {
             "description": "Event class such as control, verifier, model, or observation.",
             "type": "string"
            },
            "source": {
             "default": "native",
             "type": "string"
            },
            "step": {
             "minimum": 0,
             "type": "integer"
            }
           },
           "required": [
            "kind",
            "detail"
           ],
           "type": "object"
          },
          "maxItems": 5000,
          "minItems": 1,
          "type": "array"
         },
         "notes": {
          "description": "Optional analyst notes.",
          "items": {
           "type": "string"
          },
          "maxItems": 5000,
          "type": "array"
         }
        },
        "required": [
         "events"
        ],
        "type": "object"
       }
      }
     },
     "required": true
    },
    "responses": {
     "200": {
      "description": "Deterministic receipt with item-level decision path and SHA-256 hashes."
     },
     "400": {
      "description": "Input error (a hint points at /api/examples)."
     },
     "429": {
      "description": "Rate limited."
     }
    },
    "summary": "Turn emulator events into checkpoints, rewinds, notes, and a timeline."
   }
  },
  "/api/report-card/start": {
   "post": {
    "operationId": "reportCardStart",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "additionalProperties": false,
        "properties": {
         "challenge": {
          "maxLength": 128,
          "minLength": 8,
          "type": "string"
         }
        },
        "type": "object"
       }
      }
     },
     "required": true
    },
    "responses": {
     "200": {
      "description": "One-shot session and items"
     },
     "429": {
      "description": "Rate limited or warming"
     }
    },
    "summary": "Start a disposable checker-graded report card."
   }
  },
  "/api/report-card/submit": {
   "post": {
    "operationId": "reportCardSubmit",
    "responses": {
     "200": {
      "description": "Signed checker result"
     },
     "400": {
      "description": "Input error"
     },
     "429": {
      "description": "Retryable contention or limit"
     }
    },
    "summary": "Grade a report card and issue a signed receipt."
   }
  },
  "/api/safepatch": {
   "post": {
    "operationId": "safepatch",
    "requestBody": {
     "content": {
      "application/json": {
       "example": {
        "document": "# Summary\nRelease 4 ships July 12, 2026.\n\n# Notes\nThe draft is wordy.\n",
        "operations": [
         {
          "allow_token_changes": [],
          "find": "The draft is wordy.",
          "replace": "The draft is concise.",
          "target_heading": "Notes"
         }
        ],
        "reason": "Tighten the Notes section only."
       },
       "schema": {
        "additionalProperties": false,
        "description": "Apply deterministic, section-scoped Markdown replacements under conservation checks.",
        "properties": {
         "document": {
          "description": "Complete Markdown document to patch.",
          "maxLength": 200000,
          "minLength": 1,
          "type": "string"
         },
         "operations": {
          "items": {
           "additionalProperties": false,
           "properties": {
            "allow_token_changes": {
             "description": "Protected literal tokens that this operation may intentionally change.",
             "items": {
              "type": "string"
             },
             "maxItems": 100,
             "type": "array"
            },
            "find": {
             "minLength": 1,
             "type": "string"
            },
            "replace": {
             "type": "string"
            },
            "target_heading": {
             "description": "Markdown heading text without the leading # characters.",
             "minLength": 1,
             "type": "string"
            }
           },
           "required": [
            "target_heading",
            "find",
            "replace"
           ],
           "type": "object"
          },
          "maxItems": 50,
          "minItems": 1,
          "type": "array"
         },
         "reason": {
          "type": "string"
         }
        },
        "required": [
         "document",
         "operations"
        ],
        "type": "object"
       }
      }
     },
     "required": true
    },
    "responses": {
     "200": {
      "description": "Deterministic receipt with item-level decision path and SHA-256 hashes."
     },
     "400": {
      "description": "Input error (a hint points at /api/examples)."
     },
     "429": {
      "description": "Rate limited."
     }
    },
    "summary": "Apply a section-scoped Markdown patch under conservation checks."
   }
  },
  "/api/stats": {
   "get": {
    "operationId": "getStats",
    "responses": {
     "200": {
      "description": "OK"
     }
    },
    "summary": "Aggregate, privacy-preserving usage counters."
   }
  },
  "/mcp": {
   "post": {
    "operationId": "mcp",
    "responses": {
     "200": {
      "description": "JSON-RPC response"
     }
    },
    "summary": "MCP endpoint (Streamable HTTP JSON-RPC 2.0). Includes Tier 0 tools, the disposable report card, and Open Promotion Bench."
   }
  }
 },
 "servers": [
  {
   "url": "https://whetstone.cyberelf.link"
  }
 ]
}