{
 "use_case": "editorial-ledger",
 "title": "Rehearsal: editorial-control ledger for a fictional local news story",
 "about": "A fictional newsroom assigns a story from two fictional source documents. The model writes the first draft (receipted), the editor files a rewritten final text, the claim check lists what the edit removed and added, a named editor signs off and the piece is sealed. The sealed record must verify, including that the published text is the signed-off text, and a copy with one entry changed must not.",
 "licence": "Synthetic: the Harbour Gazette, Port Aldane and every name, figure and quote are invented for Decosa. Part of decosa-api, AGPL-3.0-or-later.",
 "inputs": [
  {
   "file": "inputs/piece.json",
   "what": "The piece: title, assignment, desk, who is responsible, and the sources [{title, text}] the draft must be written from."
  },
  {
   "file": "inputs/final.txt",
   "what": "The editor's final text, as it will be published (plain text, paragraphs separated by blank lines)."
  },
  {
   "file": "inputs/editor.json",
   "what": "The editor who revises and signs off: {name, role}."
  }
 ],
 "steps": [
  {
   "id": "piece",
   "method": "POST",
   "path": "/editorial/pieces",
   "body": {
    "$file": "inputs/piece.json"
   }
  },
  {
   "id": "draft",
   "method": "POST",
   "path": "/editorial/pieces/${piece.piece_id}/draft",
   "timeout": 150,
   "body": {}
  },
  {
   "id": "revise",
   "method": "POST",
   "path": "/editorial/pieces/${piece.piece_id}/revisions",
   "body": {
    "text": {
     "$file": "inputs/final.txt"
    },
    "editor": {
     "$file": "inputs/editor.json"
    },
    "active_ms": 90000
   }
  },
  {
   "id": "claims",
   "method": "POST",
   "path": "/editorial/pieces/${piece.piece_id}/claims",
   "timeout": 150,
   "body": {}
  },
  {
   "id": "signoff",
   "method": "POST",
   "path": "/editorial/pieces/${piece.piece_id}/signoff",
   "body": {
    "editor": {
     "$file": "inputs/editor.json"
    },
    "decision": "approve",
    "final_sha256": {
     "$ref": "revise.text_sha256"
    }
   }
  },
  {
   "id": "publish",
   "method": "POST",
   "path": "/editorial/pieces/${piece.piece_id}/publish",
   "body": {
    "public_draft": true
   }
  },
  {
   "id": "public",
   "method": "GET",
   "path": "/editorial/p/${publish.public_id}",
   "auth": false
  },
  {
   "id": "verify",
   "method": "POST",
   "path": "/editorial/verify",
   "auth": false,
   "body": {
    "public_id": {
     "$ref": "publish.public_id"
    },
    "text": {
     "$file": "inputs/final.txt"
    }
   }
  },
  {
   "id": "tampered",
   "method": "POST",
   "path": "/editorial/verify",
   "auth": false,
   "body": {
    "record": {
     "$ref": "publish.record"
    }
   },
   "tamper": {
    "at": "record.entries[kind=signoff].editor.name",
    "set": "Someone Else"
   }
  }
 ],
 "checks": [
  {
   "says": "the model writes a first draft from the sources",
   "path": "draft.text",
   "contains": "North Quay"
  },
  {
   "says": "the edit is recorded as a substantial rewrite (over 20% of words changed)",
   "path": "revise.metrics_draft.changed_share",
   "min": 0.2
  },
  {
   "says": "the claim check answered every item",
   "path": "claims.unparsed",
   "equals": 0
  },
  {
   "says": "the editor's new lede is listed as an added or edited sentence",
   "path": "claims.items[new~Ferry passengers at Port Aldane][0].status",
   "in": [
    "added",
    "edited"
   ]
  },
  {
   "says": "a signed-off piece is published without an AI label",
   "path": "publish.label",
   "equals": false
  },
  {
   "says": "the sealed record verifies",
   "path": "verify.ok",
   "equals": true
  },
  {
   "says": "the published text is the signed-off text, byte for byte",
   "path": "verify.published_text.exact",
   "equals": true
  },
  {
   "says": "a record with the sign-off editor changed no longer verifies",
   "path": "tampered.ok",
   "equals": false
  },
  {
   "says": "every model call has a signed receipt",
   "receipts": "signed"
  }
 ]
}
