{
 "note": "The journalist's desk: the cycle every evidence export goes through, the full pass and where it stands, and the pass ledger, one row per hand-kept data file with the evidence vault head it was last checked against. Kept by correspondent@php.newsroom (until 24 October, claude-journalist). The staleness report on /views/desk/ is computed from this file, the built pages and the vault's claims at every build.",
 "author": "claude-journalist",
 "decided": {
  "by": "Dinis Cruz, editor",
  "on": "2026-10-24",
  "says": "the journalist does the full pass and maintains the site after each export as part of its workflow, released in turn rather than in one large push; and, the same day, the pipeline: researcher, curator, journalist (Sonnet, publishes), correspondent (Opus, reviews and writes the analysis), then the ontologist, the librarian and the desk"
 },
 "cycle": [
  {
   "id": "research",
   "who": "researcher@php.newsroom (Sonnet)",
   "label": "Research",
   "what": "Makes the network requests to the live websites and keeps everything it reads in the source-watch vault, the largest vault."
  },
  {
   "id": "curate",
   "who": "curator@php.newsroom (Sonnet)",
   "label": "Curate",
   "what": "Reads only the researcher's vault, reads each capture, and writes promotions, claims and timeline rows into the evidence vault."
  },
  {
   "id": "publish",
   "who": "journalist@php.newsroom (Sonnet)",
   "label": "Publish",
   "what": "Reads only the evidence vault: exports it, gives every new claim a verdict, refreshes the data the pages draw from, and releases to the live site."
  },
  {
   "id": "review",
   "who": "correspondent@php.newsroom (Opus)",
   "label": "Review",
   "what": "Reads what went live, fixes and tweaks it in the open, writes the state of affairs and the analysis, and tightens the journalist's rules."
  },
  {
   "id": "graphs",
   "who": "the ontologist, the librarian and the desk",
   "label": "Graphs",
   "what": "Only after the correspondent: the semantic graphs, the parties and the attribution are brought up to the reviewed data."
  },
  {
   "id": "settled",
   "who": "the build",
   "label": "Settled",
   "what": "The report at the foot of this page is empty: no 'as of' older than the latest capture, every file checked against the current head, every vault claim reviewed."
  }
 ],
 "pass": [
  {
   "n": 1,
   "title": "The desk, the plan and the staleness report",
   "status": "done",
   "what": "This page: the cycle, the pass, the pass ledger and the report that says what is still stale."
  },
  {
   "n": 2,
   "title": "Refresh the hand-kept data from the new evidence",
   "status": "in progress",
   "what": "Story, the compromise line, the offline ledger, agencies, numbers, the timeline, the KEV snapshot and the software inventory, each checked against the current head. Done so far: the compromise evidence and claim, the offline list, the story summary, the front page's dated lines, the 'been hacked' answer, the context row and the 22.6 million figure, at 1f38e70921b2; to do: agencies, numbers in full, the timeline, the software inventory, defence and affected systems."
  },
  {
   "n": 3,
   "title": "Move the facts typed into the build into data",
   "status": "pending",
   "what": "Front-page tiles, KEV, playbook, the Explained page, chart windows and counts read from data, so the next export changes them without code."
  },
  {
   "n": 4,
   "title": "The persona pass",
   "status": "pending",
   "what": "The sixteen readers' answers, introductions and asks move into personas.json, with their 'as of' generated, and are re-read against the state of affairs."
  },
  {
   "n": 5,
   "title": "Review the rest of the curator's claims",
   "status": "pending",
   "what": "Every claim on /claims/review/ gets a verdict; the used ones go into the site's claim table with their sources."
  }
 ],
 "files": [
  {
   "path": "data/story.json",
   "kept_by_before": "story-site",
   "checked_against": "1f38e70921b2",
   "note": "exploitation paragraph: 'as of' moved to 14:40 UTC on 25 October; the CVE-2026-115560 question is the correspondent's; not re-read in full."
  },
  {
   "path": "data/claims.json",
   "kept_by_before": "story-site",
   "checked_against": null,
   "note": "Partly: no-confirmed-compromise refreshed to 14:40 UTC on 25 October (vault 94352a55fbaa, 454 sources); the other 69 claims not yet re-read."
  },
  {
   "path": "data/impact.json",
   "kept_by_before": "story-site",
   "checked_against": "1f38e70921b2",
   "note": "GARR (Italy, platforms isolated 21 October) added, vault 94352a55fbaa; other rows not re-read in full."
  },
  {
   "path": "data/compromise.json",
   "kept_by_before": "story-site",
   "checked_against": "94352a55fbaa",
   "note": "La Razón (no successful execution established, 23 October) added; as of 14:40 UTC on 25 October; searched count 454; head 94352a55fbaa."
  },
  {
   "path": "data/exploitation.json",
   "kept_by_before": "story-site",
   "checked_against": null,
   "note": ""
  },
  {
   "path": "data/numbers.json",
   "kept_by_before": "story-site",
   "checked_against": null,
   "note": "22.6 million: Palo Alto Networks, via Insurance Business and TechTarget; what it measures."
  },
  {
   "path": "data/agencies.json",
   "kept_by_before": "story-site",
   "checked_against": null,
   "note": ""
  },
  {
   "path": "data/timeline.json",
   "kept_by_before": "story-site",
   "checked_against": null,
   "note": ""
  },
  {
   "path": "data/history.json",
   "kept_by_before": "story-site",
   "checked_against": null,
   "note": "Partly: the php2shell row's KEV and response lines refreshed (24 October); the comparators not re-read."
  },
  {
   "path": "data/defence.json",
   "kept_by_before": "story-site",
   "checked_against": null,
   "note": ""
  },
  {
   "path": "data/affected.json",
   "kept_by_before": "story-site",
   "checked_against": null,
   "note": ""
  },
  {
   "path": "data/software.json",
   "kept_by_before": "the vault export (collector-gov's capture)",
   "checked_against": null,
   "note": ""
  },
  {
   "path": "data/plain.json",
   "kept_by_before": "story-site",
   "checked_against": "1f38e70921b2",
   "note": "'As of' lines to 09:35 UTC on 25 October. Not re-read in full; the desk's message of 25 October on CVE-2026-115560 in Right now is passed to the correspondent."
  },
  {
   "path": "data/personas.json",
   "kept_by_before": "briefing writer",
   "checked_against": null,
   "note": ""
  },
  {
   "path": "data/questions.json",
   "kept_by_before": "librarian",
   "checked_against": null,
   "note": "Partly: 'Has anyone actually been hacked?' as of 09:35 UTC on 25 October; the other answers not yet re-read."
  },
  {
   "path": "data/signals.json",
   "kept_by_before": "journalist and historian",
   "checked_against": null,
   "note": ""
  },
  {
   "path": "data/patching.json",
   "kept_by_before": "journalist",
   "checked_against": null,
   "note": ""
  },
  {
   "path": "data/state.json",
   "kept_by_before": "journalist",
   "checked_against": "1f38e70921b2",
   "note": "State of affairs v3."
  }
 ],
 "kept_as_written": [
  "articles/",
  "updates/",
  "versions/",
  "whatsnew/",
  "admin/",
  "readings/",
  "brief/",
  "corrections/",
  "feedback/",
  "sherpa/",
  "team/",
  "pulse/",
  "sources/",
  "facts/",
  "views/"
 ],
 "kept_as_written_why": "Stories, updates, versions of the state of affairs, release notes, briefs, outside readings and source pages are dated and kept as written by design; a dated phrase in them is history, not staleness. Facts pages carry every version of a fact. The state of affairs gives each measure its own as-of time on purpose.",
 "accepted": [
  {
   "page": "*",
   "phrase": "as of 20:30 UTC on 21 October",
   "why": "Huntress's own time for its statement that it had seen no exploitation on its partners' systems (claim huntress-none): a source's date, kept wherever the claim is quoted."
  }
 ],
 "catches": [
  {
   "on": "2026-10-24",
   "what": "claim cur6-third-flaw-115560 held back as 'CVE not in the PHP advisory in the vault' although Cloudflare, SOCRadar and The Hacker News carry it; the story still said 'Nothing from PHP on the list yet'. Verdict now used; story and the front page's open question updated.",
   "file": "data/claim-review.json, data/story.json, data/plain.json",
   "kind": "verdict",
   "journalist_run": "20261024T2126Z-journalist",
   "fixed_in": "the correspondent's release after v0.16.1"
  },
  {
   "on": "2026-10-24",
   "what": "The CVE-2026-115560 advisory of 23 October (a third PHP flaw, unpatched until the next regular release) was on no page of the site.",
   "file": "data/story.json",
   "kind": "missing",
   "journalist_run": "20261024T2126Z-journalist",
   "fixed_in": "the correspondent's release after v0.16.1"
  },
  {
   "on": "2026-10-24",
   "what": "claim cur8-sansec-memory-leak: reason said Sansec's own post is not in the vault; it is (sansec-research-php2shell).",
   "file": "data/claim-review.json",
   "kind": "verdict",
   "journalist_run": "20261024T2126Z-journalist",
   "fixed_in": "the correspondent's release after v0.16.1"
  },
  {
   "on": "2026-10-24",
   "what": "Sansec's two captures differ: the Heartbleed comparison and 'default configurations are vulnerable' of 22 October are gone on 23 October. The journalist compared neither.",
   "file": "data/claim-review.json",
   "kind": "contradiction",
   "journalist_run": "20261024T2126Z-journalist",
   "fixed_in": "the correspondent's release after v0.16.1"
  },
  {
   "on": "2026-10-24",
   "what": "claim cur2-certin-high: MediaNama says CERT-In rated it 'high', Indian Express and a CERT-In post say 'critical-severity'. Held back, now for the contradiction.",
   "file": "data/claim-review.json",
   "kind": "contradiction",
   "journalist_run": "20261024T2126Z-journalist",
   "fixed_in": "the correspondent's release after v0.16.1"
  },
  {
   "on": "2026-10-24",
   "what": "claim cur8-eu-joint-advisory held back as 'one Italian outlet'; four more outlets in the vault report the joint statement. Now noted with all five.",
   "file": "data/claim-review.json",
   "kind": "verdict",
   "journalist_run": "20261024T2126Z-journalist",
   "fixed_in": "the correspondent's release after v0.16.1"
  },
  {
   "on": "2026-10-24",
   "what": "claims cur6-at-no-successful-attacks and cur8-rainforest-honeypot marked 'noted' (not used) while the journalist's own compromise.json rows and the front page use them. Now used.",
   "file": "data/claim-review.json",
   "kind": "verdict",
   "journalist_run": "20261024T2126Z-journalist",
   "fixed_in": "the correspondent's release after v0.16.1"
  },
  {
   "on": "2026-10-24",
   "what": "claim cur8-cloudflare-waf-rule: reason said Cloudflare's post is not in the vault; it is (cloudflare-blog-php2shell-waf).",
   "file": "data/claim-review.json",
   "kind": "verdict",
   "journalist_run": "20261024T2126Z-journalist",
   "fixed_in": "the correspondent's release after v0.16.1"
  },
  {
   "on": "2026-10-24",
   "what": "Die Presse row: 'as of 12:03' next to '10:03 UTC' read as two different times (12:03 is Vienna time); RainForest row left out that the 21 requests came from 14 source IPs.",
   "file": "data/compromise.json, data/plain.json",
   "kind": "row",
   "journalist_run": "20261024T2126Z-journalist",
   "fixed_in": "the correspondent's release after v0.16.1"
  }
 ],
 "catches_about": "What the correspondent corrected in the journalist's work, one row per correction: when, what, the file, its kind (verdict, row, as-of, missing, contradiction), the journalist's run and the release that fixed it. Counted on /views/desk/, so the editor can see what a Sonnet journalist misses."
}
