2026-08-21T0410Z-intel
One pipeline fire, in full · intel run of 2026-08-21 · sub-agent allocation and telemetry, per-iteration verification verdicts and findings, source-list edits, coverage gaps, bridge invocations — and the run's own verification & coverage notes: what was published, what was dropped at the borderline or judged not relevant (and why), single-source carve-outs, and contradictions. Rendered from runs/2026-08-21/2026-08-21T0410Z-intel.md.
Run telemetry
- Items returned
- 4
- Duration
- 17m 15s
- Tool calls
- 30 WebFetch3 WebSearch16 bridge
- Cited sources
- 5 of 29 in slice
- Items returned
- 2
- Duration
- 14m 48s
- Tool calls
- 22 WebFetch17 WebSearch16 bridge
- Cited sources
- 2 of 18 in slice
- Items returned
- 6
- Duration
- 25m 56s
- Tool calls
- 34 WebFetch6 WebSearch28 bridge
- Cited sources
- 6 of 36 in slice
- Items returned
- 1
- Duration
- 17m 33s
- Tool calls
- 22 WebFetch11 WebSearch16 bridge
- Cited sources
- 3 of 13 in slice
- Items returned
- 3
- Duration
- 14m 02s
- Tool calls
- 0 WebFetch0 WebSearch12 bridge
- Cited sources
- 10 of 10 in slice
- Items returned
- 3
- Duration
- 12m 04s
- Tool calls
- 0 WebFetch2 WebSearch9 bridge
- Cited sources
- 7 of 7 in slice
Verification
Deep dive
—
Entries published (this run)
- Thirteen CVEs in ATutor, none of which will ever be fixed — including an unauthenticated auto-login token forgery that authenticates as any account, administrators included vulnerability notable
- UPDATE — ShieldBreak reproduced on a fully patched Windows Server 2025 with August's updates installed: Defender's own clean engine writes the attacker's DLL into System32, and Microsoft's only change on the day was adding a CWE tag vulnerability notable update
- UPDATE — Toneshell's tenth version abandons custom sockets for WebSocket-over-TLS through WinHTTP, retiring every network signature built on the old channel, and a new hVNC backdoor carries no embedded C2 at all threat notable update
- UPDATE — the actor behind France's tax-authority theft is linked by media reporting to the Education Ministry intrusion the ministry disclosed on 31 July, and social-security numbers were in scope for a subset of staff incident notable update
- UPDATE — the Siemens S7 joint advisory read from its own primary: five named detection classes, a gold-copy firmware comparison, and an explicit instruction to pass the mitigations to systems integrators threat notable update
Sources changed (this run)
Edits this run made to sources/sources.json · promotions, demotions, new candidates, and fetch-method / category / reliability / url corrections (the run record's sources_changed[]). Paginated; 10 per page.
10 bookkeeping · 2 url-migrated · 1 added-as-candidate · 1 promoted.
| Source | Change | From → To | Reason |
|---|---|---|---|
| wordfence | added-as-candidate | — → candidate | this run's single new candidate, and a root-cause fix rather than an addition. Wordfence is a CVE Naming Authority for the WordPress plugin ecosystem and was the originating discloser behind two entries published on 2026-08-19 — but because the publisher was untracked, both entries cite a syndication mirror rather than the original research, which is a most-primary-source defect the source list itself caused. Its feed then immediately surfaced an in-window unauthenticated file-upload disclosure in a plugin with roughly six million installs that no other tracked source carried. |
| cert-lv | promoted | candidate → active | the state digest counted 3 contributing runs, meeting the documented promotion bar. Read from sources.promotion_due rather than eyeballed, which is the rule a single fire cannot otherwise apply because it cannot remember earlier fires. |
| ncsc-ch-focus | url-migrated | https://www.ncsc.admin.ch/ncsc/de/home/aktuell/im-fokus.html → https://www.bacs.admin.ch/de/im-fokus | NCSC Switzerland's public site migrated to the Bundesamt fuer Cybersicherheit (BACS) domain, announced on the new site 2026-08-20. The old URLs 301-redirect only 'in most cases' and the announcement states those redirects are NOT permanently available, so the old URL was treated as expiring rather than working. The new URL was verified reachable this run before the change was committed. This is an essential-tier record, so leaving it to break would have cost the home-region surface. |
| ncsc-ch-incidents | url-migrated | https://www.ncsc.admin.ch/ncsc/de/home/aktuell/aktuelle-vorfaelle.html → https://www.bacs.admin.ch/de/aktuelle-vorfaelle | same migration, same verification. Note security-hub.ncsc.admin.ch — the Cyber Security Hub API behind the ncsc-csh bridge subcommand — still resolved this run and is deliberately NOT changed. |
| cisa-kev | bookkeeping | — → last_successful_fetch 2026-08-21, counters reset | catalogue version 2026.08.20 carried this run's only new additions, the two TrueConf Server CVEs |
| enisa-euvd | bookkeeping | — → last_successful_fetch 2026-08-21, counters reset | supplied both TrueConf CVE records in full after neither Kaspersky page proved to carry a CVE identifier at all — identifiers, CVSS 4.0 scores, EPSS, structured affected ranges and the exploited-from date |
| cert-pl | bookkeeping | — → last_successful_fetch 2026-08-21, counters reset | sole primary for the 13-CVE ATutor disclosure, read in both English and Polish |
| checkpoint-research | bookkeeping | — → last_successful_fetch 2026-08-21, counters reset | sole primary for this run's deep dive |
| talos | bookkeeping | — → last_successful_fetch 2026-08-21, counters reset | two companion posts behind the UAT-10147 entry |
| mandiant-gtig | bookkeeping | — → last_successful_fetch 2026-08-21, counters reset | sole primary for the three-cluster authentication-abuse entry |
| ibm-xforce | bookkeeping | — → last_successful_fetch 2026-08-21, counters reset | sole primary for the ITG27 update. Note the record was reported as a recipe gap by the research pass but the specific article URL read cleanly through the direct bridge — the listing is the defect, not the host. |
| heise-sec | bookkeeping | — → last_successful_fetch 2026-08-21, counters reset | independent corroboration of the Berlin compromise and of the Senate's refusal to give scope detail |
| trustwave-spiderlabs | bookkeeping | — → last_successful_fetch 2026-08-21, counters reset | LevelBlue SpiderLabs supplied the ShieldBreak reproduction and the seven-stage mechanism |
| wiz-blog | bookkeeping | — → last_successful_fetch 2026-08-21, counters reset | one of four primaries on the crates.io attack, including the self-issued correction this entry carries instead of the original claim |
Coverage gaps (this run)
Sources this run's brief needed that returned no usable content via any documented recipe. Bridge-recovered or quiet-day sources do NOT appear here. (Distinct from the independent source-accessibility probe at the foot of this section, which probes all active sources regardless of what any run needed.)
| Source (uncovered) | URL tried | Method chain | Status / class | What the agent did instead |
|---|---|---|---|---|
| jina-reader-pool | https://r.jina.ai/ (all configured keys) | jina | 402 transport-block seventh consecutive fire with the reader pool credit-exhausted — 7 of 7 keys returned HTTP 402 with live_key_count=0, confirmed by an explicit jina-usage check. | no pass planned around the reader. Every published entry rests on a transport that worked — the KEV JSON feed, the ENISA EUVD advisory API, Microsoft's MSRC API |
| wordfence | https://www.wordfence.com/blog/2026/08/critical-arbitrary-file-upload-vulnerabil | rss → bridge:url → webfetch → bridge:url (intelligence API v2 production) → bridge:url (intelligence API v2 scanner) | 0 recipe-gap the RSS feed reads cleanly and is what surfaced the item, but the ARTICLE BODY is unreachable: the direct bridge is refused and falls through to the exhausted r | not published — a vulnerability entry that cannot state which version to patch to is filler, and inventing the missing fields is the exact defect class the gate |
| cisa-advisories covered via alternate · should NOT be in this list | https://www.cisa.gov/news-events/cybersecurity-advisories | webfetch → bridge:cisa page → bridge:url → websearch | 403 transport-403 eighth consecutive unreachable run; HTTP 403 to every user agent with the reader fallback exhausted. Essential-tier miss. | the KEV JSON feed at the /sites/default/files/feeds/ path is unaffected by the HTML refusal and was read directly by the main agent, confirming catalogue versio |
| cisa-directives | https://www.cisa.gov/news-events/directives | bridge:url → websearch | 403 transport-403 seventh consecutive unreachable run, same condition; essential-tier miss and a rotation-priority source. | no evidence from any other source that a directive published in-window |
| ccn-cert-es | https://www.ccn-cert.cni.es/en/updated-security/ccn-news.html | bridge:url → jina → websearch | 403 transport-403 rotation-priority source; HTTP 403 to the direct transport on both the Spanish avisos listing and the English news listing, with the record's pinned reader tran | a WebSearch substitute surfaced only vulnerability-domain items already in scope elsewhere; no CCN-CERT-specific in-window item is known lost. NOT demoted — a 4 |
| siemens-productcert-csaf | https://cert-portal.siemens.com/productcert/csaf/ | bridge:url → bridge:cisa csaf-recent → websearch | 403 transport-403 fifth consecutive failure; vendor portal refuses the direct transport with the reader unavailable. Rotation-priority source. | the cisagov CSAF mirror was checked as the documented alternate; nothing attributable to Siemens newer than the advisory already covered on 2026-08-13, so no in |
| ssd-disclosure | https://ssd-disclosure.com/ | bridge:url | 202 transport-block fifth consecutive failure on the open backlog item. The only rung that has ever worked for this host is the reader pool, which remains credit-exhausted; the cli | none available; the Unisoc backlog row stays open unchanged, to be struck at the ~30-day mark (2026-09-17) if the reader pool has not returned |
| venarix | https://venarix.com/blog | bridge:url → rss | 200 recipe-gap fourth consecutive failure; the listing is a client-rendered shell with no server-rendered article rows, and the per-article path cannot be enumerated without e | no in-window item known lost; the tracker's subject matter was covered by other breach sources |
| zaufana-trzecia-strona covered via alternate · should NOT be in this list | https://zaufanatrzeciastrona.pl/ | webfetch → rss | 403 transport-403 Cloudflare challenge to the direct transport; the RSS feed was readable but its newest item predates the window | CERT-PL was reachable and carried the Polish authority surface, supplying this run's ATutor entry; no in-window Polish item is known lost |
| ccb-belgium covered via alternate · should NOT be in this list | https://ccb.belgium.be/advisories | bridge:url | 402 transport-block rotation-priority source. The previous fire moved this record off its reader pin after establishing the direct bridge worked; this run the direct path did not r | CERT-EU and NCSC-NL covered the European advisory surface. Flagged for a recipe re-check next fire — the record should not silently regress to unreachable after |
| trellix | https://www.trellix.com/blogs/ | bridge:url | 200 recipe-gap the served index still returns only content dated February to May 2026, confirming the standing stale-index defect first recorded by the 2026-07-27 audit | none; a standing recipe defect on a research-tier source that should be fixed rather than re-observed each run |
| sans-ics covered via alternate · should NOT be in this list | https://www.sans.org/blog/?focus-area=industrial-control-systems-ics | webfetch → bridge:url | 200 recipe-gap the focus-area query parameter is honoured by no transport — both WebFetch and the direct bridge return the generic blog listing, so the ICS slice cannot be iso | none this run; the OT/ICS surface was covered by the joint-advisory primary instead. Needs a recipe that filters client-side or a different ICS-specific route. |
| paradigm-shift-research | https://ps.tc/ | bridge:url | 200 recipe-gap top rotation priority (last success 2026-07-29) and still a persistent client-rendered application shell | none; carried forward |
Bridge invocations (this run)
29 bridge calls this run · these are successful bridge fetches (separate from "Coverage gaps" above).
- url ×16
- feed ×2
- url --direct (bacs.admin.ch) ×2
- cisa-kev api ×1
- enisa-euvd advisory ×1
- enisa-euvd recent ×1
- pdf ×1
- msrc cve ×1
Verification findings · all iterations
Per-iteration finding detail. Each table is one verifier pass · what was flagged, how the main agent remediated it, and the outcome. Walking the tables top-to-bottom shows the verifier's debugging trail across iterations.
Iteration #1 NEEDS_FIXES cap-breach · 5 findings (truth=3, editorial=4, advisory=5) · Claude Opus 5 · —
| F-code | Section | Item · URL/quote | Verifier summary | Remediation · outcome |
|---|---|---|---|---|
| F4 hallucinated-fact | — | CVE-2026-64969 was typed info-disclosure, but the advisory describes permanent DELETION of another user's profile picture including instructors and administrators — an integrity effect, CWE-639. The b | type changed to auth-bypass and the body now carries the deletion impact in the advisory's own terms. APPLIED — entry survives. | |
| F4 hallucinated-fact | — | CVE-2026-64972 was described as reflected XSS 'via a preview parameter'; the injectable parameter is `popup`, and preview.php is the script it sits in. On a per-identifier reference table a hunter wou | corrected to the `popup` parameter in preview.php, with the double-quote attribute break-out the advisory describes. APPLIED — entry survives. | |
| F3 claim-not-supported | — | one sentence carried two quotes under a single trailing citation to the advisory, but the sandbox phrase lives in the co-cited report rather than the advisory. | NOT APPLIED — this entry was removed by the overtaken-run reconciliation before commit, because the 2026-08-23 fire published the same story. Recorded so the fi | |
| F11 editorial-advisory | — | the summary said the chain completes 'in roughly ten seconds'; the source says approximately eight to twelve, which the body carried correctly. No source says ten. | the range is now used in both places. APPLIED — entry survives. | |
| F10 missed-angle | — | the deferral is avoidable: the flaw carries CVE-2026-32475 and the CNA's own research post plus the ENISA vulnerability API — both transports this run used successfully elsewhere — carry every field t | NOT published, deliberately, under the wall-clock watchdog — by the time this finding could be acted on the run was ~76 h overrun and two later fires had publis |
Verification & coverage notes
The run record's narrative body, verbatim. This is where the run accounts for its own judgement calls — every borderline drop and judged-not-relevant item with its reason, dedup decisions, single-source items and their carve-outs, contradictions, and per-source coverage gaps — so nothing the run considered disappears silently.
Verification & coverage notesrun record body
2026-08-21T0410Z-intel · Opus 5 · window 26 h · 5 entries published
Verification & coverage notes
This run was suspended mid-pipeline for roughly three days and was overtaken. Read the rest of these notes in that light. The fire started 2026-08-21T04:10:40Z and completed its research, composition, mechanical gate and one verifier iteration inside 93 minutes. The container was then suspended; the session resumed on 2026-08-24, with real elapsed time at ~76.8 h. duration_seconds records that honestly and will trip the runaway-duration warning — it is a telemetry fact about this fire, not drift to fix.
What the overrun cost, and what was done about it. Scheduled fires on 2026-08-23 (intel and weekly) and 2026-08-24 (weekly) published while this run sat mid-pipeline. Per the overtaken-run rule, origin/main was re-fetched before any commit and every not-yet-committed candidate was re-deduplicated against what those fires published. Six of the eleven composed entries were removed as duplicates:
- the Defender boot-time remediation driver research — the 2026-08-23 fire published it as
2026-08-23/btr-sys-defender-remediation-driver-kernel-primitive - the three Russian-nexus authentication-abuse clusters — published as
2026-08-23/gtig-russia-clusters-app-passwords-whatsapp-linking - the crates.io build-script supply-chain attack — published as
2026-08-23/rust-crates-arrayref-build-script-backdoor-dprk - the SPECTRE / kernel-callback-unlinking implant — published as
2026-08-23/spectre-uat-10147-byovd-edr-callback-unlink, with the agentic-AI half as a second entry - the TrueConf Server exploitation chain — published as
2026-08-23/trueconf-server-kev-head-mare-trojanized-installer - the Berlin state-network compromise — carried by that fire as a strategic synthesis,
2026-08-23/weekly-w34-berlin-landesnetz-nine-days-no-vector
On Berlin specifically, the later fire made the better call and this run defers to it. This run published an operational incident entry mapping a spearphishing attachment and user execution, on the strength of a wire agency citing unnamed security circles. The 2026-08-23 fire, working the same story three days later, declined to publish an operational entry at all and said why: no named authority had stated a vector, an unattributed source describes no attacker behaviour to map, and it "maps no ATT&CK technique rather than invent one" — carrying the incident as a synthesis entry instead, which is exactly the disposition the original backlog row had suggested as the alternative. That is the more disciplined reading of the same evidence, and it is now the published one. The registry keeps only that fire's entity key for the incident; this run's duplicate key was dropped rather than left as a second key for a known entity.
The four surviving entities and the state rebase. Because the later fires had already registered their own keys for all six dropped topics, entities/registry.yaml, state/cves_seen.json, state/source_health.json, sources/sources.json and state/coverage_backlog.md were each rebased on origin/main and only this run's still-needed additions re-applied — four entity keys, thirteen ATutor CVE records plus one bumped last_seen, one new candidate source, and one backlog row. That avoids both duplicate keys and the deletion of the later fires' records that a blind ours-wins resolution would have caused. Two source changes this run had made independently — promoting the Latvian national CERT to active, and migrating both NCSC-CH records to the new bacs.admin.ch domain — turned out to have been made identically by a later fire, so main's versions stand.
What actually publishes: five entries, four of them updates. One new entry (the ATutor disclosure) and four updates (ShieldBreak's independent reproduction, the ITG27 Havencode/Toneshell delta, the ZeroBytes French-government footprint, and the Siemens S7 advisory's own detection and hardening sections read from the primary PDF). All five were checked against the later fires' output and none is covered by them. Priorities: one notable × five — no high, no critical, which is the honest reading of a delta set this narrow.
Verification. One iteration, on Opus, verdict NEEDS_FIXES (truth 3, editorial 4, advisory 5), run against the full eleven-entry set before the reconciliation. It fetched all 31 inline source URLs fresh, tested all 33 evidence quotes as literal contiguous substrings — all 33 passed — and upheld every judgement call it was asked to challenge, including both contested drops. Two of its three truth findings applied to surviving entries and were fixed: an ATutor CVE typed as information disclosure where the advisory describes permanent deletion of an administrator's data, and a wrong parameter name on another ATutor CVE. The third applied to an entry the reconciliation removed and is recorded on the iteration rather than lost. Its editorial finding on the ShieldBreak entry — a "roughly ten seconds" figure no source states — was also fixed to the source's eight-to-twelve-second range. No confirmation pass ran: the double-CLEAN gate is waived under the wall-clock watchdog, with the reason recorded in verification.confirmation_waived.
The verifier's headline finding was completeness, and it stands as an open item rather than a fixed one. An in-window, pre-authentication file-upload-to-remote-code-execution flaw in very widely deployed WordPress tooling was deferred to the coverage backlog on the ground that its fields were unobtainable — the article body is unreachable on every transport here and the feed carries only a teaser. The verifier established that the flaw carries CVE-2026-32475 and that both the CNA's own research post and the ENISA vulnerability API — transports this run used successfully elsewhere — carry every missing field, and separately corrected this run's framing: for that item the assigning CNA and originating discloser is Patchstack, not the publisher this run added as a candidate. It was still not published, deliberately: by the time the finding could be acted on the run was ~76 h overrun and two later fires had published. The backlog row is upgraded with the CVE id, the reachable transports and the Patchstack correction so the next fire lands it directly. Patchstack is untracked and could not be added under the one-candidate-per-run cap; it is named in the row.
A capability gap closed, and the bug a real document found. The 2026-08-20 fire published the Siemens S7 joint advisory from an outlet's reading because the advisory ships as a PDF only, nothing here could extract PDF text, and its backlog row asked a later fire to record a working extraction path in the fetch bridge. That is done: the bridge gained a stdlib-only PDF text extractor covering Flate content streams, PDF string-escape and nesting rules, simple fonts and CID fonts via their ToUnicode CMap, with an offline test suite and two deliberate honesty properties — an image-only PDF reports that it found no text objects rather than looking like an empty document, and a CMap-approximated decode is labelled an approximation. Reading the real 333 KB advisory then found a genuine bug in it: a marked-content property dictionary was being mis-parsed as a hex string. Fixed, with a regression test. The advisory yielded 62,519 characters and carries detection and hardening detail no prior entry had, which is why the S7 update survives the dedup.
Composition and window, as researched. Gap of 24.0 h to 2026-08-20T0409Z-intel at the time of research, so a 26 h window — Standard class. The research itself was sound and is not in question: four domain sub-agents plus two scoped Phase 4 deep-read follow-ups, and those follow-ups caught six defects before the verifier ever saw them, including a CVE scoped to one package presented as covering three, a download figure conflating one package's count with a family total, an enumeration that silently dropped one of thirteen CVEs, and — the most consequential — the establishment, by following a citation chain to its source rather than trusting a summary, that no source attributes the Bloctel breach to the actor behind the two other French government intrusions and that no source states a unified investigation across all three. Both of those claims were in the surfacing pass; neither is in the published entry.
borderline-drop lines (as judged at research time, all still standing).
borderline-drop: Operation ASTERIX (fake hardware-wallet applications, seed-phrase theft) — no home-region, coverage-focus or sector nexus; the victims are individual cryptocurrency holders.borderline-drop: mercenary-spyware notification volume across 110 countries — a count with no named spyware family, no attack vector and no defender takeaway.borderline-drop: Cisco Crosswork and Secure Workload hardening releases — internally discovered, not known to be exploited; the routine-patch-cycle exclusion, and the store already published this grouped-hardening-release pattern on 2026-08-08. Both advisories were fetched before the drop; the verifier upheld it.borderline-drop: extortion ultimatum against a Swiss-headquartered manufacturer, deadline 2026-08-21 — leak-site claim only, no victim statement, no samples. The verifier upheld it. NOTE: the deadline has since passed and no later fire appears to have revisited it; worth a look.borderline-drop: three further leak-site listings naming a Swiss data-centre operator, a Spanish municipality and an engineering firm — claims only, no victim statement, no regulator notice, no press.borderline-drop: four out-of-nexus incidents (a healthcare-billing platform, a telecoms provider, a hosting company, a restaurant franchisee) — no nexus and no transferable TTP.borderline-drop: an investment-fraud ecosystem study — US and Australian consumer fraud, no constituency nexus.borderline-drop: a vendor CVE set whose primary could not be reached on any transport — aggregator-only.borderline-drop: an open-redirect advisory with no CVE and vendor detail pending, and an industrial advisory at moderate severity, local-only, patched, unexploited — both below the actionability bar.
Single-source items and carve-outs (surviving entries). single-source-national-cert on the ATutor entry (the coordinating national CSIRT for its own advisory) and on the Siemens S7 update (the authoring agencies' own document). single-source on the ITG27 update — one lab's own deception-environment telemetry, with a note that the lab states no European targeting for the campaign. multi-source on the ShieldBreak update (an independent reproduction plus Microsoft's own record, queried directly) and on the ZeroBytes update (the education ministry's own office, the consumer-protection directorate's own release, and a reporting chain traced to its origin).
Coverage gaps: cisa-advisories (HTTP 403, eighth consecutive run, essential-tier); cisa-directives (HTTP 403, seventh consecutive, essential-tier); ccn-cert-es (403 with the pinned reader transport credit-exhausted); siemens-productcert-csaf (403, fifth consecutive, checked against the CSAF mirror instead); ssd-disclosure (client-rendered shell, reader-only host, fifth consecutive); venarix (client-rendered listing, fourth consecutive); zaufana-trzecia-strona (Cloudflare challenge, RSS readable but pre-window); ccb-belgium (direct path returned no advisory rows after the prior fire reported the recipe fixed — needs a re-check); trellix (stale served index, standing defect); sans-ics (focus-area filter honoured by no transport); paradigm-shift-research (client-rendered shell, top rotation priority); wordfence (feed works, article body unreachable — new record, needs an article-body recipe); jina-reader-pool (seventh consecutive credit exhaustion, 7/7 keys HTTP 402).
Essential-coverage: missed=cisa-advisories (HTTP 403, eighth consecutive run), cisa-directives (HTTP 403, seventh consecutive run).
Watchlist: products checked=0, hits=0; suppliers checked=0, hits=0 — the profile configures no product or supplier watchlist, so both sweeps are no-ops.
Two things the operator should see.
- The container suspension is the story of this fire, not the content. A ~3-day mid-pipeline suspension is a different failure mode from the multi-hour stalls the wall-clock watchdog was built for, and the watchdog cannot detect it from inside — the run had already passed its own gate before the clock jumped. The salvage worked (nothing wrong was published, and the reconciliation caught all six duplicates), but the cost was six entries of composition and verification work, and a 24 h reader window that went uncovered on 2026-08-21 and 2026-08-22 with no run record for either date.
- Seven consecutive fires have now run with the reader pool fully exhausted, and this is the first where it demonstrably cost a publishable item — the WordPress file-upload flaw above was blocked on exactly that rung. Several source records are pinned to the reader exclusively.
← Operations dashboard · day page 2026-08-21 · run-record contract: docs/pipeline.md