{
  "$comment": "The executable half of the profile audit, extended when this repository became a website (2026-09-15). It publishes numbers in exactly three ways now: prose in README.md (the featured-project cards, the projects-index count, the badge set, the waka statistics), pictures generated on a schedule (three cards from scripts/render-cards.mjs, the contribution snake from main.yml, the waka block from wakatime.yml, the reading list from blog-post-workflow.yml), and the personal site committed alongside them - index.html, projects/, blog/, styles.css and script.js, deployed from main by Cloudflare Workers Builds. Every figure this repository can recompute offline from its own files has a command here, run by .github/workflows/claims.yml through alloevil/verify-claims: the cards' daily cron and the generator that produces them, the star count the generator must keep reading from the environment rather than hardcoding (the defect fixed on 2026-09-12), the two SVG variants of the snake against the filenames main.yml publishes, which assets exist and which surface embeds or serves them, that the README's language badges agree with the waka block it displays, that the waka block is machine-written between the action's markers, and that the hero has no generator. The site added seven of the same kind: its four pages' root-relative references all resolve on disk, its project index is a bijection against the captured upstream index (16 entries, same order, repository URLs pinned), its featured grid is the README's own shortlist, its writing index is a bijection against the captured sitemap, its receipt panel reads claims.json instead of copying it, its deploy publishes the staged surface and none of this repository's plumbing, and no site asset is orphaned, and the origin it publishes (site.json, stamped into canonical/og:url/og:image by the build) is the same origin sitemap.xml and robots.txt name. Figures that come from another repository, a published artifact or a network response are checked against a dated capture committed under docs/snapshots/ - a point-in-time excerpt of the source, with its URL and fetch date at the head, that the command parses; freshness is not checked there, and each such claim's method says what a re-fetch would need. Ten work that way (the codeblast, coding-agent-internals and deepresearch-arms-lab cards, the archmap graph figures, the live Tabby star count, the recall card's newest batch, the ledger card's synthetic demo fixture, the projects-index count, the project index the site renders, and the blog sitemap the site's post list is checked against) and the reading feed is counted from the README's own injected block, leaving three claims manual because no artifact can support them: the WakaTime statistics (a live account behind the WAKATIME_API_KEY secret), the profile-view counter (a third-party tally that increments on every read) and the contribution grid (GitHub's per-day counts, drawn on the runner). A README edit that contradicts a figure now fails the gate; a figure that cannot be recomputed here says so and names where it lives.",
  "project": "alloevil (GitHub profile repository)",
  "repository": "https://github.com/alloevil/alloevil",
  "updated": "2026-09-15",
  "claims": [
    {
      "id": "cards-rendered-daily",
      "claim": "The three profile cards are rendered daily: cards.yml runs on a cron whose day, month and weekday fields are all wildcards (30 3 * * *, 03:30 UTC every day), and the README's card section says they are rendered daily.",
      "value": "daily (30 3 * * *)",
      "metric": "the schedule in .github/workflows/cards.yml versus the phrase rendered daily in README.md's Evidence, Not Widgets section",
      "method": "A cron is daily exactly when its day-of-month, month and day-of-week fields are *, so the schedule itself is the figure. The check is here because this repository has already published a cadence its cron did not have (blog-post-workflow.yml read every hour against 0 */2 * * * until 2026-09-12), and because a card job that stops firing looks exactly like a card that is up to date.",
      "repro": "python3 -c 'import re, pathlib\ny = pathlib.Path(\".github/workflows/cards.yml\").read_text(encoding=\"utf-8\")\ncron = re.search(r\"cron:\\s*[^0-9]*([0-9*/,\\- ]+)\", y, re.M).group(1).strip()\nf = cron.split()\ndaily = len(f) == 5 and f[2:] == [\"*\", \"*\", \"*\"]\nreadme = pathlib.Path(\"README.md\").read_text(encoding=\"utf-8\")\nsays = \"rendered daily\" in readme\nif not (daily and says):\n    print(cron + \" daily=\" + str(daily) + \" README-rendered-daily=\" + str(says))\n    raise SystemExit(1)\nprint(cron + \" -> daily=\" + str(daily) + \" | README states rendered daily=\" + str(says))'",
      "evidence": ".github/workflows/cards.yml + README.md",
      "as_of": "2026-09-13",
      "check": {
        "cmd": "python3 -c 'import re, pathlib\ny = pathlib.Path(\".github/workflows/cards.yml\").read_text(encoding=\"utf-8\")\ncron = re.search(r\"cron:\\s*[^0-9]*([0-9*/,\\- ]+)\", y, re.M).group(1).strip()\nf = cron.split()\ndaily = len(f) == 5 and f[2:] == [\"*\", \"*\", \"*\"]\nreadme = pathlib.Path(\"README.md\").read_text(encoding=\"utf-8\")\nsays = \"rendered daily\" in readme\nif not (daily and says):\n    print(cron + \" daily=\" + str(daily) + \" README-rendered-daily=\" + str(says))\n    raise SystemExit(1)\nprint(cron + \" -> daily=\" + str(daily) + \" | README states rendered daily=\" + str(says))'",
        "expect": {
          "equals": "30 3 * * * -> daily=True | README states rendered daily=True"
        },
        "timeout": 60
      }
    },
    {
      "id": "cards-are-generator-output-only",
      "claim": "The three cards the README embeds are the generator's output and nothing else: scripts/render-cards.mjs names exactly archmap-card.svg, recall-card.svg and ledger-card.svg, the README embeds exactly those three from the output branch, and no copy of any card is committed to the default branch.",
      "value": "3 generator names = 3 README embeds, 0 committed copies",
      "metric": "the card names in scripts/render-cards.mjs versus the /output/ card URLs in README.md versus any *-card.svg in the working tree",
      "method": "cards.yml writes the cards to the output branch and re-carries them there on every run; a card committed on the default branch would shadow the generated one and never be refreshed. Reading all three surfaces at once means renaming a card in the generator without the README fails here instead of rendering a 404.",
      "repro": "python3 -c 'import re, pathlib\nscript = pathlib.Path(\"scripts/render-cards.mjs\").read_text(encoding=\"utf-8\")\nreadme = pathlib.Path(\"README.md\").read_text(encoding=\"utf-8\")\nmade = sorted(set(re.findall(r\"\\b([a-z]+-card)\\.svg\", script)))\nshown = sorted(set(re.findall(r\"/output/([a-z]+-card)\\.svg\", readme)))\ncommitted = sorted(str(p) for p in pathlib.Path(\".\").rglob(\"*-card.svg\") if \".git\" not in p.parts)\nif not (len(made) == 3 and made == shown and not committed):\n    print(\"generator=\" + str(made) + \" README=\" + str(shown) + \" committed=\" + str(committed))\n    raise SystemExit(1)\nprint(\"generator card names=\" + str(len(made)) + \" README output-branch embeds=\" + str(len(shown)) + \" identical=\" + str(made == shown) + \" committed copies here=\" + str(len(committed)))'",
      "evidence": "scripts/render-cards.mjs + README.md + .github/workflows/cards.yml",
      "as_of": "2026-09-13",
      "check": {
        "cmd": "python3 -c 'import re, pathlib\nscript = pathlib.Path(\"scripts/render-cards.mjs\").read_text(encoding=\"utf-8\")\nreadme = pathlib.Path(\"README.md\").read_text(encoding=\"utf-8\")\nmade = sorted(set(re.findall(r\"\\b([a-z]+-card)\\.svg\", script)))\nshown = sorted(set(re.findall(r\"/output/([a-z]+-card)\\.svg\", readme)))\ncommitted = sorted(str(p) for p in pathlib.Path(\".\").rglob(\"*-card.svg\") if \".git\" not in p.parts)\nif not (len(made) == 3 and made == shown and not committed):\n    print(\"generator=\" + str(made) + \" README=\" + str(shown) + \" committed=\" + str(committed))\n    raise SystemExit(1)\nprint(\"generator card names=\" + str(len(made)) + \" README output-branch embeds=\" + str(len(shown)) + \" identical=\" + str(made == shown) + \" committed copies here=\" + str(len(committed)))'",
        "expect": {
          "equals": "generator card names=3 README output-branch embeds=3 identical=True committed copies here=0"
        },
        "timeout": 60
      }
    },
    {
      "id": "star-count-not-hardcoded",
      "claim": "The archmap legend's star count is measured at render time, not written into the generator: render-cards.mjs reads process.env.TABBY_STARS, omits the whole segment when the variable is unset or zero, and contains no NNk-star literal; cards.yml fills the variable with gh api repos/Eugeny/tabby --jq .stargazers_count.",
      "value": "env-driven, 0 hardcoded star literals",
      "metric": "process.env.TABBY_STARS and the nk-star template in scripts/render-cards.mjs, plus the TABBY_STARS assignment in .github/workflows/cards.yml",
      "method": "This is the defect the 2026-09-12 audit fixed and the reason this claims file exists: the legend carried a hardcoded 60k-star literal inside the script that re-renders the card daily, so the daily job could never correct it (upstream was 74,442 stars that day). The check pins all three parts of the mechanism - env read, unset-guard, live query - because dropping any one of them silently restores a hand-written number. Verified by running the generator here on 2026-09-13: with TABBY_STARS=74442 the legend prints Eugeny/tabby (~74k*), with no variable set the star segment is absent.",
      "repro": "python3 -c 'import re, pathlib\nscript = pathlib.Path(\"scripts/render-cards.mjs\").read_text(encoding=\"utf-8\")\ny = pathlib.Path(\".github/workflows/cards.yml\").read_text(encoding=\"utf-8\")\nenvd = \"process.env.TABBY_STARS\" in script\nguarded = \"TABBY_STARS > 0\" in script\nhard = re.findall(r\"[0-9]+\\s*k\\u2605\", script)\nfetched = \"gh api repos/Eugeny/tabby\" in y and \"TABBY_STARS=\" in y\nif not (envd and guarded and not hard and fetched):\n    print(\"env=\" + str(envd) + \" guarded=\" + str(guarded) + \" literals=\" + str(hard) + \" fetched=\" + str(fetched))\n    raise SystemExit(1)\nprint(\"legend stars from TABBY_STARS env=\" + str(envd) + \" omitted when unset=\" + str(guarded) + \" hardcoded star literals=\" + str(len(hard)) + \" cards.yml queries stargazers_count=\" + str(fetched))'",
      "evidence": "scripts/render-cards.mjs + .github/workflows/cards.yml",
      "as_of": "2026-09-13",
      "check": {
        "cmd": "python3 -c 'import re, pathlib\nscript = pathlib.Path(\"scripts/render-cards.mjs\").read_text(encoding=\"utf-8\")\ny = pathlib.Path(\".github/workflows/cards.yml\").read_text(encoding=\"utf-8\")\nenvd = \"process.env.TABBY_STARS\" in script\nguarded = \"TABBY_STARS > 0\" in script\nhard = re.findall(r\"[0-9]+\\s*k\\u2605\", script)\nfetched = \"gh api repos/Eugeny/tabby\" in y and \"TABBY_STARS=\" in y\nif not (envd and guarded and not hard and fetched):\n    print(\"env=\" + str(envd) + \" guarded=\" + str(guarded) + \" literals=\" + str(hard) + \" fetched=\" + str(fetched))\n    raise SystemExit(1)\nprint(\"legend stars from TABBY_STARS env=\" + str(envd) + \" omitted when unset=\" + str(guarded) + \" hardcoded star literals=\" + str(len(hard)) + \" cards.yml queries stargazers_count=\" + str(fetched))'",
        "expect": {
          "equals": "legend stars from TABBY_STARS env=True omitted when unset=True hardcoded star literals=0 cards.yml queries stargazers_count=True"
        },
        "timeout": 60
      }
    },
    {
      "id": "readme-local-assets-exist",
      "claim": "Both assets the README embeds from this repository exist at the path it names: ./assets/readme/hero.svg (the hero) and ./assets/readme/made-with-beautify.svg (the signature).",
      "value": "2 local refs, 0 missing",
      "metric": "every src= / srcset= in README.md that starts with ./ resolved on disk",
      "method": "These two are the only images this repository serves from itself; a rename or a case change turns the README's first screen into a broken icon with nothing in CI to notice. Every other image in the README is a remote URL (the output branch, shields.io, komarev) and is deliberately out of scope.",
      "repro": "python3 -c 'import re, pathlib\nreadme = pathlib.Path(\"README.md\").read_text(encoding=\"utf-8\")\nrefs = sorted(set(re.findall(r\"(?:src|srcset)=\\\"(\\./[^\\\"]+)\\\"\", readme)))\nmissing = [r for r in refs if not pathlib.Path(r).is_file()]\nif not refs or missing:\n    print(\"refs=\" + str(refs) + \" missing=\" + str(missing))\n    raise SystemExit(1)\nprint(str(len(refs)) + \" local asset refs, all committed: \" + \" \".join(r[2:] for r in refs))'",
      "evidence": "README.md + assets/readme/",
      "as_of": "2026-09-13",
      "check": {
        "cmd": "python3 -c 'import re, pathlib\nreadme = pathlib.Path(\"README.md\").read_text(encoding=\"utf-8\")\nrefs = sorted(set(re.findall(r\"(?:src|srcset)=\\\"(\\./[^\\\"]+)\\\"\", readme)))\nmissing = [r for r in refs if not pathlib.Path(r).is_file()]\nif not refs or missing:\n    print(\"refs=\" + str(refs) + \" missing=\" + str(missing))\n    raise SystemExit(1)\nprint(str(len(refs)) + \" local asset refs, all committed: \" + \" \".join(r[2:] for r in refs))'",
        "expect": {
          "equals": "2 local asset refs, all committed: assets/readme/hero.svg assets/readme/made-with-beautify.svg"
        },
        "timeout": 60
      }
    },
    {
      "id": "badges-match-waka-languages",
      "claim": "The language badges agree with the waka block the same README displays: Primary Python and Secondary JavaScript are the top two languages by repo count in the I Mostly Code in block, and each badge's link filters the same language it names.",
      "value": "Primary Python / Secondary JavaScript = waka top-2 Python JavaScript",
      "metric": "the language= parameter and badge label of the two language badges in README.md versus the repo counts in the generated waka block",
      "method": "The badge read Secondary TypeScript until 2026-09-12 while the block two screens below listed JavaScript 10 repos 23.81% above TypeScript 9 repos 21.43% - a badge contradicting the statistics it sits above. The check recomputes the order from the block rather than trusting the badge text.",
      "repro": "python3 -c 'import re, pathlib\nreadme = pathlib.Path(\"README.md\").read_text(encoding=\"utf-8\")\nbadges = re.findall(r\"language=([a-z]+)\\\"><img alt=\\\"[^\\\"]*\\\" src=\\\"[^\\\"]*badge/[^\\\"]*?-([A-Za-z+#.]+)-[0-9A-Fa-f]{6}\", readme)\nlabels = [b[1] for b in badges]\nhrefs = [b[0] for b in badges]\nwaka = readme[readme.index(\"START_SECTION:waka\"):readme.index(\"END_SECTION:waka\")]\nrows = re.findall(r\"^([A-Za-z+#]+)\\s+([0-9]+) repos\", waka, re.M)\ntop = [r[0] for r in sorted(rows, key=lambda r: -int(r[1]))[:2]]\nif not (len(badges) == 2 and labels == top and hrefs == [x.lower() for x in labels]):\n    print(\"badges=\" + str(badges) + \" waka-top2=\" + str(top))\n    raise SystemExit(1)\nprint(\"language badges \" + labels[0] + \"/\" + labels[1] + \" = the waka block top-2 by repos (\" + \" \".join(top) + \"), and each badge href filters the same language\")'",
      "evidence": "README.md (badges + the waka section)",
      "as_of": "2026-09-13",
      "check": {
        "cmd": "python3 -c 'import re, pathlib\nreadme = pathlib.Path(\"README.md\").read_text(encoding=\"utf-8\")\nbadges = re.findall(r\"language=([a-z]+)\\\"><img alt=\\\"[^\\\"]*\\\" src=\\\"[^\\\"]*badge/[^\\\"]*?-([A-Za-z+#.]+)-[0-9A-Fa-f]{6}\", readme)\nlabels = [b[1] for b in badges]\nhrefs = [b[0] for b in badges]\nwaka = readme[readme.index(\"START_SECTION:waka\"):readme.index(\"END_SECTION:waka\")]\nrows = re.findall(r\"^([A-Za-z+#]+)\\s+([0-9]+) repos\", waka, re.M)\ntop = [r[0] for r in sorted(rows, key=lambda r: -int(r[1]))[:2]]\nif not (len(badges) == 2 and labels == top and hrefs == [x.lower() for x in labels]):\n    print(\"badges=\" + str(badges) + \" waka-top2=\" + str(top))\n    raise SystemExit(1)\nprint(\"language badges \" + labels[0] + \"/\" + labels[1] + \" = the waka block top-2 by repos (\" + \" \".join(top) + \"), and each badge href filters the same language\")'",
        "expect": {
          "equals": "language badges Python/JavaScript = the waka block top-2 by repos (Python JavaScript), and each badge href filters the same language"
        },
        "timeout": 60
      }
    },
    {
      "id": "snake-both-variants-published",
      "claim": "The snake is published in both colour variants main.yml generates: the dark source points at github-contribution-grid-snake-dark.svg, the light source and the fallback img at github-contribution-grid-snake.svg, and the workflow's snk step declares exactly those two outputs (the dark one with palette=github-dark).",
      "value": "dark/light pair matches the two declared snk outputs",
      "metric": "the two prefers-color-scheme srcsets and the fallback img in README.md versus the outputs block of the Platane/snk step in .github/workflows/main.yml",
      "method": "Until 2026-09-12 the dark source pointed at the light SVG, so the dark file was generated every two hours and never displayed. Pairing the README's srcsets with the filenames the snk step writes makes a rename on either side fail instead of silently rendering the wrong palette.",
      "repro": "python3 -c 'import re, pathlib\nreadme = pathlib.Path(\"README.md\").read_text(encoding=\"utf-8\")\ny = pathlib.Path(\".github/workflows/main.yml\").read_text(encoding=\"utf-8\")\nsrcs = dict(re.findall(r\"<source media=\\\"\\(prefers-color-scheme: ([a-z]+)\\)\\\" srcset=\\\"[^\\\"]*?/([^\\\"/]+)\\\"\", readme))\nimg = re.search(r\"<img alt=\\\"github contribution grid snake animation\\\" src=\\\"[^\\\"]*?/([^\\\"/]+)\\\"\", readme).group(1)\npublished = sorted(set(re.findall(r\"dist/(github-contribution-grid-snake[a-z-]*\\.svg)\", y)))\nwant = {\"dark\": \"github-contribution-grid-snake-dark.svg\", \"light\": \"github-contribution-grid-snake.svg\"}\nif not (srcs == want and img == want[\"light\"] and published == sorted(want.values())):\n    print(\"sources=\" + str(srcs) + \" fallback=\" + img + \" main.yml outputs=\" + str(published))\n    raise SystemExit(1)\nprint(\"dark=\" + srcs[\"dark\"] + \" light=\" + srcs[\"light\"] + \" fallback=\" + img + \" | snk publishes both variants=\" + str(len(published) == 2))'",
      "evidence": "README.md + .github/workflows/main.yml",
      "as_of": "2026-09-13",
      "check": {
        "cmd": "python3 -c 'import re, pathlib\nreadme = pathlib.Path(\"README.md\").read_text(encoding=\"utf-8\")\ny = pathlib.Path(\".github/workflows/main.yml\").read_text(encoding=\"utf-8\")\nsrcs = dict(re.findall(r\"<source media=\\\"\\(prefers-color-scheme: ([a-z]+)\\)\\\" srcset=\\\"[^\\\"]*?/([^\\\"/]+)\\\"\", readme))\nimg = re.search(r\"<img alt=\\\"github contribution grid snake animation\\\" src=\\\"[^\\\"]*?/([^\\\"/]+)\\\"\", readme).group(1)\npublished = sorted(set(re.findall(r\"dist/(github-contribution-grid-snake[a-z-]*\\.svg)\", y)))\nwant = {\"dark\": \"github-contribution-grid-snake-dark.svg\", \"light\": \"github-contribution-grid-snake.svg\"}\nif not (srcs == want and img == want[\"light\"] and published == sorted(want.values())):\n    print(\"sources=\" + str(srcs) + \" fallback=\" + img + \" main.yml outputs=\" + str(published))\n    raise SystemExit(1)\nprint(\"dark=\" + srcs[\"dark\"] + \" light=\" + srcs[\"light\"] + \" fallback=\" + img + \" | snk publishes both variants=\" + str(len(published) == 2))'",
        "expect": {
          "equals": "dark=github-contribution-grid-snake-dark.svg light=github-contribution-grid-snake.svg fallback=github-contribution-grid-snake.svg | snk publishes both variants=True"
        },
        "timeout": 60
      }
    },
    {
      "id": "assets-inventory",
      "claim": "assets/ holds six files in two groups: the README's two (readme/hero.svg, readme/made-with-beautify.svg), which README.md embeds, and the site's three (site/favicon.svg, site/theme.js, site/og.png), which the pages reference; assets/bar_graph.png is a bot artifact no page references.",
      "value": "6 files: 2 README-embedded + 3 site-referenced + 1 orphan",
      "metric": "every file under assets/ versus the references in README.md and in the four pages, plus the path list scripts/build-site.mjs stages",
      "method": "This claim said three files until the site was added (2026-09-15). The site brought its own assets - two at first, then a third when the social preview image was captured - so the count moved and the check moved with it: the assertion now also reads the build's PUBLISHED list, because an asset the README embeds must not be staged as a page resource while an asset the site references must be. bar_graph.png stays the one committed file nothing displays: the metrics bot rewrites it and no page embeds it.",
      "repro": "python3 -c 'import pathlib\nassets = sorted(str(p) for p in pathlib.Path(\"assets\").rglob(\"*\") if p.is_file())\nreadme = pathlib.Path(\"README.md\").read_text(encoding=\"utf-8\")\nsite = \"\".join(pathlib.Path(p).read_text(encoding=\"utf-8\") for p in [\"index.html\", \"404.html\", \"projects/index.html\", \"blog/index.html\", \"styles.css\", \"script.js\"])\nembedded = [a for a in assets if \"src=\\\"./\" + a + \"\\\"\" in readme]\nserved = [a for a in assets if \"/\" + a in site]\norphans = [a for a in assets if a not in embedded and a not in served]\npublished = pathlib.Path(\"scripts/build-site.mjs\").read_text(encoding=\"utf-8\").split(\"PUBLISHED = [\")[1].split(\"]\")[0]\nif not (len(assets) == 6 and len(embedded) == 2 and len(served) == 3 and orphans == [\"assets/bar_graph.png\"] and \"\\\"assets/readme\\\"\" not in published and \"\\\"assets/site\\\"\" in published):\n    print(\"assets=\" + str(assets) + \" embedded=\" + str(embedded) + \" served=\" + str(served) + \" orphans=\" + str(orphans) + \" published=\" + published)\n    raise SystemExit(1)\nprint(\"assets/ holds \" + str(len(assets)) + \" files: \" + str(len(embedded)) + \" embedded by the README (\" + \", \".join(a[7:] for a in embedded) + \"), \" + str(len(served)) + \" referenced by the site (\" + \", \".join(a[7:] for a in served) + \"); assets/bar_graph.png is a bot artifact no page references; the build stages assets/site and never assets/readme\")'",
      "evidence": "assets/ + README.md + the four pages + scripts/build-site.mjs",
      "as_of": "2026-09-15",
      "check": {
        "cmd": "python3 -c 'import pathlib\nassets = sorted(str(p) for p in pathlib.Path(\"assets\").rglob(\"*\") if p.is_file())\nreadme = pathlib.Path(\"README.md\").read_text(encoding=\"utf-8\")\nsite = \"\".join(pathlib.Path(p).read_text(encoding=\"utf-8\") for p in [\"index.html\", \"404.html\", \"projects/index.html\", \"blog/index.html\", \"styles.css\", \"script.js\"])\nembedded = [a for a in assets if \"src=\\\"./\" + a + \"\\\"\" in readme]\nserved = [a for a in assets if \"/\" + a in site]\norphans = [a for a in assets if a not in embedded and a not in served]\npublished = pathlib.Path(\"scripts/build-site.mjs\").read_text(encoding=\"utf-8\").split(\"PUBLISHED = [\")[1].split(\"]\")[0]\nif not (len(assets) == 6 and len(embedded) == 2 and len(served) == 3 and orphans == [\"assets/bar_graph.png\"] and \"\\\"assets/readme\\\"\" not in published and \"\\\"assets/site\\\"\" in published):\n    print(\"assets=\" + str(assets) + \" embedded=\" + str(embedded) + \" served=\" + str(served) + \" orphans=\" + str(orphans) + \" published=\" + published)\n    raise SystemExit(1)\nprint(\"assets/ holds \" + str(len(assets)) + \" files: \" + str(len(embedded)) + \" embedded by the README (\" + \", \".join(a[7:] for a in embedded) + \"), \" + str(len(served)) + \" referenced by the site (\" + \", \".join(a[7:] for a in served) + \"); assets/bar_graph.png is a bot artifact no page references; the build stages assets/site and never assets/readme\")'",
        "expect": {
          "equals": "assets/ holds 6 files: 2 embedded by the README (readme/hero.svg, readme/made-with-beautify.svg), 3 referenced by the site (site/favicon.svg, site/og.png, site/theme.js); assets/bar_graph.png is a bot artifact no page references; the build stages assets/site and never assets/readme"
        },
        "timeout": 60
      }
    },
    {
      "id": "waka-block-is-generated",
      "claim": "The waka block in the README - including its Last Updated on MM/DD/YYYY HH:MM:SS UTC stamp - is written by the scheduled workflow and not by hand: the block sits between exactly one paired set of the action's markers and carries a well-formed stamp, wakatime.yml runs anmol098/waka-readme-stats against README.md with no README_FILE override, and its cron 30 18 * * * is 18:30 UTC = 00:00 IST, which is what that file's own comment (Runs at 12am IST) says.",
      "value": "markers paired, action owns README.md, 30 18 * * * = 00:00 IST",
      "metric": "the START/END markers and the stamp format inside README.md's waka section, the action and its inputs in .github/workflows/wakatime.yml, and the cron arithmetic against that file's comment",
      "method": "The stamp is the only date on the page telling a reader when these statistics were true. If a marker is lost the action appends a second block or stops replacing the first while the frozen stamp keeps looking authoritative; the IST arithmetic is checked because the comment and the cron are two statements of one schedule and only the cron is executed.",
      "repro": "python3 -c 'import re, pathlib\nreadme = pathlib.Path(\"README.md\").read_text(encoding=\"utf-8\")\ny = pathlib.Path(\".github/workflows/wakatime.yml\").read_text(encoding=\"utf-8\")\ns = readme.count(\"<!--START_SECTION:waka-->\")\ne = readme.count(\"<!--END_SECTION:waka-->\")\npaired = s == 1 and e == 1 and readme.index(\"<!--START_SECTION:waka-->\") < readme.index(\"<!--END_SECTION:waka-->\")\nwaka = readme[readme.index(\"<!--START_SECTION:waka-->\"):readme.index(\"<!--END_SECTION:waka-->\")]\nstamp = bool(re.search(r\"Last Updated on [0-9]{2}/[0-9]{2}/[0-9]{4} [0-9]{2}:[0-9]{2}:[0-9]{2} UTC\", waka))\nuses = \"anmol098/waka-readme-stats\" in y and \"README_FILE\" not in y\ncron = re.search(r\"cron:\\s*[^0-9]*([0-9*/,\\- ]+)\", y, re.M).group(1).strip()\nmins, hours = [int(x) for x in cron.split()[:2]]\nist = (hours * 60 + mins + 330) % 1440\nmidnight = ist == 0 and \"12am IST\" in y\nif not (paired and stamp and uses and midnight):\n    print(\"markers=\" + str(s) + \"/\" + str(e) + \" paired=\" + str(paired) + \" stamp=\" + str(stamp) + \" action-edits-README=\" + str(uses) + \" ist-minute=\" + str(ist) + \" comment-matches=\" + str(midnight))\n    raise SystemExit(1)\nprint(\"waka markers paired=\" + str(paired) + \" stamp well-formed=\" + str(stamp) + \" | anmol098/waka-readme-stats edits README.md (no README_FILE override)=\" + str(uses) + \" | cron \" + cron + \" = 00:00 IST, matching the comment=\" + str(midnight))'",
      "evidence": "README.md + .github/workflows/wakatime.yml",
      "as_of": "2026-09-13",
      "check": {
        "cmd": "python3 -c 'import re, pathlib\nreadme = pathlib.Path(\"README.md\").read_text(encoding=\"utf-8\")\ny = pathlib.Path(\".github/workflows/wakatime.yml\").read_text(encoding=\"utf-8\")\ns = readme.count(\"<!--START_SECTION:waka-->\")\ne = readme.count(\"<!--END_SECTION:waka-->\")\npaired = s == 1 and e == 1 and readme.index(\"<!--START_SECTION:waka-->\") < readme.index(\"<!--END_SECTION:waka-->\")\nwaka = readme[readme.index(\"<!--START_SECTION:waka-->\"):readme.index(\"<!--END_SECTION:waka-->\")]\nstamp = bool(re.search(r\"Last Updated on [0-9]{2}/[0-9]{2}/[0-9]{4} [0-9]{2}:[0-9]{2}:[0-9]{2} UTC\", waka))\nuses = \"anmol098/waka-readme-stats\" in y and \"README_FILE\" not in y\ncron = re.search(r\"cron:\\s*[^0-9]*([0-9*/,\\- ]+)\", y, re.M).group(1).strip()\nmins, hours = [int(x) for x in cron.split()[:2]]\nist = (hours * 60 + mins + 330) % 1440\nmidnight = ist == 0 and \"12am IST\" in y\nif not (paired and stamp and uses and midnight):\n    print(\"markers=\" + str(s) + \"/\" + str(e) + \" paired=\" + str(paired) + \" stamp=\" + str(stamp) + \" action-edits-README=\" + str(uses) + \" ist-minute=\" + str(ist) + \" comment-matches=\" + str(midnight))\n    raise SystemExit(1)\nprint(\"waka markers paired=\" + str(paired) + \" stamp well-formed=\" + str(stamp) + \" | anmol098/waka-readme-stats edits README.md (no README_FILE override)=\" + str(uses) + \" | cron \" + cron + \" = 00:00 IST, matching the comment=\" + str(midnight))'",
        "expect": {
          "equals": "waka markers paired=True stamp well-formed=True | anmol098/waka-readme-stats edits README.md (no README_FILE override)=True | cron 30 18 * * * = 00:00 IST, matching the comment=True"
        },
        "timeout": 60
      }
    },
    {
      "id": "hero-has-no-generator",
      "claim": "The hero is hand-authored: assets/readme/hero.svg says so in its own header comment, and no generator in this repository writes it - render-cards.mjs emits the three cards only.",
      "value": "hand-authored header, 0 generators",
      "metric": "the header comment of assets/readme/hero.svg versus the card names scripts/render-cards.mjs writes",
      "method": "After a hand-written figure was found inside the daily generator, every generated-looking asset should state where it comes from. The hero is the figure on the first screen with no reproducible source; this claim keeps that a stated fact rather than a guess, and it is the reason a reader can tell the hero from the three cards.",
      "repro": "python3 -c 'import pathlib\nhero = pathlib.Path(\"assets/readme/hero.svg\").read_text(encoding=\"utf-8\")\nscript = pathlib.Path(\"scripts/render-cards.mjs\").read_text(encoding=\"utf-8\")\ndeclared = \"Hand-authored header\" in hero\ngenerated = \"hero.svg\" in script\nif not (declared and not generated):\n    print(\"declares-hand-authored=\" + str(declared) + \" a-generator-writes-it=\" + str(generated))\n    raise SystemExit(1)\nprint(\"hero.svg declares a hand-authored header=\" + str(declared) + \" | card generator writes it=\" + str(generated))'",
      "evidence": "assets/readme/hero.svg + scripts/render-cards.mjs",
      "as_of": "2026-09-13",
      "check": {
        "cmd": "python3 -c 'import pathlib\nhero = pathlib.Path(\"assets/readme/hero.svg\").read_text(encoding=\"utf-8\")\nscript = pathlib.Path(\"scripts/render-cards.mjs\").read_text(encoding=\"utf-8\")\ndeclared = \"Hand-authored header\" in hero\ngenerated = \"hero.svg\" in script\nif not (declared and not generated):\n    print(\"declares-hand-authored=\" + str(declared) + \" a-generator-writes-it=\" + str(generated))\n    raise SystemExit(1)\nprint(\"hero.svg declares a hand-authored header=\" + str(declared) + \" | card generator writes it=\" + str(generated))'",
        "expect": {
          "equals": "hero.svg declares a hand-authored header=True | card generator writes it=False"
        },
        "timeout": 60
      }
    },
    {
      "id": "codeblast-card-figures",
      "claim": "The codeblast card in the featured-projects table publishes the corpus size and the mutation-testing result of a named batch: tRPC, 957 files; n=30 run 2026-08-28, 28/28 killed mutants.",
      "value": "957 files, n=30, 28/28, 2026-08-28",
      "metric": "the committed snapshot docs/snapshots/codeblast-trpc-n30-2026-09-14.json - codeblast's eval/mutation-2026-08-28-trpc-n30.json rows and its SKILL.md graph block - versus the 957-file / n=30 / 28-28 sentence in README.md",
      "method": "The card restates a sibling repository's measurement, and codeblast's own gate recomputes it there (trpc-mutation-impact-recall = 28/28, trpc-graph-scale-measured = 957 files, 6248 nodes, 17072 edges). This repository cannot run that gate - cards.yml only clones codeblast on the runner - so a dated excerpt of the two source files is committed under docs/snapshots/ and the check recomputes 28/28 and 957 files from it, then requires the README card to carry the same figures. The snapshot is a point-in-time capture (2026-09-14): a new batch, or a regenerated graph, in codeblast is not seen here until the snapshot is re-fetched, so freshness is not checked.",
      "repro": "python3 -c 'import json, pathlib\ns = json.loads(pathlib.Path(\"docs/snapshots/codeblast-trpc-n30-2026-09-14.json\").read_text(encoding=\"utf-8\"))\nrun = s[\"mutation_run\"]\nrows = run[\"rows\"]\nscored = [r for r in rows if r[\"scored\"]]\nhits = sum(1 for r in scored if r[\"recall_hit\"])\nfiles = s[\"graph_scale\"][\"block\"][\"files_indexed\"]\nreadme = pathlib.Path(\"README.md\").read_text(encoding=\"utf-8\")\nprose = \"tRPC, 957 files; n=30 run 2026-08-28: 28/28 killed mutants\" in readme\ndated = \"2026-08-28\" in run[\"file\"] and \"-n30\" in run[\"file\"]\nif not (len(rows) == 30 and len(scored) == 28 and hits == 28 and files == 957 and prose and dated):\n    print(\"rows=\" + str(len(rows)) + \" scored=\" + str(len(scored)) + \" hits=\" + str(hits) + \" files=\" + str(files) + \" dated=\" + str(dated) + \" README-matches=\" + str(prose))\n    raise SystemExit(1)\nprint(\"codeblast snapshot (\" + run[\"file\"] + \"): \" + str(files) + \" files | \" + str(hits) + \"/\" + str(len(scored)) + \" recalled | README card matches=\" + str(prose))'",
      "evidence": "docs/snapshots/codeblast-trpc-n30-2026-09-14.json + README.md",
      "as_of": "2026-09-14",
      "check": {
        "cmd": "python3 -c 'import json, pathlib\ns = json.loads(pathlib.Path(\"docs/snapshots/codeblast-trpc-n30-2026-09-14.json\").read_text(encoding=\"utf-8\"))\nrun = s[\"mutation_run\"]\nrows = run[\"rows\"]\nscored = [r for r in rows if r[\"scored\"]]\nhits = sum(1 for r in scored if r[\"recall_hit\"])\nfiles = s[\"graph_scale\"][\"block\"][\"files_indexed\"]\nreadme = pathlib.Path(\"README.md\").read_text(encoding=\"utf-8\")\nprose = \"tRPC, 957 files; n=30 run 2026-08-28: 28/28 killed mutants\" in readme\ndated = \"2026-08-28\" in run[\"file\"] and \"-n30\" in run[\"file\"]\nif not (len(rows) == 30 and len(scored) == 28 and hits == 28 and files == 957 and prose and dated):\n    print(\"rows=\" + str(len(rows)) + \" scored=\" + str(len(scored)) + \" hits=\" + str(hits) + \" files=\" + str(files) + \" dated=\" + str(dated) + \" README-matches=\" + str(prose))\n    raise SystemExit(1)\nprint(\"codeblast snapshot (\" + run[\"file\"] + \"): \" + str(files) + \" files | \" + str(hits) + \"/\" + str(len(scored)) + \" recalled | README card matches=\" + str(prose))'",
        "expect": {
          "equals": "codeblast snapshot (eval/mutation-2026-08-28-trpc-n30.json): 957 files | 28/28 recalled | README card matches=True"
        },
        "timeout": 60
      }
    },
    {
      "id": "coding-agent-internals-figures",
      "claim": "The coding-agent-internals card publishes the size of that repository's comparison: 12 coding agents, across search, edit, LSP, DAP and sub-agents.",
      "value": "12 agents, 5 dimensions",
      "metric": "the committed snapshot docs/snapshots/coding-agent-internals-2026-09-14.json (that repository's agents/ and dimensions/ listings) versus the 12-agent and 5-dimension sentence in README.md",
      "method": "The count is the length of that repository's own agent pages, and its claims.json checks it there (agents-page-count = 12, dimensions-page-count = 5, agent-page-tables = 12 / 12 / 10). Nothing in this profile repository can enumerate those pages offline, so a dated listing of the two directories is committed and the check counts it and requires the README card to agree - five dimensions only means the page names are all present and .md. Point-in-time capture (2026-09-14): a page added upstream is invisible here until the snapshot is re-fetched, so freshness is not checked.",
      "repro": "python3 -c 'import json, pathlib\ns = json.loads(pathlib.Path(\"docs/snapshots/coding-agent-internals-2026-09-14.json\").read_text(encoding=\"utf-8\"))\nagents = s[\"agents\"][\"names\"]\ndims = s[\"dimensions\"][\"names\"]\nreadme = pathlib.Path(\"README.md\").read_text(encoding=\"utf-8\")\nprose = \"How 12 coding agents\" in readme and \"search, edit, LSP, DAP and sub-agents\" in readme\npaged = all(n.endswith(\".md\") for n in agents + dims)\nif not (len(agents) == 12 and len(dims) == 5 and paged and prose):\n    print(\"agents=\" + str(len(agents)) + \" dimensions=\" + str(len(dims)) + \" pages=\" + str(paged) + \" README-matches=\" + str(prose))\n    raise SystemExit(1)\nprint(\"coding-agent-internals snapshot: \" + str(len(agents)) + \" agent pages, \" + str(len(dims)) + \" dimension pages | README card matches=\" + str(prose))'",
      "evidence": "docs/snapshots/coding-agent-internals-2026-09-14.json + README.md",
      "as_of": "2026-09-14",
      "check": {
        "cmd": "python3 -c 'import json, pathlib\ns = json.loads(pathlib.Path(\"docs/snapshots/coding-agent-internals-2026-09-14.json\").read_text(encoding=\"utf-8\"))\nagents = s[\"agents\"][\"names\"]\ndims = s[\"dimensions\"][\"names\"]\nreadme = pathlib.Path(\"README.md\").read_text(encoding=\"utf-8\")\nprose = \"How 12 coding agents\" in readme and \"search, edit, LSP, DAP and sub-agents\" in readme\npaged = all(n.endswith(\".md\") for n in agents + dims)\nif not (len(agents) == 12 and len(dims) == 5 and paged and prose):\n    print(\"agents=\" + str(len(agents)) + \" dimensions=\" + str(len(dims)) + \" pages=\" + str(paged) + \" README-matches=\" + str(prose))\n    raise SystemExit(1)\nprint(\"coding-agent-internals snapshot: \" + str(len(agents)) + \" agent pages, \" + str(len(dims)) + \" dimension pages | README card matches=\" + str(prose))'",
        "expect": {
          "equals": "coding-agent-internals snapshot: 12 agent pages, 5 dimension pages | README card matches=True"
        },
        "timeout": 60
      }
    },
    {
      "id": "deepresearch-arms-figures",
      "claim": "The deepresearch-arms-lab card publishes the study's shape and its outcome: a 14-arm ablation on a weak base model, re-validated at n=15 and then n=24, with the n=15 advantage not surviving.",
      "value": "14 arms, n=15 and n=24",
      "metric": "the committed snapshot docs/snapshots/deepresearch-arms-lab-2026-09-14.json - qa_data.json's arm keys and row counts, eval/questions_ext.json's 24 ids, and the EXPERIMENTS.md lines carrying the n=15 expansion and its retraction - versus the card sentence in README.md",
      "method": "The arm count and the two question-set sizes are that repository's own experiment log, and its claims.json holds the receipts there. A dated excerpt is committed here so the numbers are counted rather than trusted: 14 arms with committed per-question results, the 24-id extended question set, the line that takes the statistical base from n=10 to n=15, and the line where the n=15 advantage (+0.12) flips to -0.10 at n=20. Point-in-time capture (2026-09-14): the study can be extended upstream without this repository changing, and freshness is not checked.",
      "repro": "python3 -c 'import json, pathlib\ns = json.loads(pathlib.Path(\"docs/snapshots/deepresearch-arms-lab-2026-09-14.json\").read_text(encoding=\"utf-8\"))\narms = s[\"arms\"][\"row_counts\"]\nqset = s[\"question_set\"][\"ids\"]\ntexts = [e[\"text\"] for e in s[\"experiments\"][\"lines\"]]\nn15 = any(\"n=15\" in t for t in texts)\nretracted = any(\"+0.12\" in t and \"\\u22120.10\" in t for t in texts)\nreadme = pathlib.Path(\"README.md\").read_text(encoding=\"utf-8\")\nprose = \"14-arm ablation\" in readme and \"(n=15, then n=24)\" in readme and \"the n=15 advantage did not survive\" in readme\nif not (len(arms) == 14 and len(qset) == 24 and max(arms.values()) == 24 and n15 and retracted and prose):\n    print(\"arms=\" + str(len(arms)) + \" qset=\" + str(len(qset)) + \" maxrows=\" + str(max(arms.values())) + \" n15=\" + str(n15) + \" retracted=\" + str(retracted) + \" README-matches=\" + str(prose))\n    raise SystemExit(1)\nprint(\"deepresearch-arms-lab snapshot: \" + str(len(arms)) + \" arms | n=15 recorded, n=24 question set (\" + str(len(qset)) + \") | n=15 advantage retracted=\" + str(retracted) + \" | README card matches=\" + str(prose))'",
      "evidence": "docs/snapshots/deepresearch-arms-lab-2026-09-14.json + README.md",
      "as_of": "2026-09-14",
      "check": {
        "cmd": "python3 -c 'import json, pathlib\ns = json.loads(pathlib.Path(\"docs/snapshots/deepresearch-arms-lab-2026-09-14.json\").read_text(encoding=\"utf-8\"))\narms = s[\"arms\"][\"row_counts\"]\nqset = s[\"question_set\"][\"ids\"]\ntexts = [e[\"text\"] for e in s[\"experiments\"][\"lines\"]]\nn15 = any(\"n=15\" in t for t in texts)\nretracted = any(\"+0.12\" in t and \"\\u22120.10\" in t for t in texts)\nreadme = pathlib.Path(\"README.md\").read_text(encoding=\"utf-8\")\nprose = \"14-arm ablation\" in readme and \"(n=15, then n=24)\" in readme and \"the n=15 advantage did not survive\" in readme\nif not (len(arms) == 14 and len(qset) == 24 and max(arms.values()) == 24 and n15 and retracted and prose):\n    print(\"arms=\" + str(len(arms)) + \" qset=\" + str(len(qset)) + \" maxrows=\" + str(max(arms.values())) + \" n15=\" + str(n15) + \" retracted=\" + str(retracted) + \" README-matches=\" + str(prose))\n    raise SystemExit(1)\nprint(\"deepresearch-arms-lab snapshot: \" + str(len(arms)) + \" arms | n=15 recorded, n=24 question set (\" + str(len(qset)) + \") | n=15 advantage retracted=\" + str(retracted) + \" | README card matches=\" + str(prose))'",
        "expect": {
          "equals": "deepresearch-arms-lab snapshot: 14 arms | n=15 recorded, n=24 question set (24) | n=15 advantage retracted=True | README card matches=True"
        },
        "timeout": 60
      }
    },
    {
      "id": "archmap-card-graph-figures",
      "claim": "The archmap card publishes the Tabby module graph it draws: 16 packages, 32 import edges, plus each node's file count and fan-in.",
      "value": "16 packages, 32 import edges",
      "metric": "the committed snapshots docs/snapshots/codeblast-tabby-arch-2026-09-14.json (codeblast's committed DATA graph of modules and modEdges) and docs/snapshots/archmap-card-2026-09-14.json (the card deployed on the output branch): module count, import-edge count, and every drawn node's file count and fan-in",
      "method": "The graph is codeblast's committed artifact and the card is its dagre re-layout, which needs codeblast's installed dagre to re-run - cards.yml does that on the runner. Both are captured dated under docs/snapshots/ (the arch page is ~425 KB, so only its DATA graph is excerpted; the card capture holds the legend and each drawn node's printed figures). The check recomputes 16 packages, 32 import edges and every node's files/fan-in from the graph, and requires the deployed card to print exactly those. Point-in-time capture (2026-09-14): a regenerated graph in codeblast, or a re-rendered card, is not seen until the snapshots are re-fetched, so freshness is not checked.",
      "repro": "python3 -c 'import json, pathlib\ng = json.loads(pathlib.Path(\"docs/snapshots/codeblast-tabby-arch-2026-09-14.json\").read_text(encoding=\"utf-8\"))\ncard = json.loads(pathlib.Path(\"docs/snapshots/archmap-card-2026-09-14.json\").read_text(encoding=\"utf-8\"))\npkgs = len(g[\"modules\"])\nedges = sum(1 for e in g[\"mod_edges\"] if e[\"src\"] != e[\"dst\"])\nlegend = \"16 packages\" in card[\"legend\"] and \"32 import edges\" in card[\"legend\"]\nexpected = sorted((m[\"name\"].replace(\"tabby-\", \"\"), m[\"files\"], sum(e[\"w\"] for e in g[\"mod_edges\"] if e[\"dst\"] == m[\"name\"])) for m in g[\"modules\"])\ndrawn = sorted((n[\"label\"], n[\"files\"], n[\"fan_in\"]) for n in card[\"nodes\"][\"counted\"])\nmatch = expected == drawn and card[\"subtitle\"].endswith(g[\"generated\"].split()[0])\nif not (pkgs == 16 and edges == 32 and legend and match):\n    print(\"modules=\" + str(pkgs) + \" import-edges=\" + str(edges) + \" legend=\" + str(legend) + \" per-node-match=\" + str(match))\n    raise SystemExit(1)\nprint(\"tabby graph snapshot: \" + str(pkgs) + \" packages, \" + str(edges) + \" import edges, per-node files/fan-in match=\" + str(match) + \" | deployed card legend agrees=\" + str(legend))'",
      "evidence": "docs/snapshots/codeblast-tabby-arch-2026-09-14.json + docs/snapshots/archmap-card-2026-09-14.json",
      "as_of": "2026-09-14",
      "check": {
        "cmd": "python3 -c 'import json, pathlib\ng = json.loads(pathlib.Path(\"docs/snapshots/codeblast-tabby-arch-2026-09-14.json\").read_text(encoding=\"utf-8\"))\ncard = json.loads(pathlib.Path(\"docs/snapshots/archmap-card-2026-09-14.json\").read_text(encoding=\"utf-8\"))\npkgs = len(g[\"modules\"])\nedges = sum(1 for e in g[\"mod_edges\"] if e[\"src\"] != e[\"dst\"])\nlegend = \"16 packages\" in card[\"legend\"] and \"32 import edges\" in card[\"legend\"]\nexpected = sorted((m[\"name\"].replace(\"tabby-\", \"\"), m[\"files\"], sum(e[\"w\"] for e in g[\"mod_edges\"] if e[\"dst\"] == m[\"name\"])) for m in g[\"modules\"])\ndrawn = sorted((n[\"label\"], n[\"files\"], n[\"fan_in\"]) for n in card[\"nodes\"][\"counted\"])\nmatch = expected == drawn and card[\"subtitle\"].endswith(g[\"generated\"].split()[0])\nif not (pkgs == 16 and edges == 32 and legend and match):\n    print(\"modules=\" + str(pkgs) + \" import-edges=\" + str(edges) + \" legend=\" + str(legend) + \" per-node-match=\" + str(match))\n    raise SystemExit(1)\nprint(\"tabby graph snapshot: \" + str(pkgs) + \" packages, \" + str(edges) + \" import edges, per-node files/fan-in match=\" + str(match) + \" | deployed card legend agrees=\" + str(legend))'",
        "expect": {
          "equals": "tabby graph snapshot: 16 packages, 32 import edges, per-node files/fan-in match=True | deployed card legend agrees=True"
        },
        "timeout": 60
      }
    },
    {
      "id": "archmap-star-count-is-live",
      "claim": "The archmap legend's star count is a live count of Eugeny/tabby taken when the card is rendered - no pinned figure - and the card omits the segment when no count is supplied. The card deployed on the output branch was re-rendered after the 2026-09-12 fix: on 2026-09-14 it reads ~74k*, the rounded count the GitHub API returned that day, with the pre-fix hardcoded 60k* literal gone.",
      "value": "live star count at render time (unpinned; the deployed card of 2026-09-14 reads ~74k*)",
      "metric": "the committed snapshots docs/snapshots/archmap-card-2026-09-14.json (the output-branch legend) and docs/snapshots/tabby-stars-2026-09-14.json (api.github.com/repos/Eugeny/tabby) versus gh api repos/Eugeny/tabby --jq .stargazers_count in .github/workflows/cards.yml, read by the generator as process.env.TABBY_STARS",
      "method": "The figure is a network call at render time and moves with the upstream project's traffic, so it is captured rather than pinned: the two committed snapshots record what the API said and what the deployed card drew on the same day, and the check asserts the card's rounded token equals the API count from that capture. Freshness is not checked - both drift upstream, and a card left stale by a failed run would not be caught here; the mechanism that keeps the figure measured (env read, unset-guard, live query) is machine-checked by star-count-not-hardcoded. History the prose had to correct: when this claim was filed on 2026-09-13 the deployed card still carried the pre-fix 60k* literal; cards.yml has re-rendered it since, so the present-tense 'still shows 60k*' is no longer true.",
      "repro": "python3 -c 'import json, pathlib, re\ncard = json.loads(pathlib.Path(\"docs/snapshots/archmap-card-2026-09-14.json\").read_text(encoding=\"utf-8\"))\napi = json.loads(pathlib.Path(\"docs/snapshots/tabby-stars-2026-09-14.json\").read_text(encoding=\"utf-8\"))\ntoken = \"(~\" + str(round(api[\"stargazers_count\"] / 1000)) + \"k\\u2605)\"\nm = re.search(r\"\\(~(\\d+)k\\u2605\\)\", card[\"legend\"])\nagrees = m is not None and m.group(1) == str(round(api[\"stargazers_count\"] / 1000))\nif not agrees:\n    print(\"legend=\" + card[\"legend\"] + \" api-stars=\" + str(api[\"stargazers_count\"]) + \" expected=\" + token)\n    raise SystemExit(1)\nprint(\"deployed archmap legend carries \" + token + \" = round(\" + str(api[\"stargazers_count\"]) + \"/1000) from the API snapshot of \" + api[\"fetched\"])'",
      "evidence": "docs/snapshots/archmap-card-2026-09-14.json + docs/snapshots/tabby-stars-2026-09-14.json + .github/workflows/cards.yml",
      "as_of": "2026-09-14",
      "check": {
        "cmd": "python3 -c 'import json, pathlib, re\ncard = json.loads(pathlib.Path(\"docs/snapshots/archmap-card-2026-09-14.json\").read_text(encoding=\"utf-8\"))\napi = json.loads(pathlib.Path(\"docs/snapshots/tabby-stars-2026-09-14.json\").read_text(encoding=\"utf-8\"))\ntoken = \"(~\" + str(round(api[\"stargazers_count\"] / 1000)) + \"k\\u2605)\"\nm = re.search(r\"\\(~(\\d+)k\\u2605\\)\", card[\"legend\"])\nagrees = m is not None and m.group(1) == str(round(api[\"stargazers_count\"] / 1000))\nif not agrees:\n    print(\"legend=\" + card[\"legend\"] + \" api-stars=\" + str(api[\"stargazers_count\"]) + \" expected=\" + token)\n    raise SystemExit(1)\nprint(\"deployed archmap legend carries \" + token + \" = round(\" + str(api[\"stargazers_count\"]) + \"/1000) from the API snapshot of \" + api[\"fetched\"])'",
        "expect": {
          "equals": "deployed archmap legend carries (~74k★) = round(74463/1000) from the API snapshot of 2026-09-14"
        },
        "timeout": 60
      }
    },
    {
      "id": "recall-card-figures",
      "claim": "The published recall card shows codeblast's newest committed mutation run - as of filing the 2026-09-07 graphql-tools n=10 batch: 100% recall, 10/10 mutants, precision 0.33 across all channels and 0.92 on the call channel. It is a different batch from the tRPC n=30 run the README's codeblast card quotes (28/28, 2026-08-28).",
      "value": "2026-09-07 graphql-tools n=10: 10/10 recall, 0.33 / 0.92 precision",
      "metric": "the committed snapshot docs/snapshots/recall-card-2026-09-14.json - the output-branch card's printed figures, the scored rows of codeblast's newest dated batch, and the list of batches committed in codeblast/eval - versus the ring and precision bars the card draws",
      "method": "render-cards.mjs sorts codeblast/eval for mutation-<date>*.json and draws the last one, so the ring tracks whichever batch landed last rather than the batch the README's codeblast card quotes. The check recomputes recall and both precision means from the committed rows, confirms the batch is the newest in the committed eval listing and is not the tRPC n=30 run the prose quotes, and requires the card's printed 100% / 10/10 / 0.33 / 0.92 to match. Point-in-time capture (2026-09-14): a new batch landing in codeblast changes the card without this repository changing and is invisible here until the snapshot is re-fetched, so freshness is not checked.",
      "repro": "python3 -c 'import json, pathlib\ns = json.loads(pathlib.Path(\"docs/snapshots/recall-card-2026-09-14.json\").read_text(encoding=\"utf-8\"))\nrows = [r for r in s[\"mutation_run\"][\"rows\"] if r[\"scored\"]]\nhits = sum(1 for r in rows if r[\"recall_hit\"])\nprec = sum(r[\"precision\"] for r in rows) / len(rows)\ncall = [r for r in rows if isinstance(r[\"precision_call\"], (int, float)) and r[\"precision_call\"] > 0]\nprec_call = sum(r[\"precision_call\"] for r in call) / len(call)\nnewest = sorted(s[\"eval_listing\"][\"mutation_files\"])[-1]\ncard = s[\"card\"]\nok = (newest == s[\"mutation_run\"][\"file\"] and \"graphql-tools\" in newest and \"trpc\" not in newest and len(rows) == 10 and hits == 10 and format(prec, \".2f\") == card[\"precision_all\"] and format(prec_call, \".2f\") == card[\"precision_call\"] and card[\"mutants\"] == \"10/10 mutants recalled\" and card[\"recall_pct\"] == \"100%\" and \"2026-09-07\" in card[\"subtitle\"])\nif not ok:\n    print(\"newest=\" + newest + \" rows=\" + str(len(rows)) + \" hits=\" + str(hits) + \" prec=\" + format(prec, \".2f\") + \" callprec=\" + format(prec_call, \".2f\") + \" card=\" + json.dumps(card))\n    raise SystemExit(1)\nprint(\"recall card snapshot: newest batch \" + newest + \" -> \" + str(hits) + \"/\" + str(len(rows)) + \" recalled | precision \" + format(prec, \".2f\") + \" all channels, \" + format(prec_call, \".2f\") + \" call | card agrees=True\")'",
      "evidence": "docs/snapshots/recall-card-2026-09-14.json",
      "as_of": "2026-09-14",
      "check": {
        "cmd": "python3 -c 'import json, pathlib\ns = json.loads(pathlib.Path(\"docs/snapshots/recall-card-2026-09-14.json\").read_text(encoding=\"utf-8\"))\nrows = [r for r in s[\"mutation_run\"][\"rows\"] if r[\"scored\"]]\nhits = sum(1 for r in rows if r[\"recall_hit\"])\nprec = sum(r[\"precision\"] for r in rows) / len(rows)\ncall = [r for r in rows if isinstance(r[\"precision_call\"], (int, float)) and r[\"precision_call\"] > 0]\nprec_call = sum(r[\"precision_call\"] for r in call) / len(call)\nnewest = sorted(s[\"eval_listing\"][\"mutation_files\"])[-1]\ncard = s[\"card\"]\nok = (newest == s[\"mutation_run\"][\"file\"] and \"graphql-tools\" in newest and \"trpc\" not in newest and len(rows) == 10 and hits == 10 and format(prec, \".2f\") == card[\"precision_all\"] and format(prec_call, \".2f\") == card[\"precision_call\"] and card[\"mutants\"] == \"10/10 mutants recalled\" and card[\"recall_pct\"] == \"100%\" and \"2026-09-07\" in card[\"subtitle\"])\nif not ok:\n    print(\"newest=\" + newest + \" rows=\" + str(len(rows)) + \" hits=\" + str(hits) + \" prec=\" + format(prec, \".2f\") + \" callprec=\" + format(prec_call, \".2f\") + \" card=\" + json.dumps(card))\n    raise SystemExit(1)\nprint(\"recall card snapshot: newest batch \" + newest + \" -> \" + str(hits) + \"/\" + str(len(rows)) + \" recalled | precision \" + format(prec, \".2f\") + \" all channels, \" + format(prec_call, \".2f\") + \" call | card agrees=True\")'",
        "expect": {
          "equals": "recall card snapshot: newest batch mutation-2026-09-07-graphql-tools-n10.json -> 10/10 recalled | precision 0.33 all channels, 0.92 call | card agrees=True"
        },
        "timeout": 60
      }
    },
    {
      "id": "ledger-card-figures",
      "claim": "The published ledger card draws four synthetic demo steps - 2s / 1s / 1s / 37s and 1,898 / 2,340 / 2,540 / 2,668 tokens, no cost column - from the claude-code demo fixture, and says so in its footer (claude-code demo session, one row per step, same numbers as the dashboard).",
      "value": "4 steps; 2s/1s/1s/37s; 1,898/2,340/2,540/2,668 tokens",
      "metric": "the committed snapshot docs/snapshots/ledger-card-2026-09-14.json - the output-branch card's columns, its four step rows and its footer - versus AgentXRay's frontend/src/demo/fixtures.json through its public/js/pure.js buildTurnLedger, the same code the dashboard runs",
      "method": "The generator picks the fixture with the highest ledger score and, because the fixtures are single-turn, splits it at assistant-message boundaries into steps; reproducing that needs AgentXRay's fixture and its buildTurnLedger, neither of which is in this repository (cards.yml clones AgentXRay for the step). So the card's own rows are captured dated and checked - four steps, the time and token cells, no cost column, and the footer that labels the session a synthetic claude-code demo. AgentXRay documents the fixtures as synthetic (frontend/demo/sample-logs, scripts/build-demo-fixtures.mjs; its README says the demo holds no real user sessions), which is why the profile describes this card as a demo session. Point-in-time capture (2026-09-14): changing the fixture upstream changes the card without this repository changing; freshness is not checked.",
      "repro": "python3 -c 'import json, pathlib\ns = json.loads(pathlib.Path(\"docs/snapshots/ledger-card-2026-09-14.json\").read_text(encoding=\"utf-8\"))\nrows = s[\"rows\"]\ntimes = [r[\"time\"] for r in rows]\ntokens = [r[\"tokens\"] for r in rows]\nok = (len(rows) == 4 and times == [\"2s\", \"1s\", \"1s\", \"37s\"] and tokens == [\"1,898\", \"2,340\", \"2,540\", \"2,668\"] and s[\"columns\"] == [\"step\", \"time\", \"tokens\"] and \"cost\" not in s[\"columns\"] and \"claude-code demo session\" in s[\"footer\"] and \"one row per step\" in s[\"footer\"])\nif not ok:\n    print(\"rows=\" + str(len(rows)) + \" times=\" + str(times) + \" tokens=\" + str(tokens) + \" columns=\" + str(s[\"columns\"]) + \" footer=\" + s[\"footer\"])\n    raise SystemExit(1)\nprint(\"ledger card snapshot: \" + str(len(rows)) + \" steps | \" + \"/\".join(times) + \" | \" + \"/\".join(tokens) + \" tokens | cost column=\" + str(\"cost\" in s[\"columns\"]) + \" | synthetic claude-code demo footer present\")'",
      "evidence": "docs/snapshots/ledger-card-2026-09-14.json",
      "as_of": "2026-09-14",
      "check": {
        "cmd": "python3 -c 'import json, pathlib\ns = json.loads(pathlib.Path(\"docs/snapshots/ledger-card-2026-09-14.json\").read_text(encoding=\"utf-8\"))\nrows = s[\"rows\"]\ntimes = [r[\"time\"] for r in rows]\ntokens = [r[\"tokens\"] for r in rows]\nok = (len(rows) == 4 and times == [\"2s\", \"1s\", \"1s\", \"37s\"] and tokens == [\"1,898\", \"2,340\", \"2,540\", \"2,668\"] and s[\"columns\"] == [\"step\", \"time\", \"tokens\"] and \"cost\" not in s[\"columns\"] and \"claude-code demo session\" in s[\"footer\"] and \"one row per step\" in s[\"footer\"])\nif not ok:\n    print(\"rows=\" + str(len(rows)) + \" times=\" + str(times) + \" tokens=\" + str(tokens) + \" columns=\" + str(s[\"columns\"]) + \" footer=\" + s[\"footer\"])\n    raise SystemExit(1)\nprint(\"ledger card snapshot: \" + str(len(rows)) + \" steps | \" + \"/\".join(times) + \" | \" + \"/\".join(tokens) + \" tokens | cost column=\" + str(\"cost\" in s[\"columns\"]) + \" | synthetic claude-code demo footer present\")'",
        "expect": {
          "equals": "ledger card snapshot: 4 steps | 2s/1s/1s/37s | 1,898/2,340/2,540/2,668 tokens | cost column=False | synthetic claude-code demo footer present"
        },
        "timeout": 60
      }
    },
    {
      "id": "waka-figures",
      "claim": "The waka block publishes the account's WakaTime statistics: Code Time 2,701 hrs 3 mins, the commit-time split (Morning 1,860 / Daytime 1,380 / Evening 275 / Night 12), the weekly language, editor, project and OS tables, the time zone (Asia/Shanghai), and the repo counts by language (Python 14, JavaScript 10, TypeScript 9, HTML 4, SCSS 1).",
      "value": "2,701 hrs 3 mins; 1,860/1,380/275/12 commits; 14/10/9/4/1 repos",
      "metric": "the WakaTime API as read by the anmol098/waka-readme-stats action in .github/workflows/wakatime.yml",
      "method": "Every figure in the block is an account statistic: the action queries the API with a repository secret and rewrites the section between its markers. Only the block's clock is checkable from this repository (waka-block-is-generated checks the markers, the stamp format and the cron); the statistics themselves exist behind the API.",
      "repro": "curl -s -H \"Authorization: Basic $(printf %s <WAKATIME_API_KEY> | base64)\" https://wakatime.com/api/v1/users/current/stats/last_7_days",
      "evidence": "https://wakatime.com/@alloevil",
      "as_of": "2026-09-13",
      "check": {
        "manual": "the numbers are fetched from the WakaTime API by wakatime.yml with the WAKATIME_API_KEY secret (anmol098/waka-readme-stats querying the user's stats endpoint), and nothing committed holds them: the API needs the network and the key, and the figures move with the author's editor usage rather than with this repository. The committed block cannot stand in for the source - the action rewrites it on its daily cron, and the block committed 2026-09-13 01:38 UTC already reads 2,705 hrs 30 mins (1,962/1,410/284/16 commits; 15/11/9/4/1 repos), one refresh on from the value above. Re-checking the claim means fetching the API response; that response is the missing artifact."
      }
    },
    {
      "id": "projects-index-count",
      "claim": "The featured-projects section says the index it links to covers 16 published projects so far.",
      "value": "16 projects",
      "metric": "the committed snapshot docs/snapshots/alloevil-projects-2026-09-14.json (the project headings on alloevil.github.io/projects) versus the README's '16 so far' sentence",
      "method": "The count is rendered by the projects site in another repository, so a dated capture of that page is committed here and counted; the check also requires the README to keep wording it as a snapshot, because the account has more public repositories than the index lists - proxy-evolution and deepseek-v41-architecture-explorer among the missing ones, which is what the 2026-09-12 audit found behind the previous wording 'every project'. Point-in-time capture (2026-09-14): the index gains entries from another repository, so the count drifts upstream and freshness is not checked.",
      "repro": "python3 -c 'import json, pathlib\ns = json.loads(pathlib.Path(\"docs/snapshots/alloevil-projects-2026-09-14.json\").read_text(encoding=\"utf-8\"))\nn = len(s[\"projects\"])\nreadme = pathlib.Path(\"README.md\").read_text(encoding=\"utf-8\")\nprose = \"(16 so far)\" in readme and \"(https://alloevil.github.io/projects/)\" in readme\nif not (n == 16 and prose):\n    print(\"projects=\" + str(n) + \" README-matches=\" + str(prose))\n    raise SystemExit(1)\nprint(\"projects index snapshot: \" + str(n) + \" project headings | README says 16 so far=\" + str(prose))'",
      "evidence": "docs/snapshots/alloevil-projects-2026-09-14.json + README.md",
      "as_of": "2026-09-14",
      "check": {
        "cmd": "python3 -c 'import json, pathlib\ns = json.loads(pathlib.Path(\"docs/snapshots/alloevil-projects-2026-09-14.json\").read_text(encoding=\"utf-8\"))\nn = len(s[\"projects\"])\nreadme = pathlib.Path(\"README.md\").read_text(encoding=\"utf-8\")\nprose = \"(16 so far)\" in readme and \"(https://alloevil.github.io/projects/)\" in readme\nif not (n == 16 and prose):\n    print(\"projects=\" + str(n) + \" README-matches=\" + str(prose))\n    raise SystemExit(1)\nprint(\"projects index snapshot: \" + str(n) + \" project headings | README says 16 so far=\" + str(prose))'",
        "expect": {
          "equals": "projects index snapshot: 16 project headings | README says 16 so far=True"
        },
        "timeout": 60
      }
    },
    {
      "id": "reading-feed-count",
      "claim": "The Recently Reading list publishes the five newest items of the baoyu.io feed.",
      "value": "5 feed items",
      "metric": "the items between the BLOG-POST-LIST markers in README.md and the feed_list the blog-post-workflow action is given in .github/workflows/blog-post-workflow.yml",
      "method": "blog-post-workflow.yml pulls https://baoyu.io/feed.xml on a two-hourly cron and rewrites everything between its markers, so the list is committed - but as a cache of a live feed. The check counts the injected items (5, the action's keep-count) and requires every one to link into baoyu.io, which is the feed the workflow is configured to pull. It deliberately does not compare the entries against a snapshot of the feed, because the next run would make that fail for a reason that is not an error: the entries rotate upstream, and only the published count and the feed binding are checked here.",
      "repro": "python3 -c 'import re, pathlib\nreadme = pathlib.Path(\"README.md\").read_text(encoding=\"utf-8\")\nblock = re.search(r\"BLOG-POST-LIST:START -->(.*?)<!-- BLOG-POST-LIST:END\", readme, re.S).group(1)\nitems = [line for line in block.splitlines() if line.startswith(\"- [\")]\nworkflow = pathlib.Path(\".github/workflows/blog-post-workflow.yml\").read_text(encoding=\"utf-8\")\nfeed = \"https://baoyu.io/feed.xml\" in workflow\nlinked = all(re.search(r\"^- \\[.+\\]\\(https://baoyu\\.io/\", line) for line in items)\nif not (len(items) == 5 and feed and linked):\n    print(\"items=\" + str(len(items)) + \" feed=\" + str(feed) + \" all-baoyu-links=\" + str(linked))\n    raise SystemExit(1)\nprint(\"Recently Reading block: \" + str(len(items)) + \" injected items, all linking baoyu.io | workflow feed=\" + str(feed))'",
      "evidence": "README.md + .github/workflows/blog-post-workflow.yml",
      "as_of": "2026-09-14",
      "check": {
        "cmd": "python3 -c 'import re, pathlib\nreadme = pathlib.Path(\"README.md\").read_text(encoding=\"utf-8\")\nblock = re.search(r\"BLOG-POST-LIST:START -->(.*?)<!-- BLOG-POST-LIST:END\", readme, re.S).group(1)\nitems = [line for line in block.splitlines() if line.startswith(\"- [\")]\nworkflow = pathlib.Path(\".github/workflows/blog-post-workflow.yml\").read_text(encoding=\"utf-8\")\nfeed = \"https://baoyu.io/feed.xml\" in workflow\nlinked = all(re.search(r\"^- \\[.+\\]\\(https://baoyu\\.io/\", line) for line in items)\nif not (len(items) == 5 and feed and linked):\n    print(\"items=\" + str(len(items)) + \" feed=\" + str(feed) + \" all-baoyu-links=\" + str(linked))\n    raise SystemExit(1)\nprint(\"Recently Reading block: \" + str(len(items)) + \" injected items, all linking baoyu.io | workflow feed=\" + str(feed))'",
        "expect": {
          "equals": "Recently Reading block: 5 injected items, all linking baoyu.io | workflow feed=True"
        },
        "timeout": 60
      }
    },
    {
      "id": "profile-views-badge",
      "claim": "The profile-views badge publishes a live view tally served by komarev.com for the alloevil profile.",
      "value": "live counter (third-party)",
      "metric": "the image the komarev.com/ghpvc badge URL returns",
      "method": "The badge is an <img> pointing at a third-party counter that increments on every profile view, so its value is neither committed nor reproducible - it is by construction different at every read. The badge's presence is part of the README's first screen; its number belongs to that service.",
      "repro": "curl -sI 'https://komarev.com/ghpvc/?username=alloevil&style=flat-square&color=blue' | head -1",
      "evidence": "https://komarev.com/ghpvc/?username=alloevil",
      "as_of": "2026-09-13",
      "check": {
        "manual": "the tally is served per request by https://komarev.com/ghpvc/?username=alloevil and increments on every view of the profile page: the number is different at every read, nothing about it is committed, and no offline command can reproduce a counter that only the third-party service holds. A snapshot would record one read, not the counter, so the badge's presence is what the README can publish."
      }
    },
    {
      "id": "snake-contribution-grid",
      "claim": "The snake picture publishes the account's contribution graph: every square in it is one day of GitHub contribution history, re-rendered every two hours by .github/workflows/main.yml.",
      "value": "live contribution grid (rendered)",
      "metric": "the github_user_name input of the Platane/snk step in main.yml against the account's contribution data",
      "method": "The grid is GitHub's own contribution data, drawn on the runner by Platane/snk into two SVGs (light and dark) that are pushed to the output branch; the profiles README displays them by URL. The colours and layout are the action's, the days are the platform's, and nothing in this repository holds the counts.",
      "repro": "gh api graphql -f query='{user(login:\"alloevil\"){contributionsCollection{contributionCalendar{totalContributions}}}}'",
      "evidence": "https://github.com/alloevil/alloevil/actions/workflows/main.yml",
      "as_of": "2026-09-13",
      "check": {
        "manual": "the grid is GitHub's own contribution data, drawn on the runner by Platane/snk (main.yml) from the account's contributionsCollection and pushed to the output branch; the per-day counts exist only behind that API, fetched with the workflow token, and nothing in this repository holds them. The picture changes with every commit, so a snapshot of the SVG would pin one day of a graph the README displays live; what this repository can check offline - the account the action is given and the two published colour variants - is checked by snake-both-variants-published."
      }
    },
    {
      "id": "site-pages-resolve",
      "claim": "Every root-relative href or src in the site's four pages resolves to a file in the repository - or to a directory holding an index.html - so no published page links to something the deploy would not serve.",
      "value": "4 pages, 0 missing references",
      "metric": "the root-relative href/src values in index.html, 404.html, projects/index.html and blog/index.html against the files on disk",
      "method": "The site is static, so a renamed asset is a link that 404s in production and keeps working in the editor. scripts/build-site.mjs runs the same check over the staged copy and refuses to build, which fails the deploy too; this claim is the version that runs on every push without node, and it is what makes the README's file table trustworthy.",
      "repro": "python3 -c 'import pathlib, re\npages = [\"index.html\", \"404.html\", \"projects/index.html\", \"blog/index.html\"]\nrefs = []\nmissing = []\nfor page in pages:\n    html = pathlib.Path(page).read_text(encoding=\"utf-8\")\n    for raw in re.findall(r\"\\b(?:href|src)=\\\"([^\\\"]+)\\\"\", html):\n        ref = raw.split(\"#\")[0].split(\"?\")[0]\n        if not ref.startswith(\"/\") or ref.startswith(\"//\") or ref == \"/\":\n            continue\n        refs.append((page, ref))\n        target = pathlib.Path(ref.lstrip(\"/\"))\n        if not (target.is_file() or (target / \"index.html\").is_file()):\n            missing.append(page + \" -> \" + ref)\nif missing or not refs:\n    print(\"checked=\" + str(len(refs)) + \" missing=\" + str(missing))\n    raise SystemExit(1)\nprint(str(len(pages)) + \" pages carry \" + str(len(refs)) + \" root-relative references, 0 missing: \" + \" \".join(sorted(set(r[1] for r in refs))))'",
      "evidence": "index.html + 404.html + projects/index.html + blog/index.html",
      "as_of": "2026-09-15",
      "check": {
        "cmd": "python3 -c 'import pathlib, re\npages = [\"index.html\", \"404.html\", \"projects/index.html\", \"blog/index.html\"]\nrefs = []\nmissing = []\nfor page in pages:\n    html = pathlib.Path(page).read_text(encoding=\"utf-8\")\n    for raw in re.findall(r\"\\b(?:href|src)=\\\"([^\\\"]+)\\\"\", html):\n        ref = raw.split(\"#\")[0].split(\"?\")[0]\n        if not ref.startswith(\"/\") or ref.startswith(\"//\") or ref == \"/\":\n            continue\n        refs.append((page, ref))\n        target = pathlib.Path(ref.lstrip(\"/\"))\n        if not (target.is_file() or (target / \"index.html\").is_file()):\n            missing.append(page + \" -> \" + ref)\nif missing or not refs:\n    print(\"checked=\" + str(len(refs)) + \" missing=\" + str(missing))\n    raise SystemExit(1)\nprint(str(len(pages)) + \" pages carry \" + str(len(refs)) + \" root-relative references, 0 missing: \" + \" \".join(sorted(set(r[1] for r in refs))))'",
        "expect": {
          "equals": "4 pages carry 43 root-relative references, 0 missing: /assets/site/favicon.svg /assets/site/theme.js /blog/ /blog/posts.json /claims.json /projects/ /projects/projects.json /script.js /styles.css"
        },
        "timeout": 60
      }
    },
    {
      "id": "site-projects-match-the-captured-index",
      "claim": "The site's project index is the index's own data: projects/projects.json holds the same sixteen entries, in the same order, as the committed capture of alloevil.github.io/llms.txt, every links.github is github.com/alloevil/<name>, and every site link in the file appears in the capture.",
      "value": "16 entries, same order, 0 unknown links",
      "metric": "the project headings in docs/snapshots/alloevil-projects-llms-2026-09-15.txt versus the entries in projects/projects.json",
      "method": "The homepage's featured grid and the whole projects page render from this one file, so the failure worth guarding is drift: an entry added to the project index upstream, or a link edited here, would leave the site describing a list that no longer exists. The three entries whose index link points at their own site instead of a repository (agent-changelog, github-discovery, foodmap) get their repository URL derived from the name, and the check pins that derivation, so a typo fails here rather than on a click.",
      "repro": "python3 -c 'import json, pathlib, re\ncapture = pathlib.Path(\"docs/snapshots/alloevil-projects-llms-2026-09-15.txt\").read_text(encoding=\"utf-8\")\nnames = []\ngroup = False\nfor line in capture.splitlines():\n    if line.startswith(\"## \"):\n        group = True\n        continue\n    m = re.match(r\"^- \\[([^\\]]+)\\]\\(\\S+\\): \", line)\n    if m and group and m.group(1) != \"llms-full.txt\":\n        names.append(m.group(1))\ndoc = json.loads(pathlib.Path(\"projects/projects.json\").read_text(encoding=\"utf-8\"))\nsite = [p[\"name\"] for p in doc[\"projects\"]]\nbad_repo = [p[\"name\"] for p in doc[\"projects\"] if p[\"links\"][\"github\"] != \"https://github.com/alloevil/\" + p[\"name\"]]\ncaptured = set(re.findall(r\"https://alloevil\\.github\\.io/[A-Za-z0-9._-]+/\", capture))\nsite_urls = [p[\"links\"][\"site\"] for p in doc[\"projects\"] if \"site\" in p[\"links\"]]\nunknown = [u for u in site_urls if u not in captured]\nif not (len(names) == 16 and names == site and not bad_repo and not unknown):\n    print(\"capture=\" + str(len(names)) + \" json=\" + str(len(site)) + \" same-order=\" + str(names == site) + \" unknown-repos=\" + str(bad_repo) + \" unknown-sites=\" + str(unknown))\n    raise SystemExit(1)\nprint(\"captured index: \" + str(len(names)) + \" entries, identical to projects/projects.json (\" + str(len(site)) + \") in the same order; every links.github is github.com/alloevil/<name>; all \" + str(len(site_urls)) + \" site links appear in the capture\")'",
      "evidence": "docs/snapshots/alloevil-projects-llms-2026-09-15.txt + projects/projects.json",
      "as_of": "2026-09-15",
      "check": {
        "cmd": "python3 -c 'import json, pathlib, re\ncapture = pathlib.Path(\"docs/snapshots/alloevil-projects-llms-2026-09-15.txt\").read_text(encoding=\"utf-8\")\nnames = []\ngroup = False\nfor line in capture.splitlines():\n    if line.startswith(\"## \"):\n        group = True\n        continue\n    m = re.match(r\"^- \\[([^\\]]+)\\]\\(\\S+\\): \", line)\n    if m and group and m.group(1) != \"llms-full.txt\":\n        names.append(m.group(1))\ndoc = json.loads(pathlib.Path(\"projects/projects.json\").read_text(encoding=\"utf-8\"))\nsite = [p[\"name\"] for p in doc[\"projects\"]]\nbad_repo = [p[\"name\"] for p in doc[\"projects\"] if p[\"links\"][\"github\"] != \"https://github.com/alloevil/\" + p[\"name\"]]\ncaptured = set(re.findall(r\"https://alloevil\\.github\\.io/[A-Za-z0-9._-]+/\", capture))\nsite_urls = [p[\"links\"][\"site\"] for p in doc[\"projects\"] if \"site\" in p[\"links\"]]\nunknown = [u for u in site_urls if u not in captured]\nif not (len(names) == 16 and names == site and not bad_repo and not unknown):\n    print(\"capture=\" + str(len(names)) + \" json=\" + str(len(site)) + \" same-order=\" + str(names == site) + \" unknown-repos=\" + str(bad_repo) + \" unknown-sites=\" + str(unknown))\n    raise SystemExit(1)\nprint(\"captured index: \" + str(len(names)) + \" entries, identical to projects/projects.json (\" + str(len(site)) + \") in the same order; every links.github is github.com/alloevil/<name>; all \" + str(len(site_urls)) + \" site links appear in the capture\")'",
        "expect": {
          "equals": "captured index: 16 entries, identical to projects/projects.json (16) in the same order; every links.github is github.com/alloevil/<name>; all 12 site links appear in the capture"
        },
        "timeout": 60
      }
    },
    {
      "id": "site-featured-matches-readme",
      "claim": "Six projects are flagged featured in projects/projects.json, and they are exactly the six the README's Featured Projects table presents; the homepage renders that grid from the data file rather than from hand-written markup.",
      "value": "6 featured = 6 README cards",
      "metric": "the featured flags in projects/projects.json versus the project headings in README.md's featured table, and the mount in index.html",
      "method": "Two surfaces publish the same shortlist now, which is two chances to disagree: a project promoted in one place and not the other is a reader-visible contradiction, and hand-written cards on the homepage would hide it from this gate. The six are recomputed from the file, so promoting a seventh means editing the flag and the README together.",
      "repro": "python3 -c 'import json, pathlib, re\nreadme = pathlib.Path(\"README.md\").read_text(encoding=\"utf-8\")\ncards = re.findall(r\"### [^\\n]*?([A-Za-z][A-Za-z0-9-]+)\\n>\", readme)\ndoc = json.loads(pathlib.Path(\"projects/projects.json\").read_text(encoding=\"utf-8\"))\nfeatured = [p[\"name\"] for p in doc[\"projects\"] if p[\"featured\"]]\nhome = pathlib.Path(\"index.html\").read_text(encoding=\"utf-8\")\nmount = \"id=\\\"featured\\\"\" in home and \"/projects/projects.json\" in home\nif not (len(featured) == 6 and sorted(cards) == sorted(featured) and mount):\n    print(\"README=\" + str(cards) + \" featured=\" + str(featured) + \" renders-from-json=\" + str(mount))\n    raise SystemExit(1)\nprint(\"the READMEs \" + str(len(cards)) + \" featured cards and projects.json \" + str(len(featured)) + \" featured entries are the same set (\" + \", \".join(featured) + \"); the homepage renders them from the data file=\" + str(mount))'",
      "evidence": "README.md + projects/projects.json + index.html",
      "as_of": "2026-09-15",
      "check": {
        "cmd": "python3 -c 'import json, pathlib, re\nreadme = pathlib.Path(\"README.md\").read_text(encoding=\"utf-8\")\ncards = re.findall(r\"### [^\\n]*?([A-Za-z][A-Za-z0-9-]+)\\n>\", readme)\ndoc = json.loads(pathlib.Path(\"projects/projects.json\").read_text(encoding=\"utf-8\"))\nfeatured = [p[\"name\"] for p in doc[\"projects\"] if p[\"featured\"]]\nhome = pathlib.Path(\"index.html\").read_text(encoding=\"utf-8\")\nmount = \"id=\\\"featured\\\"\" in home and \"/projects/projects.json\" in home\nif not (len(featured) == 6 and sorted(cards) == sorted(featured) and mount):\n    print(\"README=\" + str(cards) + \" featured=\" + str(featured) + \" renders-from-json=\" + str(mount))\n    raise SystemExit(1)\nprint(\"the READMEs \" + str(len(cards)) + \" featured cards and projects.json \" + str(len(featured)) + \" featured entries are the same set (\" + \", \".join(featured) + \"); the homepage renders them from the data file=\" + str(mount))'",
        "expect": {
          "equals": "the READMEs 6 featured cards and projects.json 6 featured entries are the same set (codeblast, paired-eval, AgentXRay, coding-agent-internals, agents-with-receipts, deepresearch-arms-lab); the homepage renders them from the data file=True"
        },
        "timeout": 60
      }
    },
    {
      "id": "site-blog-index-matches-the-sitemap",
      "claim": "The writing index publishes the four posts the blog has actually published: every url in blog/posts.json appears in the committed capture of alloevil.github.io/sitemap.xml, the four dates run newest first, and blog/index.html renders the list from the JSON.",
      "value": "4 posts, all in the sitemap capture",
      "metric": "the urls in blog/posts.json versus docs/snapshots/alloevil-blog-sitemap-2026-09-15.xml, and the mount in blog/index.html",
      "method": "The posts live in another repository, so this is the project index's pattern again: a dated capture here, a bijection against it, freshness deliberately unchecked. What it does check is that no entry can be invented (a url that was never published fails) and that the order the page shows is the order the data supports - blog/index.html sorts by date, so the entries have to be dated.",
      "repro": "python3 -c 'import json, pathlib, re\nlocs = set(re.findall(r\"<loc>([^<]+)</loc>\", pathlib.Path(\"docs/snapshots/alloevil-blog-sitemap-2026-09-15.xml\").read_text(encoding=\"utf-8\")))\nposts = json.loads(pathlib.Path(\"blog/posts.json\").read_text(encoding=\"utf-8\"))[\"posts\"]\nurls = [p[\"url\"] for p in posts]\ndates = [p[\"date\"] for p in posts]\nstray = [u for u in urls if u not in locs]\npage = pathlib.Path(\"blog/index.html\").read_text(encoding=\"utf-8\")\nmount = \"id=\\\"posts\\\"\" in page and \"/blog/posts.json\" in page\nif not (len(urls) == 4 and len(set(urls)) == 4 and not stray and dates == sorted(dates, reverse=True) and mount):\n    print(\"posts=\" + str(len(urls)) + \" stray=\" + str(stray) + \" dated-desc=\" + str(dates == sorted(dates, reverse=True)) + \" renders-from-json=\" + str(mount))\n    raise SystemExit(1)\nprint(\"posts.json lists \" + str(len(urls)) + \" posts, every url appears in the committed sitemap capture, the dates run newest first, and blog/index.html renders from /blog/posts.json\")'",
      "evidence": "blog/posts.json + docs/snapshots/alloevil-blog-sitemap-2026-09-15.xml + blog/index.html",
      "as_of": "2026-09-15",
      "check": {
        "cmd": "python3 -c 'import json, pathlib, re\nlocs = set(re.findall(r\"<loc>([^<]+)</loc>\", pathlib.Path(\"docs/snapshots/alloevil-blog-sitemap-2026-09-15.xml\").read_text(encoding=\"utf-8\")))\nposts = json.loads(pathlib.Path(\"blog/posts.json\").read_text(encoding=\"utf-8\"))[\"posts\"]\nurls = [p[\"url\"] for p in posts]\ndates = [p[\"date\"] for p in posts]\nstray = [u for u in urls if u not in locs]\npage = pathlib.Path(\"blog/index.html\").read_text(encoding=\"utf-8\")\nmount = \"id=\\\"posts\\\"\" in page and \"/blog/posts.json\" in page\nif not (len(urls) == 4 and len(set(urls)) == 4 and not stray and dates == sorted(dates, reverse=True) and mount):\n    print(\"posts=\" + str(len(urls)) + \" stray=\" + str(stray) + \" dated-desc=\" + str(dates == sorted(dates, reverse=True)) + \" renders-from-json=\" + str(mount))\n    raise SystemExit(1)\nprint(\"posts.json lists \" + str(len(urls)) + \" posts, every url appears in the committed sitemap capture, the dates run newest first, and blog/index.html renders from /blog/posts.json\")'",
        "expect": {
          "equals": "posts.json lists 4 posts, every url appears in the committed sitemap capture, the dates run newest first, and blog/index.html renders from /blog/posts.json"
        },
        "timeout": 60
      }
    },
    {
      "id": "site-receipts-are-read-not-copied",
      "claim": "The homepage's receipt panel shows claims.json's own entries rather than a copy: script.js fetches /claims.json, the build stages claims.json, index.html ships empty mounts, and no claim id or receipt row is written into the markup.",
      "value": "2 mounts, 0 claim ids in markup, 0 committed rows",
      "metric": "the receipt mount in index.html and the fetch in script.js versus the claim ids in claims.json and the PUBLISHED list in scripts/build-site.mjs",
      "method": "A copy of the numbers in the homepage markup would be a third place to keep true and the first to go stale - this repository has already published a hand-written figure inside a daily generator, which is the defect claims.json exists for. The panel therefore renders the file CI runs, including its checked/manual split, and this claim fails if anyone freezes those values into the HTML or drops claims.json from the deploy.",
      "repro": "python3 -c 'import json, pathlib\nbuild = pathlib.Path(\"scripts/build-site.mjs\").read_text(encoding=\"utf-8\")\nhome = pathlib.Path(\"index.html\").read_text(encoding=\"utf-8\")\nscript = pathlib.Path(\"script.js\").read_text(encoding=\"utf-8\")\nclaims = json.loads(pathlib.Path(\"claims.json\").read_text(encoding=\"utf-8\"))\nstaged = \"\\\"claims.json\\\"\" in build.split(\"PUBLISHED = [\")[1].split(\"]\")[0]\nfetched = \"getJSON(\\\"/claims.json\\\")\" in script\nmounts = home.count(\"data-receipt\")\nids = [c[\"id\"] for c in claims[\"claims\"] if c[\"id\"] in home]\nrows = home.count(\"receipt__row\")\nif not (staged and fetched and mounts == 2 and not ids and rows == 0):\n    print(\"staged=\" + str(staged) + \" fetched=\" + str(fetched) + \" mounts=\" + str(mounts) + \" claim-ids-in-markup=\" + str(ids) + \" committed-rows=\" + str(rows))\n    raise SystemExit(1)\nprint(\"homepage receipts: claims.json is staged=\" + str(staged) + \", fetched at load=\" + str(fetched) + \", the markup ships \" + str(mounts) + \" empty mounts, claim ids written into the markup=0, receipt rows committed=0\")'",
      "evidence": "index.html + script.js + claims.json + scripts/build-site.mjs",
      "as_of": "2026-09-15",
      "check": {
        "cmd": "python3 -c 'import json, pathlib\nbuild = pathlib.Path(\"scripts/build-site.mjs\").read_text(encoding=\"utf-8\")\nhome = pathlib.Path(\"index.html\").read_text(encoding=\"utf-8\")\nscript = pathlib.Path(\"script.js\").read_text(encoding=\"utf-8\")\nclaims = json.loads(pathlib.Path(\"claims.json\").read_text(encoding=\"utf-8\"))\nstaged = \"\\\"claims.json\\\"\" in build.split(\"PUBLISHED = [\")[1].split(\"]\")[0]\nfetched = \"getJSON(\\\"/claims.json\\\")\" in script\nmounts = home.count(\"data-receipt\")\nids = [c[\"id\"] for c in claims[\"claims\"] if c[\"id\"] in home]\nrows = home.count(\"receipt__row\")\nif not (staged and fetched and mounts == 2 and not ids and rows == 0):\n    print(\"staged=\" + str(staged) + \" fetched=\" + str(fetched) + \" mounts=\" + str(mounts) + \" claim-ids-in-markup=\" + str(ids) + \" committed-rows=\" + str(rows))\n    raise SystemExit(1)\nprint(\"homepage receipts: claims.json is staged=\" + str(staged) + \", fetched at load=\" + str(fetched) + \", the markup ships \" + str(mounts) + \" empty mounts, claim ids written into the markup=0, receipt rows committed=0\")'",
        "expect": {
          "equals": "homepage receipts: claims.json is staged=True, fetched at load=True, the markup ships 2 empty mounts, claim ids written into the markup=0, receipt rows committed=0"
        },
        "timeout": 60
      }
    },
    {
      "id": "site-deploys-the-staged-surface",
      "claim": "The deploy publishes the staged site and nothing else: wrangler.jsonc names the Worker alloevil, serves ./dist with a 404 page and declares no worker script; scripts/build-site.mjs stages the ten published paths with none of the repository's plumbing among them; and package.json plus the README carry the build and deploy commands Cloudflare Workers Builds runs.",
      "value": "name alloevil, assets ./dist, 10 staged paths, 0 plumbing",
      "metric": "wrangler.jsonc + package.json + the PUBLISHED list in scripts/build-site.mjs + the deploy section of README.md",
      "method": "The first draft pointed the asset directory at the repository root and published by subtraction: every new top-level file sat one forgotten ignore pattern from being uploaded, and `wrangler dev` watched its own state directory until it stopped answering requests. Staging publishes by addition - the list in the build script is the published surface - and this claim holds the four files that have to agree (config, manifest, build list, README) to what the Worker actually serves.",
      "repro": "python3 -c 'import json, pathlib, re\ncfg = pathlib.Path(\"wrangler.jsonc\").read_text(encoding=\"utf-8\")\npkg = json.loads(pathlib.Path(\"package.json\").read_text(encoding=\"utf-8\"))\nbuild = pathlib.Path(\"scripts/build-site.mjs\").read_text(encoding=\"utf-8\")\nreadme = pathlib.Path(\"README.md\").read_text(encoding=\"utf-8\")\nname = re.search(r\"\\\"name\\\": \\\"([a-z0-9-]+)\\\"\", cfg).group(1)\ndirectory = re.search(r\"\\\"directory\\\": \\\"([^\\\"]+)\\\"\", cfg).group(1)\nentries = re.findall(r\"\\\"([^\\\"]+)\\\"\", build.split(\"PUBLISHED = [\")[1].split(\"]\")[0])\nscripts = pkg.get(\"scripts\", {})\ndocumented = \"npm run build\" in readme and \"npx wrangler deploy\" in readme\nplumbing = [e for e in entries if e.split(\"/\")[0] in (\"docs\", \"scripts\", \".github\", \"node_modules\") or e in (\"README.md\", \"package.json\", \"package-lock.json\", \"wrangler.jsonc\", \"LICENSE\")]\nok = (name == \"alloevil\" and directory == \"./dist\" and \"404-page\" in cfg and \"\\\"main\\\"\" not in cfg\n      and \"build-site.mjs\" in scripts.get(\"build\", \"\") and \"wrangler deploy\" in scripts.get(\"deploy\", \"\")\n      and len(entries) == 10 and not plumbing and documented)\nif not ok:\n    print(\"name=\" + name + \" assets=\" + directory + \" published=\" + str(entries) + \" plumbing-staged=\" + str(plumbing) + \" documented=\" + str(documented))\n    raise SystemExit(1)\nprint(\"wrangler.jsonc: name=\" + name + \", assets=\" + directory + \", not_found_handling=404-page, no worker script; the build stages \" + str(len(entries)) + \" paths (\" + \", \".join(entries) + \") and none of the repositorys plumbing; the README carries the Cloudflare build and deploy commands\")'",
      "evidence": "wrangler.jsonc + package.json + scripts/build-site.mjs + README.md",
      "as_of": "2026-09-15",
      "check": {
        "cmd": "python3 -c 'import json, pathlib, re\ncfg = pathlib.Path(\"wrangler.jsonc\").read_text(encoding=\"utf-8\")\npkg = json.loads(pathlib.Path(\"package.json\").read_text(encoding=\"utf-8\"))\nbuild = pathlib.Path(\"scripts/build-site.mjs\").read_text(encoding=\"utf-8\")\nreadme = pathlib.Path(\"README.md\").read_text(encoding=\"utf-8\")\nname = re.search(r\"\\\"name\\\": \\\"([a-z0-9-]+)\\\"\", cfg).group(1)\ndirectory = re.search(r\"\\\"directory\\\": \\\"([^\\\"]+)\\\"\", cfg).group(1)\nentries = re.findall(r\"\\\"([^\\\"]+)\\\"\", build.split(\"PUBLISHED = [\")[1].split(\"]\")[0])\nscripts = pkg.get(\"scripts\", {})\ndocumented = \"npm run build\" in readme and \"npx wrangler deploy\" in readme\nplumbing = [e for e in entries if e.split(\"/\")[0] in (\"docs\", \"scripts\", \".github\", \"node_modules\") or e in (\"README.md\", \"package.json\", \"package-lock.json\", \"wrangler.jsonc\", \"LICENSE\")]\nok = (name == \"alloevil\" and directory == \"./dist\" and \"404-page\" in cfg and \"\\\"main\\\"\" not in cfg\n      and \"build-site.mjs\" in scripts.get(\"build\", \"\") and \"wrangler deploy\" in scripts.get(\"deploy\", \"\")\n      and len(entries) == 10 and not plumbing and documented)\nif not ok:\n    print(\"name=\" + name + \" assets=\" + directory + \" published=\" + str(entries) + \" plumbing-staged=\" + str(plumbing) + \" documented=\" + str(documented))\n    raise SystemExit(1)\nprint(\"wrangler.jsonc: name=\" + name + \", assets=\" + directory + \", not_found_handling=404-page, no worker script; the build stages \" + str(len(entries)) + \" paths (\" + \", \".join(entries) + \") and none of the repositorys plumbing; the README carries the Cloudflare build and deploy commands\")'",
        "expect": {
          "equals": "wrangler.jsonc: name=alloevil, assets=./dist, not_found_handling=404-page, no worker script; the build stages 10 paths (index.html, 404.html, styles.css, script.js, claims.json, robots.txt, sitemap.xml, assets/site, projects, blog) and none of the repositorys plumbing; the README carries the Cloudflare build and deploy commands"
        },
        "timeout": 60
      }
    },
    {
      "id": "site-origin-stamped-metadata",
      "claim": "One origin, one edit: site.json holds the address the site answers on, sitemap.xml lists exactly the three public pages at it, robots.txt points at that sitemap, the source pages carry root-relative canonical/og:url/og:image that the build absolutizes, no source page hardcodes the origin, and assets/site/og.png is a 1200x630 PNG matching the og:image dimensions the pages declare.",
      "value": "1 origin, 3 sitemap URLs, 3 stamped pages, og.png 1200x630",
      "metric": "site.json versus sitemap.xml, robots.txt, the head of each public page, and the PNG's own IHDR",
      "method": "These tags exist for readers that never run script.js, so they cannot be filled in by it: the earlier version rewrote canonical and og:url from location.origin at runtime, which also pointed a preview deployment at production. The build writes them instead, and this claim is what keeps the three hand-written files (site.json, sitemap.xml, robots.txt) from drifting apart - moving to a custom domain fails here until all three agree. The og:image is a capture of the hero, and its size is read out of the file rather than trusted.",
      "repro": "python3 -c 'import json, pathlib, re\nsite = json.loads(pathlib.Path(\"site.json\").read_text(encoding=\"utf-8\"))\norigin = site[\"origin\"]\nsitemap = pathlib.Path(\"sitemap.xml\").read_text(encoding=\"utf-8\")\nrobots = pathlib.Path(\"robots.txt\").read_text(encoding=\"utf-8\")\nbuild = pathlib.Path(\"scripts/build-site.mjs\").read_text(encoding=\"utf-8\")\npages = {\"index.html\": \"/\", \"projects/index.html\": \"/projects/\", \"blog/index.html\": \"/blog/\"}\nlocs = re.findall(r\"<loc>([^<]+)</loc>\", sitemap)\nissues = []\nif locs != [origin + p for p in pages.values()]:\n    issues.append(\"sitemap=\" + str(locs))\nif \"Sitemap: \" + origin + \"/sitemap.xml\" not in robots:\n    issues.append(\"robots.txt points elsewhere\")\nfor page, path in pages.items():\n    html = pathlib.Path(page).read_text(encoding=\"utf-8\")\n    for tag, pattern, want in ((\"canonical\", r\"<link rel=\\\"canonical\\\" href=\\\"([^\\\"]+)\\\"\", path),\n                               (\"og:url\", r\"<meta property=\\\"og:url\\\" content=\\\"([^\\\"]+)\\\"\", path),\n                               (\"og:image\", r\"<meta property=\\\"og:image\\\" content=\\\"([^\\\"]+)\\\"\", \"/assets/site/og.png\")):\n        found = re.search(pattern, html)\n        if not found or found.group(1) != want:\n            issues.append(page + \" \" + tag + \"=\" + (found.group(1) if found else \"missing\"))\nsource = \"\".join(pathlib.Path(p).read_text(encoding=\"utf-8\") for p in list(pages) + [\"404.html\", \"styles.css\", \"script.js\"])\nif \"workers.dev\" in source:\n    issues.append(\"the origin is hardcoded in a source page\")\npng = pathlib.Path(\"assets/site/og.png\").read_bytes()\nsize = (int.from_bytes(png[16:20], \"big\"), int.from_bytes(png[20:24], \"big\"))\ndeclared = re.search(r\"og:image:width\\\" content=\\\"(\\d+)\\\"\", pathlib.Path(\"index.html\").read_text(encoding=\"utf-8\"))\nif png[1:4] != b\"PNG\" or size != (1200, 630) or not declared or int(declared.group(1)) != 1200:\n    issues.append(\"og.png=\" + str(size))\nif \"site.json\" not in build or \"og:image\" not in build:\n    issues.append(\"the build does not stamp the metadata\")\nif issues:\n    print(\" | \".join(issues))\n    raise SystemExit(1)\nprint(\"site.json origin \" + origin + \": sitemap.xml lists exactly the \" + str(len(locs)) + \" public pages at it, robots.txt points at its sitemap, all three pages carry root-relative canonical/og:url/og:image that the build absolutizes, no source page hardcodes the origin, and assets/site/og.png is a \" + str(size[0]) + \"x\" + str(size[1]) + \" PNG matching the declared dimensions\")'\n",
      "evidence": "site.json + sitemap.xml + robots.txt + the three public pages + assets/site/og.png",
      "as_of": "2026-09-15",
      "check": {
        "cmd": "python3 -c 'import json, pathlib, re\nsite = json.loads(pathlib.Path(\"site.json\").read_text(encoding=\"utf-8\"))\norigin = site[\"origin\"]\nsitemap = pathlib.Path(\"sitemap.xml\").read_text(encoding=\"utf-8\")\nrobots = pathlib.Path(\"robots.txt\").read_text(encoding=\"utf-8\")\nbuild = pathlib.Path(\"scripts/build-site.mjs\").read_text(encoding=\"utf-8\")\npages = {\"index.html\": \"/\", \"projects/index.html\": \"/projects/\", \"blog/index.html\": \"/blog/\"}\nlocs = re.findall(r\"<loc>([^<]+)</loc>\", sitemap)\nissues = []\nif locs != [origin + p for p in pages.values()]:\n    issues.append(\"sitemap=\" + str(locs))\nif \"Sitemap: \" + origin + \"/sitemap.xml\" not in robots:\n    issues.append(\"robots.txt points elsewhere\")\nfor page, path in pages.items():\n    html = pathlib.Path(page).read_text(encoding=\"utf-8\")\n    for tag, pattern, want in ((\"canonical\", r\"<link rel=\\\"canonical\\\" href=\\\"([^\\\"]+)\\\"\", path),\n                               (\"og:url\", r\"<meta property=\\\"og:url\\\" content=\\\"([^\\\"]+)\\\"\", path),\n                               (\"og:image\", r\"<meta property=\\\"og:image\\\" content=\\\"([^\\\"]+)\\\"\", \"/assets/site/og.png\")):\n        found = re.search(pattern, html)\n        if not found or found.group(1) != want:\n            issues.append(page + \" \" + tag + \"=\" + (found.group(1) if found else \"missing\"))\nsource = \"\".join(pathlib.Path(p).read_text(encoding=\"utf-8\") for p in list(pages) + [\"404.html\", \"styles.css\", \"script.js\"])\nif \"workers.dev\" in source:\n    issues.append(\"the origin is hardcoded in a source page\")\npng = pathlib.Path(\"assets/site/og.png\").read_bytes()\nsize = (int.from_bytes(png[16:20], \"big\"), int.from_bytes(png[20:24], \"big\"))\ndeclared = re.search(r\"og:image:width\\\" content=\\\"(\\d+)\\\"\", pathlib.Path(\"index.html\").read_text(encoding=\"utf-8\"))\nif png[1:4] != b\"PNG\" or size != (1200, 630) or not declared or int(declared.group(1)) != 1200:\n    issues.append(\"og.png=\" + str(size))\nif \"site.json\" not in build or \"og:image\" not in build:\n    issues.append(\"the build does not stamp the metadata\")\nif issues:\n    print(\" | \".join(issues))\n    raise SystemExit(1)\nprint(\"site.json origin \" + origin + \": sitemap.xml lists exactly the \" + str(len(locs)) + \" public pages at it, robots.txt points at its sitemap, all three pages carry root-relative canonical/og:url/og:image that the build absolutizes, no source page hardcodes the origin, and assets/site/og.png is a \" + str(size[0]) + \"x\" + str(size[1]) + \" PNG matching the declared dimensions\")'\n",
        "expect": {
          "equals": "site.json origin https://alloevil.alloevil1.workers.dev: sitemap.xml lists exactly the 3 public pages at it, robots.txt points at its sitemap, all three pages carry root-relative canonical/og:url/og:image that the build absolutizes, no source page hardcodes the origin, and assets/site/og.png is a 1200x630 PNG matching the declared dimensions"
        },
        "timeout": 60
      }
    }
  ]
}
