{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/samedaydesk-com/json-schema/samedaydesk-com-page-change-artifact-schema.json",
  "title": "PageChangeArtifact",
  "description": "Already held JSON artifact or JSON envelope, never a path or URL to dereference. Stable source identity, separate from row id and observation time. Matching normalizes source strings (URL fragments removed). Use the same non-empty identity on both sides; duplicate active identities are ambiguous. Synthetic URL STRINGS are inert and are never fetched by this transform. The structured branches describe representative comparable inputs. Incomplete objects remain admitted for diagnostic reports, subject to unchanged HTTP safety checks; HTTP 200 does not establish completeness or usefulness.",
  "x-generated": "2026-10-30",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/agents-samedaydesk-openapi.json#/components/schemas/PageChangeArtifact",
  "type": "object",
  "anyOf": [
    {
      "$ref": "#/$defs/PageChangeMerchant"
    },
    {
      "$ref": "#/$defs/PageChangeC1"
    },
    {
      "title": "Supplied JSON envelope",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "body"
      ],
      "properties": {
        "mediaType": {
          "type": "string",
          "const": "application/json"
        },
        "body": {
          "anyOf": [
            {
              "$ref": "#/$defs/PageChangeMerchant"
            },
            {
              "$ref": "#/$defs/PageChangeC1"
            }
          ]
        },
        "observedAt": {
          "type": [
            "string",
            "null"
          ],
          "description": "Caller observation metadata only; does not attest freshness."
        },
        "status": {
          "type": "string"
        }
      }
    },
    {
      "title": "Diagnostic object (may be incomplete or incomparable)",
      "type": "object",
      "description": "Intentionally permissive diagnostic alternative, not a template for a useful comparison. Missing/wrong schemas, keys, source identities or fields do not become valid comparison evidence. A missing snapshot can be supplied as {missing:true}. Safety admission still rejects paths, URL dereference, limit raises and invalid envelopes."
    }
  ],
  "$defs": {
    "PageChangeC1": {
      "title": "Supplied legacy C1 batch result",
      "type": "object",
      "required": [
        "jobId",
        "status",
        "costParameters",
        "accounting",
        "items"
      ],
      "description": "Existing C1 result compatibility. No merchant product/schemaVersion is required. Compare only the explicitly selected data keys present on both matched rows. Missing keys are coverage unknown, not deletions; explicit null is a present value. Unselected metadata is not a content delta.",
      "properties": {
        "jobId": {
          "type": "string"
        },
        "status": {
          "type": "string"
        },
        "costParameters": {
          "type": "object"
        },
        "accounting": {
          "type": "object"
        },
        "items": {
          "type": "array",
          "minItems": 1,
          "maxItems": 32,
          "items": {
            "$ref": "#/$defs/PageChangeRow"
          }
        }
      }
    },
    "PageChangeMerchant": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "ok",
        "product",
        "schemaVersion",
        "quote",
        "jobId",
        "jobStatus",
        "stopReason",
        "partial",
        "sources",
        "accounting",
        "costInputs",
        "charged",
        "boundary"
      ],
      "properties": {
        "ok": {
          "type": "boolean"
        },
        "product": {
          "type": "string",
          "const": "samedaydesk-extract-batch"
        },
        "schemaVersion": {
          "type": "string",
          "const": "samedaydesk.extract-batch.v0"
        },
        "quote": {
          "type": "object",
          "required": [
            "amountAtomic",
            "displayUsdc",
            "meaning"
          ],
          "properties": {
            "amountAtomic": {
              "type": "string",
              "const": "10000"
            },
            "displayUsdc": {
              "type": "string",
              "const": "0.01"
            },
            "meaning": {
              "type": "string"
            }
          }
        },
        "jobId": {
          "type": "string",
          "pattern": "^[a-f0-9]{64}$"
        },
        "jobStatus": {
          "type": "string",
          "enum": [
            "running",
            "completed",
            "completed_with_unknown",
            "stopped",
            "interrupted"
          ]
        },
        "stopReason": {
          "type": [
            "string",
            "null"
          ]
        },
        "partial": {
          "type": "boolean"
        },
        "sources": {
          "type": "array",
          "minItems": 1,
          "maxItems": 5,
          "items": {
            "$ref": "#/$defs/PageChangeRow"
          }
        },
        "accounting": {
          "type": "object"
        },
        "costInputs": {
          "type": "object"
        },
        "charged": {
          "type": "boolean"
        },
        "boundary": {
          "type": "object"
        },
        "error": {
          "type": "string"
        }
      },
      "title": "Supplied merchant extract-batch v0 artifact",
      "description": "Representative merchant structure for useful comparisons; not a new paid request or proof of payment. Compare only the explicitly selected data keys present on both matched rows. Missing keys are coverage unknown, not deletions; explicit null is a present value. Unselected metadata is not a content delta."
    },
    "PageChangeRow": {
      "type": "object",
      "required": [
        "id",
        "source",
        "status",
        "data",
        "notes",
        "error",
        "provenance"
      ],
      "properties": {
        "id": {
          "type": "string",
          "description": "Row identifier; does not replace source identity."
        },
        "source": {
          "type": "string",
          "minLength": 1,
          "pattern": "\\S",
          "description": "Stable source identity, separate from row id and observation time. Matching normalizes source strings (URL fragments removed). Use the same non-empty identity on both sides; duplicate active identities are ambiguous. Synthetic URL STRINGS are inert and are never fetched by this transform."
        },
        "status": {
          "type": "string",
          "enum": [
            "pending",
            "success",
            "partial",
            "failure",
            "unknown",
            "skipped_duplicate"
          ]
        },
        "data": {
          "type": [
            "object",
            "null"
          ],
          "description": "Compare only the explicitly selected data keys present on both matched rows. Missing keys are coverage unknown, not deletions; explicit null is a present value. Unselected metadata is not a content delta.",
          "properties": {
            "title": {
              "description": "Selected extraction value: title."
            },
            "description": {
              "description": "Selected extraction value: description."
            },
            "canonical": {
              "description": "Selected extraction value: canonical."
            },
            "lang": {
              "description": "Selected extraction value: lang."
            },
            "openGraph": {
              "description": "Selected extraction value: openGraph."
            },
            "twitter": {
              "description": "Selected extraction value: twitter."
            },
            "jsonLd": {
              "description": "Selected extraction value: jsonLd."
            },
            "headings": {
              "description": "Selected extraction value: headings."
            },
            "links": {
              "description": "Selected extraction value: links."
            },
            "text": {
              "description": "Selected extraction value: text."
            },
            "aiReadiness": {
              "description": "Selected extraction value: aiReadiness."
            }
          }
        },
        "notes": {
          "type": "array"
        },
        "error": {
          "type": [
            "object",
            "null"
          ]
        },
        "provenance": {
          "type": [
            "object",
            "null"
          ]
        },
        "finalUrl": {
          "type": [
            "string",
            "null"
          ]
        },
        "httpStatus": {
          "type": [
            "integer",
            "null"
          ]
        }
      }
    }
  }
}