{
 "note": "Written by build/negatives.py: for each check, a falsification applied to a copy of the tree and the build's answer. A claim is held only while a current, caught falsification stands behind every check it cites.",
 "build": {
  "meta": {
   "tool": "build/negatives.py",
   "date": "2026-09-27",
   "commit": "aab42be",
   "code": "4ed2d04f8eaa",
   "code_files": [
    "build/build_site.py",
    "build/claims.py",
    "build/atlas.py",
    "build/invariance.py",
    "build/ledger.py",
    "build/marks.py",
    "build/fingerprint.py",
    "build/negatives.py",
    ".github/workflows/build.yml"
   ]
  },
  "cases": [
   {
    "id": "41-lineage-missing-ancestor",
    "check": "41",
    "what": "the tax-base lineage loses the filed right-of-use ancestor",
    "exit": 1,
    "fired": [
     "15",
     "41"
    ],
    "caught": true,
    "line": "check 41: canadian-dcf-cca.html: a filed input has lost its provenance record",
    "seconds": 81.2
   },
   {
    "id": "41-lineage-wrong-value",
    "check": "41",
    "what": "a drawn lineage value disagrees with its recorded input or output",
    "exit": 1,
    "fired": [
     "15",
     "41"
    ],
    "caught": true,
    "line": "check 41: canadian-dcf-cca.html: drawn value or source path disagrees with the recorded difference",
    "seconds": 81.6
   },
   {
    "id": "41-lineage-unrecorded-edge",
    "check": "41",
    "what": "the tree draws a relation the tax-base reconciliation never records",
    "exit": 1,
    "fired": [
     "41"
    ],
    "caught": true,
    "line": "check 41: canadian-dcf-cca.html: a lineage edge does not reach the ancestor and output it names",
    "seconds": 80.9
   },
   {
    "id": "41-lineage-unmeasured-fill",
    "check": "41",
    "what": "the lineage draws its values in an unmeasured decorative rule token",
    "exit": 1,
    "fired": [
     "41"
    ],
    "caught": true,
    "line": "check 41: canadian-dcf-cca.html: the lineage omits a required visible, measured mark style",
    "seconds": 80.7
   },
   {
    "id": "40-dossier-invented-citation",
    "check": "40",
    "what": "the piece register prints one more citation chord than its recorded links supply",
    "exit": 1,
    "fired": [
     "40"
    ],
    "caught": true,
    "line": "check 40: afm241-cheat-sheet.html: afm241-cheat-sheet has an incorrect or duplicate dossier-cites",
    "seconds": 81.3
   },
   {
    "id": "40-dossier-unmeasured-text",
    "check": "40",
    "what": "the active register sets metadata in the decorative rule token instead of measured ink",
    "exit": 1,
    "fired": [
     "40"
    ],
    "caught": true,
    "line": "check 40: site.css: unsupported dossier declaration color:var(--rule)",
    "seconds": 80.7
   },
   {
    "id": "40-dossier-duplicate-status",
    "check": "40",
    "what": "a piece register grows a second verification stamp without another recorded fact",
    "exit": 1,
    "fired": [
     "40"
    ],
    "caught": true,
    "line": "check 40: afm241-cheat-sheet.html: afm241-cheat-sheet exceeds the dossier's flat, recorded field budget",
    "seconds": 81.3
   },
   {
    "id": "40-dossier-faded-ink",
    "check": "40",
    "what": "the register fades its measured ink through an unmeasured opacity declaration",
    "exit": 1,
    "fired": [
     "40"
    ],
    "caught": true,
    "line": "check 40: site.css: unsupported dossier declaration opacity:.25",
    "seconds": 81.4
   },
   {
    "id": "40-dossier-uncopied-token",
    "check": "40",
    "what": "a shared register reads an ink token the standalone header does not carry",
    "exit": 1,
    "fired": [
     "40"
    ],
    "caught": true,
    "line": "check 40: site.css: unsupported dossier declaration color:var(--ink)",
    "seconds": 81.3
   },
   {
    "id": "40-dossier-counted-as-prose",
    "check": "40",
    "what": "a converted header loses the existing exclusion that keeps metadata out of measured words",
    "exit": 1,
    "fired": [
     "40"
    ],
    "caught": true,
    "line": "check 40: afm291-ch1-theory-and-analytics.html: converted header metadata lacks the existing chrome-count exclusion",
    "seconds": 83
   },
   {
    "id": "1-canonical-offsite",
    "check": "1",
    "what": "the build writes every canonical address on another site",
    "exit": 1,
    "fired": [
     "1",
     "22"
    ],
    "caught": true,
    "line": "check 1: 404.html: canonical points off-site, https://elsewhere.invalid/404.html",
    "seconds": 82.6
   },
   {
    "id": "2-other-host-named",
    "check": "2",
    "what": "the footer of every generated page names another GitHub Pages host",
    "exit": 1,
    "fired": [
     "2"
    ],
    "caught": true,
    "line": "check 2: 404.html: mentions someone-else.github.io, which is not this site",
    "seconds": 81.5
   },
   {
    "id": "3-dead-link",
    "check": "3",
    "what": "a piece links to a file that does not exist",
    "exit": 1,
    "fired": [
     "3",
     "15"
    ],
    "caught": true,
    "line": "check 3: positive-vs-normative.html: links to no-such-page.html, which does not exist",
    "seconds": 82.7
   },
   {
    "id": "4-icon-missing",
    "check": "4",
    "what": "the site manifest names an icon file that does not exist",
    "exit": 1,
    "fired": [
     "4"
    ],
    "caught": true,
    "line": "check 4: site.webmanifest: names icon site-192-gone.png, which does not exist",
    "seconds": 82.8
   },
   {
    "id": "5-figure-scope-missing",
    "check": "5",
    "what": "a lifted figure loses its colour scope in figures.css",
    "exit": 1,
    "fired": [
     "5"
    ],
    "caught": true,
    "line": "check 5: index.html: shows figure fs-tv1, which has no colour scope in figures.css",
    "seconds": 81.5
   },
   {
    "id": "6-second-h1",
    "check": "6",
    "what": "a converted document gains a second top-level heading in its body",
    "exit": 1,
    "fired": [
     "6",
     "15"
    ],
    "caught": true,
    "line": "check 6: afm291-ch1-theory-and-analytics.html: 2 top-level headings in a document body; all but the first are hidden by the stylesheet",
    "seconds": 82
   },
   {
    "id": "7-head-ended-early",
    "check": "7",
    "what": "the build puts a div inside head, which ends the head before the canonical",
    "exit": 1,
    "fired": [
     "7"
    ],
    "caught": true,
    "line": "check 7: 404.html: </div> inside <head> ends the head early; everything after it is parsed into the body",
    "seconds": 81.7
   },
   {
    "id": "8-atlas-anchor-dead",
    "check": "8",
    "what": "the placement points every mark at an anchor no document carries",
    "exit": 1,
    "fired": [
     "8",
     "32"
    ],
    "caught": true,
    "line": "check 8: atlas.html: 1 mark(s) point at anchors about.html does not carry, first is #author-gone",
    "seconds": 82.4
   },
   {
    "id": "9-listed-file-missing",
    "check": "9",
    "what": "content/pieces.json lists a file that does not exist",
    "exit": 1,
    "fired": [
     "3",
     "9",
     "11a2",
     "13",
     "38"
    ],
    "caught": true,
    "line": "check 9: content/pieces.json: canadian-dcf-cca points at not-there.html, which does not exist",
    "seconds": 81.1
   },
   {
    "id": "10-glyph-outside-subset",
    "check": "10",
    "what": "the build prints a character Inter could render that the self-hosted subset lacks",
    "exit": 1,
    "fired": [
     "10"
    ],
    "caught": true,
    "line": "check 10: font subset: U+03A9 ('Ω') in 404.html renders in the fallback, not Inter; re-subset InterVariable-sub.woff2",
    "seconds": 81.1
   },
   {
    "id": "11-chrome-colour-unknown",
    "check": "11",
    "what": "the chrome the build writes into pieces states a colour the stylesheet does not know",
    "exit": 1,
    "fired": [
     "11"
    ],
    "caught": true,
    "line": "check 11: injected chrome: #123456 is not a colour site.css knows; the chrome palette in build_site.py has drifted from the stylesheet",
    "seconds": 81
   },
   {
    "id": "11a-stray-mark",
    "check": "11a",
    "what": "the Atlas page carries a mark at a position the placement did not produce",
    "exit": 1,
    "fired": [
     "11a",
     "11a2",
     "28"
    ],
    "caught": true,
    "line": "check 11a: atlas.html: 1825 marks and 1825 links read back, 1755 points placed",
    "seconds": 79.8
   },
   {
    "id": "11a2-weight-inflated",
    "check": "11a2",
    "what": "one mark on the Atlas carries a word weight the apportionment did not give it",
    "exit": 1,
    "fired": [
     "11a2"
    ],
    "caught": true,
    "line": "check 11a2: atlas.html: mark weights add to 512,058, the corpus line says 511,988",
    "seconds": 80.7
   },
   {
    "id": "12-corpus-line-off",
    "check": "12",
    "what": "the corpus line's word total is one more than the three origins add to",
    "exit": 1,
    "fired": [
     "11a2",
     "12",
     "26"
    ],
    "caught": true,
    "line": "check 12: origin totals: words add to 511988, the corpus line says 511989",
    "seconds": 81.5
   },
   {
    "id": "13-typed-numeral",
    "check": "13",
    "what": "the build types a numeral into the footer that nothing computed",
    "exit": 1,
    "fired": [
     "13"
    ],
    "caught": true,
    "line": "check 13: 404.html: prints 1,234, which the build did not compute and no piece states",
    "seconds": 81.6
   },
   {
    "id": "14-false-superlative",
    "check": "14",
    "what": "a short essay's blurb calls it the largest essay on the site",
    "exit": 1,
    "fired": [
     "14"
    ],
    "caught": true,
    "line": "check 14: content/pieces.json: heartbeat-budget calls itself the largest essay; the-trillion-dollar-vintage is, at 18,610 words",
    "seconds": 81.6
   },
   {
    "id": "15-result-sentence-added",
    "check": "15",
    "what": "a piece gains a result sentence with a numeral that its record does not hold",
    "exit": 1,
    "fired": [
     "15"
    ],
    "caught": true,
    "line": "check 15: positive-vs-normative.html: numerals gained, not declared in the ledger: 12,344, 12,345",
    "seconds": 81.6
   },
   {
    "id": "16-ledger-class-stale",
    "check": "16",
    "what": "the ledger's class for a piece is not what the files show",
    "exit": 1,
    "fired": [
     "16"
    ],
    "caught": true,
    "line": "check 16: content/ledger.json: flagged-in-hindsight is styling, the files say copy; run build/ledger.py",
    "seconds": 81.3
   },
   {
    "id": "17-built-from-empty",
    "check": "17",
    "what": "a listed piece has no built_from line",
    "exit": 1,
    "fired": [
     "17"
    ],
    "caught": true,
    "line": "check 17: content/pieces.json: flagged-in-hindsight has no built_from line",
    "seconds": 82.5
   },
   {
    "id": "18-font-digest-wrong",
    "check": "18",
    "what": "a self-hosted font file no longer matches the digest its manifest records",
    "exit": 1,
    "fired": [
     "18"
    ],
    "caught": true,
    "line": "check 18: fonts/manifest.json: fonts/bricolagegrotesque-afm291-journal-entries.woff2 does not match its recorded sha256; run the rename",
    "seconds": 81
   },
   {
    "id": "19-heading-skips",
    "check": "19",
    "what": "the footer's headings skip from h2 to h4",
    "exit": 1,
    "fired": [
     "19"
    ],
    "caught": true,
    "line": "check 19: 404.html: a heading skips from h2 to h4",
    "seconds": 80.4
   },
   {
    "id": "20-skip-link-gone",
    "check": "20",
    "what": "the generated pages open without a skip link",
    "exit": 1,
    "fired": [
     "20"
    ],
    "caught": true,
    "line": "check 20: 404.html: has no skip link to #main",
    "seconds": 80.3
   },
   {
    "id": "21-figure-unnamed",
    "check": "21",
    "what": "a lifted figure on the home and research pages loses its accessible name",
    "exit": 1,
    "fired": [
     "21"
    ],
    "caught": true,
    "line": "check 21: index.html: a figure carries no accessible name",
    "seconds": 79.9
   },
   {
    "id": "22-script-from-elsewhere",
    "check": "22",
    "what": "every generated page loads a script from another origin",
    "exit": 1,
    "fired": [
     "22"
    ],
    "caught": true,
    "line": "check 22: 404.html: loads https://cdn.elsewhere.invalid/x.js from another origin",
    "seconds": 79.1
   },
   {
    "id": "23-dash-on-generated-page",
    "check": "23",
    "what": "the footer of every generated page carries an em dash",
    "exit": 1,
    "fired": [
     "23"
    ],
    "caught": true,
    "line": "check 23: 404.html: carries 1 em dash(es) in its prose",
    "seconds": 79.2
   },
   {
    "id": "23-dash-in-piece-prose",
    "check": "23",
    "what": "a listed piece that is not a declared record carries an em dash in its prose",
    "exit": 1,
    "fired": [
     "23"
    ],
    "caught": true,
    "line": "check 23: positive-vs-normative.html: carries 1 em dash(es) in its prose",
    "seconds": 79.4
   },
   {
    "id": "24-idempotence-step-gone",
    "check": "24",
    "what": "the workflow no longer fails the run when a further build rewrites something",
    "exit": 1,
    "fired": [
     "24"
    ],
    "caught": true,
    "line": "check 24: .github/workflows/build.yml: the gate lacks, in order, idempotence",
    "seconds": 79.6
   },
   {
    "id": "24-deploy-ungated",
    "check": "24",
    "what": "the deploy job no longer waits for the build job",
    "exit": 1,
    "fired": [
     "24"
    ],
    "caught": true,
    "line": "check 24: .github/workflows/build.yml: no deploy job needs the build job",
    "seconds": 79.5
   },
   {
    "id": "25-american-spelling",
    "check": "25",
    "what": "the footer of every generated page spells colour the American way",
    "exit": 1,
    "fired": [
     "25"
    ],
    "caught": true,
    "line": "check 25: 404.html: spells color the American way",
    "seconds": 79.2
   },
   {
    "id": "26-number-without-record",
    "check": "26",
    "what": "the footer carries a counted number whose value no record holds",
    "exit": 1,
    "fired": [
     "13",
     "26"
    ],
    "caught": true,
    "line": "check 26: 404.html: figures prints 213, which is no aggregate the build computes for that definition",
    "seconds": 79.4
   },
   {
    "id": "27-channel-unnamed",
    "check": "27",
    "what": "the home sphere declares a channel the Atlas key does not name",
    "exit": 1,
    "fired": [
     "27"
    ],
    "caught": true,
    "line": "check 27: index.html: site.js draws the channel 'halo', which the Atlas key does not name",
    "seconds": 79.6
   },
   {
    "id": "28-placed-by-lattice",
    "check": "28",
    "what": "documents are spread over the sphere by the old even lattice instead of settled by their sections",
    "exit": 1,
    "fired": [
     "28"
    ],
    "caught": true,
    "line": "check 28: atlas.html: afm291 is course work and its disc crosses out of its zone",
    "seconds": 79.1
   },
   {
    "id": "28-marks-off-the-spiral",
    "check": "28",
    "what": "a document's sections leave the spiral: every ring is drawn twice as far out",
    "exit": 1,
    "fired": [
     "28"
    ],
    "caught": true,
    "line": "check 28: atlas.html: a mark of five-shall-paragraphs lies 0.33 rad from its centre, outside its disc of 0.31",
    "seconds": 78.9
   },
   {
    "id": "28-discs-left-overlapping",
    "check": "28",
    "what": "the discs are never settled apart, so documents overlap where their starting heights put them",
    "exit": 1,
    "fired": [
     "28"
    ],
    "caught": true,
    "line": "check 28: atlas.html: afm241-cheat-sheet is course work and its disc crosses out of its zone",
    "seconds": 74
   },
   {
    "id": "28-discs-drawn-too-large",
    "check": "28",
    "what": "every disc is drawn at the whole of its share rather than two thirds of it",
    "exit": 1,
    "fired": [
     "28"
    ],
    "caught": true,
    "line": "check 28: atlas.html: the discs of afm241-cheat-sheet and afm291-workbook overlap",
    "seconds": 79.8
   },
   {
    "id": "29-stale-drawn-as-held",
    "check": "29",
    "what": "the instrument draws a page whose record is stale as held",
    "exit": 1,
    "fired": [
     "29"
    ],
    "caught": true,
    "line": "check 29: controls.html: 404.html under E shows '#', the record says '?'",
    "seconds": 80.6
   },
   {
    "id": "30-colour-unnamed",
    "check": "30",
    "what": "a lifted figure's colour loses its declared meaning",
    "exit": 1,
    "fired": [
     "30"
    ],
    "caught": true,
    "line": "check 30: index.html: fs-wlc draws with --outside, which carries no declared meaning",
    "seconds": 80.4
   },
   {
    "id": "31-numbers-not-restated",
    "check": "31",
    "what": "the lifted figures no longer restate the numbers they draw",
    "exit": 1,
    "fired": [
     "31"
    ],
    "caught": true,
    "line": "check 31: index.html: a figure draws 0.24, 0.8, 190, 5.6, 7.5, which the page's text does not restate",
    "seconds": 75.3
   },
   {
    "id": "32-author-unplaced",
    "check": "32",
    "what": "the author is left off the sphere: no entry, no zone, no anchor",
    "exit": 1,
    "fired": [
     "13",
     "32"
    ],
    "caught": true,
    "line": "check 32: atlas.html: the author is not one entry of the register (0 regions, 0 marks)",
    "seconds": 78.8
   },
   {
    "id": "32-author-card-inflated",
    "check": "32",
    "what": "the author's card claims seven words more than the featured pieces hold",
    "exit": 1,
    "fired": [
     "32"
    ],
    "caught": true,
    "line": "check 32: atlas.html: the author's card reads '2B, Accounting and Financial Management, Analytics stream · co-op term January to April 2027, 96 days from this build (2026-09-27) · 7 featured pieces: 52,822 words, 40 figures, 58 tables'; the",
    "seconds": 79
   },
   {
    "id": "33-asset-missing",
    "check": "33",
    "what": "the editor links a stylesheet that does not exist",
    "exit": 1,
    "fired": [
     "3",
     "33"
    ],
    "caught": true,
    "line": "check 33: admin.html: reads --accent, which no stylesheet it loads defines",
    "seconds": 79.1
   },
   {
    "id": "33-editor-overwritten",
    "check": "33",
    "what": "the build writes the editor as if it were a generated page",
    "exit": 1,
    "fired": [
     "33"
    ],
    "caught": true,
    "line": "check 33: admin.html: carries no noindex",
    "seconds": 79.4
   },
   {
    "id": "33-token-undefined",
    "check": "33",
    "what": "the editor reads a custom property no stylesheet it loads defines",
    "exit": 1,
    "fired": [
     "33"
    ],
    "caught": true,
    "line": "check 33: admin.html: reads --edge-2, which no stylesheet it loads defines",
    "seconds": 78.9
   },
   {
    "id": "33-id-missing",
    "check": "33",
    "what": "the editor's script asks for an element its markup no longer carries",
    "exit": 1,
    "fired": [
     "33"
    ],
    "caught": true,
    "line": "check 33: admin.html: its script asks for #save-setup, which its markup does not carry",
    "seconds": 79.5
   },
   {
    "id": "33-script-broken",
    "check": "33",
    "what": "a syntax error in the editor's script",
    "exit": 1,
    "fired": [
     "33"
    ],
    "caught": true,
    "line": "check 33: admin.html: script block 2 does not parse: SyntaxError: Unexpected identifier 'is'",
    "seconds": 80.3
   },
   {
    "id": "33-worker-stores-the-editor",
    "check": "33",
    "what": "the worker the build writes stores the editor like any other page",
    "exit": 1,
    "fired": [
     "33"
    ],
    "caught": true,
    "line": "check 33: sw.js: the worker the build writes does not name admin.html among the files it never stores",
    "seconds": 80.4
   },
   {
    "id": "33-truncated",
    "check": "33",
    "what": "the editor's file ends before its markup does",
    "exit": 1,
    "fired": [
     "33"
    ],
    "caught": true,
    "line": "check 33: admin.html: is not a whole document; it must open with the doctype and close with </html>",
    "seconds": 80.1
   },
   {
    "id": "34-mark-element-invented",
    "check": "34",
    "what": "the pages draw a line the mark's file does not carry",
    "exit": 1,
    "fired": [
     "34"
    ],
    "caught": true,
    "line": "check 34: 404.html: the brand mark drawn is not the geometry content/marks holds",
    "seconds": 81.3
   },
   {
    "id": "34-mark-stroke-unscaled",
    "check": "34",
    "what": "the tab icon is drawn at the authored stroke, which cannot hold an edge at that size",
    "exit": 1,
    "fired": [
     "34"
    ],
    "caught": true,
    "line": "check 34: the favicon mark's thinnest stroke draws 0.375 device pixels at 16px, under the one pixel an edge needs",
    "seconds": 80.9
   },
   {
    "id": "34-mark-source-missing",
    "check": "34",
    "what": "a mark's source file is gone, so what the pages draw answers to nothing",
    "exit": 1,
    "fired": [
     "34"
    ],
    "caught": true,
    "line": "check 34: content/marks/02_forensic_audit_delta.svg: missing, so the controls mark cannot be drawn",
    "seconds": 80.6
   },
   {
    "id": "34-inspection-unscaled",
    "check": "34",
    "what": "the header's construction layer is drawn at the letters' factor, which cannot hold an edge at 24px",
    "exit": 1,
    "fired": [
     "34"
    ],
    "caught": true,
    "line": "check 34: the brand inspected mark's thinnest stroke draws 0.619 device pixels at 24px, under the one pixel an edge needs",
    "seconds": 81.4
   },
   {
    "id": "35-glyph-element-invented",
    "check": "35",
    "what": "a glyph is drawn with a line its file does not carry",
    "exit": 1,
    "fired": [
     "35"
    ],
    "caught": true,
    "line": "check 35: colophon.html: the gl-evidence drawn is not the geometry content/marks holds",
    "seconds": 80.9
   },
   {
    "id": "35-glyph-drawn-too-small",
    "check": "35",
    "what": "a glyph is drawn at a size its authored stroke cannot hold",
    "exit": 1,
    "fired": [
     "35"
    ],
    "caught": true,
    "line": "check 35: the evidence glyph draws 0.938 device pixels at 18px, under the one pixel an edge needs",
    "seconds": 81
   },
   {
    "id": "35-glyph-source-missing",
    "check": "35",
    "what": "a glyph's source file is gone, so the column head answers to nothing",
    "exit": 1,
    "fired": [
     "35"
    ],
    "caught": true,
    "line": "check 35: content/marks/glyphs/04_tested.svg: missing, so the tested glyph cannot be drawn",
    "seconds": 82.2
   },
   {
    "id": "35-seal-keeps-the-ring-it-cannot-hold",
    "check": "35",
    "what": "the seal draws the ring whose stroke is under a device pixel at every size",
    "exit": 1,
    "fired": [
     "35"
    ],
    "caught": true,
    "line": "check 35: the seal drops 0 element(s) at stroke 0.0; the rule drops exactly the one its finest stroke cannot hold",
    "seconds": 82
   },
   {
    "id": "35-figure-of-another-document",
    "check": "35",
    "what": "every statement row draws the first piece's figure instead of its own",
    "exit": 1,
    "fired": [
     "35"
    ],
    "caught": true,
    "line": "check 35: library.html: the figure on afm241-cheat-sheet is not the geometry its 644 words, 2 figures, 0 tables and 0 recorded links produce",
    "seconds": 81.4
   },
   {
    "id": "35-figure-resized-by-the-stylesheet",
    "check": "35",
    "what": "the stylesheet draws the figure at a size its stroke rule was not computed for",
    "exit": 1,
    "fired": [
     "35"
    ],
    "caught": true,
    "line": "check 35: site.css: a rule on the instruments sets width to 40px; each one is drawn at the size its stroke rule was computed for and is never resized",
    "seconds": 82.7
   },
   {
    "id": "35-figure-resized-through-its-frame",
    "check": "35",
    "what": "a descendant rule resizes the figure without naming its class",
    "exit": 1,
    "fired": [
     "35"
    ],
    "caught": true,
    "line": "check 35: site.css: a rule on the instruments sets height to 3rem; each one is drawn at the size its stroke rule was computed for and is never resized",
    "seconds": 82.5
   },
   {
    "id": "36-ink-under-the-floor",
    "check": "36",
    "what": "the faintest ink in Obsidian is set to a value that measures under 4.5:1 on the paper it stands on",
    "exit": 1,
    "fired": [
     "11",
     "36"
    ],
    "caught": true,
    "line": "check 36: site.css: ink-3 on panel in Obsidian (system) is 4.19:1, under the 4.5:1 a reader needs to read it",
    "seconds": 82.1
   },
   {
    "id": "36-light-strong-enough-to-matter",
    "check": "36",
    "what": "the instrument light behind the globe is turned up until it takes the accent under the floor",
    "exit": 1,
    "fired": [
     "36"
    ],
    "caught": true,
    "line": "check 36: site.css: accent on paper under --lamp-cool in Obsidian (system) is 2.99:1, under the 4.5:1 a reader needs to read it",
    "seconds": 81.1
   },
   {
    "id": "36-lamp-syntax-outside-the-parser",
    "check": "36",
    "what": "the active Archival Light reading pool uses a browser-valid color-mix stop that the contrast parser cannot measure",
    "exit": 1,
    "fired": [
     "36"
    ],
    "caught": true,
    "line": "check 36: site.css: --lamp-warm at line 85: unsupported lamp syntax; use only numeric rgba(...) percentage stops",
    "seconds": 80.8
   },
   {
    "id": "36-lamp-name-outside-the-inventory",
    "check": "36",
    "what": "the active reading pool is renamed with a suffix the old lamp regex did not capture",
    "exit": 1,
    "fired": [
     "36"
    ],
    "caught": true,
    "line": "check 36: site.css: --lamp-warm must be the whole background of its existing measured box",
    "seconds": 82.2
   },
   {
    "id": "36-lamp-override-outside-the-palette",
    "check": "36",
    "what": "a local reading-pool override bypasses the measured theme blocks",
    "exit": 1,
    "fired": [
     "36"
    ],
    "caught": true,
    "line": "check 36: site.css: --lamp-warm at line 2272 has an unsupported name or declaration scope",
    "seconds": 81.1
   },
   {
    "id": "36-lamp-gradient-with-an-extra-layer",
    "check": "36",
    "what": "a supported reading pool is followed by an unmeasured opaque gradient",
    "exit": 1,
    "fired": [
     "36"
    ],
    "caught": true,
    "line": "check 36: site.css: --lamp-warm at line 85: unsupported lamp syntax; use only numeric rgba(...) percentage stops",
    "seconds": 82
   },
   {
    "id": "36-lamp-rendered-twice",
    "check": "36",
    "what": "the reading pool is composited twice on its existing consumer",
    "exit": 1,
    "fired": [
     "36"
    ],
    "caught": true,
    "line": "check 36: site.css: --lamp-warm must be the whole background of its existing measured box",
    "seconds": 81.5
   },
   {
    "id": "36-dark-palettes-disagree",
    "check": "36",
    "what": "the dark ground the browser asks for and the dark ground the button sets stop agreeing",
    "exit": 1,
    "fired": [
     "36"
    ],
    "caught": true,
    "line": "check 36: site.css: the two dark palettes disagree on panel-2, #2a2b33 where the browser asks for dark and #1c1d22 where the button sets it",
    "seconds": 82.3
   },
   {
    "id": "37-header-without-scope",
    "check": "37",
    "what": "a generated table header no longer says which cells it heads",
    "exit": 1,
    "fired": [
     "37"
    ],
    "caught": true,
    "line": "check 37: index.html: a table header carries no scope, so nothing says which cells it heads",
    "seconds": 80.8
   },
   {
    "id": "38-anchor-that-is-not-there",
    "check": "38",
    "what": "a case slot points at a heading the piece does not carry",
    "exit": 1,
    "fired": [
     "38"
    ],
    "caught": true,
    "line": "check 38: content/cases.json: predictive-history names #the-finding-nobody-wrote for finding, and predictive-history.html carries no heading with that id",
    "seconds": 81
   },
   {
    "id": "38-heading-quoted-loosely",
    "check": "38",
    "what": "the page prints a heading the piece's own record does not hold",
    "exit": 1,
    "fired": [
     "38"
    ],
    "caught": true,
    "line": "check 38: selected.html: prints '01 A hypothesis' at #s-01-the-hypothesis of canadian-dcf-cca.html, and the invariance record holds no such heading there",
    "seconds": 81.8
   },
   {
    "id": "38-document-that-is-not-linked",
    "check": "38",
    "what": "a slot names a document the corpus records no link to",
    "exit": 1,
    "fired": [
     "38"
    ],
    "caught": true,
    "line": "check 38: content/cases.json: crucible-cockpit names not-significant for finding, and the corpus records no link between them",
    "seconds": 82.6
   },
   {
    "id": "38-case-for-a-piece-nothing-features",
    "check": "38",
    "what": "a case is written for a piece the site does not feature",
    "exit": 1,
    "fired": [
     "38"
    ],
    "caught": true,
    "line": "check 38: content/cases.json: not-significant carries a case but is not recorded as featured, so nothing on the site shows it",
    "seconds": 82.2
   },
   {
    "id": "38-coverage-counted-generously",
    "check": "38",
    "what": "the page counts a slot as carried that the files leave empty",
    "exit": 1,
    "fired": [
     "38"
    ],
    "caught": true,
    "line": "check 38: selected.html: the page counts 0 gap and the files hold 8",
    "seconds": 82
   },
   {
    "id": "38-review-leads-with-an-unfeatured-piece",
    "check": "38",
    "what": "the review map leads with a piece the site does not feature",
    "exit": 1,
    "fired": [
     "38"
    ],
    "caught": true,
    "line": "check 38: content/review.json: brittle-network is featured and the review map does not place it, so the page would lose it",
    "seconds": 82.2
   },
   {
    "id": "38-review-places-a-piece-twice",
    "check": "38",
    "what": "one piece both leads the review and supports it",
    "exit": 1,
    "fired": [
     "38"
    ],
    "caught": true,
    "line": "check 38: content/review.json: brittle-network is named under primary and under supporting; a piece leads or it supports, not both",
    "seconds": 81.8
   },
   {
    "id": "38-review-card-prints-another-piece-s-count",
    "check": "38",
    "what": "a review card prints the first piece's word count instead of its own",
    "exit": 1,
    "fired": [
     "38"
    ],
    "caught": true,
    "line": "check 38: selected.html: the brittle-network card does not print the words the files hold for it, which is 9,237",
    "seconds": 82
   },
   {
    "id": "38-review-routes-to-a-section-that-is-not-there",
    "check": "38",
    "what": "a review card opens at a heading the piece does not carry",
    "exit": 1,
    "fired": [
     "38"
    ],
    "caught": true,
    "line": "check 38: content/review.json: brittle-network routes to #the-section-nobody-wrote, and brittle-network.html carries no heading with that id",
    "seconds": 81.6
   },
   {
    "id": "38-review-route-dropped-from-the-page",
    "check": "38",
    "what": "the page sends a routed card to the front of the document instead",
    "exit": 1,
    "fired": [
     "38"
    ],
    "caught": true,
    "line": "check 38: selected.html: the brittle-network card does not open at #systems-modelling-and-network-vulnerability-test, which the review map routes it to",
    "seconds": 82.2
   },
   {
    "id": "38-resume-proof-figure-its-own-entry-does-not-carry",
    "check": "38",
    "what": "the resume prints a figure the entry's own lines never state",
    "exit": 1,
    "fired": [
     "38"
    ],
    "caught": true,
    "line": "check 38: content/resume.json: the proof on Taxwide Inc. prints 900+, which that entry's own lines do not carry",
    "seconds": 82.3
   },
   {
    "id": "13-callout-quotes-a-number-the-piece-does-not-state",
    "check": "13",
    "what": "a review callout states a count the piece it describes never states",
    "exit": 1,
    "fired": [
     "13"
    ],
    "caught": true,
    "line": "check 13: content/review.json: the callout of brittle-network quotes 150, which brittle-network.html does not state",
    "seconds": 82.2
   },
   {
    "id": "32-now-block-stale-by-a-day",
    "check": "32",
    "what": "the Now block counts the co-op window from the day before this build",
    "exit": 1,
    "fired": [
     "32"
    ],
    "caught": true,
    "line": "check 32: about.html: the Now block does not read 'January to April 2027, 96 days from this build', which is the co-op window this build computes",
    "seconds": 81.8
   },
   {
    "id": "39-capability-evidenced-by-nothing",
    "check": "39",
    "what": "a capability the page claims is left with no work behind it",
    "exit": 1,
    "fired": [
     "39"
    ],
    "caught": true,
    "line": "check 39: content/capabilities.json: canadian names no piece at all",
    "seconds": 82.9
   },
   {
    "id": "39-capability-names-an-unlisted-piece",
    "check": "39",
    "what": "a capability names a piece the site does not list",
    "exit": 1,
    "fired": [
     "39"
    ],
    "caught": true,
    "line": "check 39: content/capabilities.json: reporting names a-piece-nobody-wrote, which is not a listed piece",
    "seconds": 82.9
   },
   {
    "id": "39-capability-total-that-is-not-the-sum",
    "check": "39",
    "what": "the words printed beside a claim are not the words of its pieces",
    "exit": 1,
    "fired": [
     "39"
    ],
    "caught": true,
    "line": "check 39: about.html: building prints 23543 words and its own pieces measure 22543",
    "seconds": 82.2
   },
   {
    "id": "42-thumb-head-without-a-tab",
    "check": "42",
    "what": "the thumb index leaves the last section head of every indexed page without a tab",
    "exit": 1,
    "fired": [
     "42"
    ],
    "caught": true,
    "line": "check 42: about.html: the section head 'Why the site exists' has no tab",
    "seconds": 81.7
   },
   {
    "id": "42-thumb-tab-in-another-head-s-words",
    "check": "42",
    "what": "every tab carries the words of the head after the one it lands on",
    "exit": 1,
    "fired": [
     "42"
    ],
    "caught": true,
    "line": "check 42: about.html: tab 1 says 'What this portfolio demonstrates', and the head it lands on says 'The short version'",
    "seconds": 81.7
   },
   {
    "id": "42-thumb-tab-lands-nowhere",
    "check": "42",
    "what": "the id written on a head is not the id its tab lands on",
    "exit": 1,
    "fired": [
     "42"
    ],
    "caught": true,
    "line": "check 42: about.html: tab 1 lands on #sec-the-short-version, and the head it stands for is #sec-the-short-version-h",
    "seconds": 81.4
   },
   {
    "id": "42-thumb-index-on-a-short-page",
    "check": "42",
    "what": "the emitter indexes pages with two section heads, which the rule leaves without one",
    "exit": 1,
    "fired": [
     "42"
    ],
    "caught": true,
    "line": "check 42: coursework.html: carries a thumb index over 2 section heads; an index needs 3",
    "seconds": 79.3
   },
   {
    "id": "42-thumb-index-on-an-instrument",
    "check": "42",
    "what": "the controls page, one of the two finished instruments, is given an index",
    "exit": 1,
    "fired": [
     "42"
    ],
    "caught": true,
    "line": "check 42: controls.html: carries a thumb index, and its page is one of the two finished instruments that carry none",
    "seconds": 79.5
   }
  ]
 },
 "runtime": {
  "meta": {
   "tool": "build/audit.js --falsify",
   "date": "2026-09-27",
   "commit": "aab42be",
   "code": "e87c0e3a6638"
  },
  "cases": [
   {
    "key": "ext",
    "page": "about.html",
    "what": "the page loads an image from another origin",
    "rec": {
     "ext": {
      "requests": 7,
      "external": 1
     }
    }
   },
   {
    "key": "idle",
    "page": "about.html",
    "what": "a script requests a new frame on every frame after load",
    "rec": {
     "idle": {
      "frames": 60
     }
    }
   },
   {
    "key": "keyboard",
    "page": "about.html",
    "what": "a stylesheet removes the focus ring from every element",
    "rec": {
     "keyboard": {
      "stops": 49,
      "noRing": 49
     }
    }
   },
   {
    "key": "print",
    "page": "index.html",
    "what": "under print media the figures may break across pages and the header stays pinned",
    "rec": {
     "print": {
      "stickyLeft": 1,
      "hidden": 0,
      "figures": 3,
      "figuresBreakable": 3
     }
    }
   },
   {
    "key": "motion",
    "page": "about.html",
    "what": "the brand mark spins under reduced motion",
    "rec": {
     "motion": {
      "animations": 1
     }
    }
   },
   {
    "key": "fit",
    "page": "about.html",
    "what": "a 900px block that no declaration allows",
    "rec": {
     "fit": {
      "scrollWidth": 900,
      "overflow": true
     }
    }
   },
   {
    "key": "chrome",
    "page": "positive-vs-normative.html",
    "what": "a block the build owns carries words the count would include",
    "rec": {
     "chrome": {
      "a": 603,
      "b": 597
     }
    }
   },
   {
    "key": "descent",
    "page": "index.html",
    "what": "a script keeps requesting frames after the scroll has stopped",
    "rec": {
     "descent": {
      "wide": {
       "rows": 6,
       "aimed": 6,
       "faced": 6,
       "framesSettle": 1554,
       "framesAfter": 2220,
       "framesAtTop": 671
      },
      "phone": {
       "rows": 6,
       "aimed": 6,
       "faced": 6,
       "framesSettle": 16026,
       "framesAfter": 22800,
       "framesAtTop": 4020
      }
     }
    }
   },
   {
    "key": "theme",
    "page": "index.html",
    "what": "the first-visit pulse repeats on every visit",
    "rec": {
     "theme": {
      "options": 2,
      "pressed": 1,
      "pulsed": true,
      "pulseEnded": true,
      "repeated": true,
      "switched": true,
      "framesAfterSwitch": 0,
      "focusRing": true
     }
    }
   },
   {
    "key": "theme",
    "page": "index.html",
    "what": "a switch of theme starts a loop that keeps requesting frames",
    "rec": {
     "theme": {
      "options": 2,
      "pressed": 1,
      "pulsed": true,
      "pulseEnded": true,
      "repeated": false,
      "switched": true,
      "framesAfterSwitch": 61,
      "focusRing": true
     }
    }
   },
   {
    "key": "corona",
    "page": "index.html",
    "what": "the sphere's payload records the wrong origin for two featured documents, so the corona names an origin the row does not have",
    "rec": {
     "corona": {
      "wide": {
       "rows": 6,
       "matched": 4,
       "atTop": "none"
      },
      "phone": {
       "rows": 6,
       "matched": 4,
       "atTop": "none"
      }
     }
    }
   },
   {
    "key": "descent",
    "page": "index.html",
    "what": "the sphere's document payload names the wrong document for the first two featured rows",
    "rec": {
     "descent": {
      "wide": {
       "rows": 6,
       "aimed": 6,
       "faced": 4,
       "framesSettle": 0,
       "framesAfter": 0,
       "framesAtTop": 0
      },
      "phone": {
       "rows": 6,
       "aimed": 6,
       "faced": 4,
       "framesSettle": 0,
       "framesAfter": 0,
       "framesAtTop": 0
      }
     }
    }
   },
   {
    "key": "inspect",
    "page": "about.html",
    "what": "the construction layer is drawn at rest, so the mark has one state and not two",
    "rec": {
     "inspect": {
      "layers": 2,
      "rest": 1,
      "hover": 1,
      "focus": 1,
      "ms": 220,
      "moved": 0,
      "framesAfter": 0,
      "reducedMs": 0
     }
    }
   },
   {
    "key": "inspect",
    "page": "about.html",
    "what": "the transition runs past the 260ms cap and keeps running for a reader who asked for no motion",
    "rec": {
     "inspect": {
      "layers": 2,
      "rest": 0,
      "hover": 0.666577,
      "focus": 1,
      "ms": 900,
      "moved": 0,
      "framesAfter": 0,
      "reducedMs": 900
     }
    }
   },
   {
    "key": "thumbs",
    "page": "resume.html",
    "what": "a script pulls the tab after the part being read",
    "rec": {
     "thumbs": {
      "tabs": 8,
      "wide": {
       "stops": 8,
       "positions": 9,
       "matched": 2,
       "landed": 8,
       "covered": 0,
       "framesAfter": 0
      },
      "phone": {
       "stops": 8,
       "positions": 9,
       "matched": 2,
       "landed": 8,
       "covered": 0,
       "framesAfter": 0
      },
      "reduced": {
       "animations": 0,
       "matched": false
      }
     }
    }
   },
   {
    "key": "thumbs",
    "page": "resume.html",
    "what": "the index is widened at rest until it lies over the text column",
    "rec": {
     "thumbs": {
      "tabs": 8,
      "wide": {
       "stops": 8,
       "positions": 9,
       "matched": 9,
       "landed": 8,
       "covered": 0,
       "framesAfter": 0
      },
      "phone": {
       "stops": 8,
       "positions": 9,
       "matched": 9,
       "landed": 8,
       "covered": 36,
       "framesAfter": 0
      },
      "reduced": {
       "animations": 0,
       "matched": true
      }
     }
    }
   },
   {
    "key": "thumbs",
    "page": "resume.html",
    "what": "the pulled tab keeps its transition for a reader who asked for no motion",
    "rec": {
     "thumbs": {
      "tabs": 8,
      "wide": {
       "stops": 8,
       "positions": 9,
       "matched": 9,
       "landed": 8,
       "covered": 0,
       "framesAfter": 0
      },
      "phone": {
       "stops": 8,
       "positions": 9,
       "matched": 9,
       "landed": 8,
       "covered": 0,
       "framesAfter": 0
      },
      "reduced": {
       "animations": 2,
       "matched": true
      }
     }
    }
   },
   {
    "key": "thumbs",
    "page": "resume.html",
    "what": "a pressed tab starts a loop that keeps requesting frames after the stop",
    "rec": {
     "thumbs": {
      "tabs": 8,
      "wide": {
       "stops": 8,
       "positions": 9,
       "matched": 9,
       "landed": 8,
       "covered": 0,
       "framesAfter": 2160
      },
      "phone": {
       "stops": 8,
       "positions": 9,
       "matched": 9,
       "landed": 8,
       "covered": 0,
       "framesAfter": 2160
      },
      "reduced": {
       "animations": 0,
       "matched": true
      }
     }
    }
   },
   {
    "key": "admin",
    "page": "admin.html",
    "what": "a syntax error in the editor's script",
    "rec": {
     "admin": {
      "errors": 1,
      "failed": 0,
      "requests": 3,
      "external": 0,
      "stubbed": 0,
      "writes": 0,
      "idleFrames": 0,
      "tabs": 4,
      "switched": 1,
      "threwUnconnected": 0,
      "themeSwitched": false,
      "themeStored": false,
      "cfgSaved": false,
      "tokenInSession": false,
      "tokenInLocal": false,
      "rows": 0,
      "pieces": 69,
      "searched": 0,
      "searchExpected": 26,
      "editorOpened": false,
      "editEnabledPublish": false,
      "promptShown": false,
      "forgotten": true,
      "guardHeld": false,
      "files": 0,
      "filesExpected": 134,
      "siteFields": 0,
      "scrollWidth": 320,
      "overflow": false
     }
    }
   },
   {
    "key": "admin",
    "page": "admin.html",
    "what": "the editor links a stylesheet that does not exist",
    "rec": {
     "admin": {
      "errors": 1,
      "failed": 2,
      "requests": 4,
      "external": 0,
      "stubbed": 2,
      "writes": 0,
      "idleFrames": 0,
      "tabs": 4,
      "switched": 4,
      "threwUnconnected": 0,
      "themeSwitched": true,
      "themeStored": true,
      "cfgSaved": true,
      "tokenInSession": true,
      "tokenInLocal": false,
      "rows": 69,
      "pieces": 69,
      "searched": 26,
      "searchExpected": 26,
      "editorOpened": true,
      "editEnabledPublish": true,
      "promptShown": true,
      "forgotten": true,
      "guardHeld": true,
      "files": 134,
      "filesExpected": 134,
      "siteFields": 13,
      "scrollWidth": 320,
      "overflow": false
     }
    }
   },
   {
    "key": "admin",
    "page": "admin.html",
    "what": "the editor writes the token to long-term storage beside the repository",
    "rec": {
     "admin": {
      "errors": 0,
      "failed": 0,
      "requests": 5,
      "external": 0,
      "stubbed": 2,
      "writes": 0,
      "idleFrames": 0,
      "tabs": 4,
      "switched": 4,
      "threwUnconnected": 0,
      "themeSwitched": true,
      "themeStored": true,
      "cfgSaved": true,
      "tokenInSession": true,
      "tokenInLocal": true,
      "rows": 69,
      "pieces": 69,
      "searched": 26,
      "searchExpected": 26,
      "editorOpened": true,
      "editEnabledPublish": true,
      "promptShown": true,
      "forgotten": true,
      "guardHeld": true,
      "files": 134,
      "filesExpected": 134,
      "siteFields": 13,
      "scrollWidth": 320,
      "overflow": false
     }
    }
   },
   {
    "key": "offline",
    "page": "sw.js",
    "what": "the new worker neither carries the saved copy across nor syncs it, so a publish empties it",
    "rec": {
     "before": 192,
     "of": 192,
     "after": 0,
     "refreshed": false,
     "editor": {
      "stored": false,
      "fresh": true
     }
    }
   },
   {
    "key": "offline",
    "page": "sw.js",
    "what": "the worker stores the editor like any other page, so a visit leaves it in the cache",
    "rec": {
     "before": 192,
     "of": 192,
     "after": 192,
     "refreshed": true,
     "editor": {
      "stored": true,
      "fresh": true
     }
    }
   }
  ]
 }
}
