2026.10.16The services page is 13 cards, each with a sourced number; /why lists every source.26 files · +5198 −88 · site, concierge, functions, tests, build scripts, config, docs/privatesite/services.html rebuilt as 13 cards, 1 per service, each with 1 or 2 fact sentences and 2 closed folds: the quote, source, year and link; what is included. site/data/facts.json holds 92 verified records and 31 claims not used, from the research sheet; scripts/facts-build.js renders both pages' blocks between markers and --check reds a stale page. site/why.html groups the facts by topic and closes with the claims not used. The house document carries the facts with sources. No prices on the page. Known: every drafted string awaits the voice pass.// PR #151 — 1 commit · 2026.10.16
2026.10.16The concierge sees the finished audit: the page exposes the run id, the close keeps it.10 files · +213 −13 · site, concierge, tests, config, docs/privateAfter a finished run on /depth-skim the concierge said it could not see the results. site/depth-skim.html declared _crawlData with a script-scoped let, so the panel's read of window._crawlData was undefined, and the close removed the rdSkimRun session entry. The page now sets window.rdSkimRunId beside both _crawlData assignments and the panel reads it first; the close rewrites rdSkimRun with the finished id and done: true; the RESUME banner and the crawl-dropped retry skip a done entry. concierge-3-test runs a scripted crawl on the real page. Known: no live walk yet.// PR #150 — 5 commits · 2026.10.16
2026.10.15The concierge offers to move you, reads the audit on screen, and knows your page.13 files · +1735 −46 · site, concierge, functions, tests, build scripts, config, docs/privatenetlify/functions/concierge.js accepts 1 offer per reply (go, scroll, prefill_audit, open_fineprint), validates it against the house document, drops it when invalid, and marks a declined offer on its message for the next prompt. site/concierge.js draws the offer as a card with Yes and No; only Yes moves the page, and a go reopens the panel there under the same token. On /depth-skim the run on screen enters the prompt; every message carries the heading in view, the scroll percent and up to 500 selected characters. Known: no live model call.// PR #148 — 2 commits · 2026.10.15
2026.10.15All 96 ledger entries rewritten from their diffs; stats from git; a scope line renders.107 files · +1442 −297 · site, tests, build scripts, docs/privatesite/ledger/entries/: each of the 96 entries was rewritten from the merge commits its prs name, or from dated commits a new commits: line records; 6 rows carry scope: none with the reason first. scripts/ledger-stats.js computes files, ins, del and systems from git, and scripts/ledger-build.js renders them as 1 scope line after the lede, refusing a half set or an unknown system. Both pages style .rd-scope. ledger-flow-test.js finds 3 pinned rows by PR, not lede. Known: ledger:drafts counts all 68 rewritten drafts as new.// PR #147 — 2 commits · 2026.10.15
2026.10.15The home page's answer lists 10 examples in bold cyan, scoped to 1 section.11 files · +172 −10 · site, functions, tests, docs/privatesite/index.html: the middle paragraph of "What does Relative Dynamics do?" is the brief's text; 5 bold examples become 10. 1 rule, #process .rd-lede b{color:#00cce8}, gives the bold the footer links' cyan in that section only; the weight and the base .rd-lede b rule are untouched. The arc's own test pins the text, the 10 phrases, the 1 scoped rule and the computed colour inside and outside; front-door-oct-test.js and front-door-polish-test.js move their 5-phrase pins to the 10. concierge-house.json is rebuilt. render-widths at 375 and 1440: no overflow.// PR #146 — 3 commits · 2026.10.15
2026.10.15public-skim gets the crawler's 26 s ceiling; the intake reads the content type first.10 files · +261 −7 · site, tests, config, docs/private"Run the map" on reldyn.io/contact died with "Unexpected token '<' … is not valid JSON". public-skim runs deep-crawl in-process under the platform's default function ceiling while deep-crawl had 26 s, so a slow target returned the platform's own HTML 504 page and contact-intake.js called res.json() on it. netlify.toml adds [functions.public-skim] timeout = 26; contact-intake.js reads the content type first, wraps the parse, and shows 1 plain timeout line for a non-JSON, unparsable or unworded non-2xx reply. Known: the probe cost 3 free maps; the well refunds no timed-out map.// PR #145 — 1 commit · 2026.10.15
2026.10.15Concierge: canvas gone, opaque bubbles, 1-line header, contact pointers, 2 buttons.12 files · +609 −169 · site, concierge, tests, config, docs/privateAfter the first live look: the concierge script drops the blanket canvas, node field and phone band; the bubbles are solid panels in the site's body face; the header is 1 line at 390. The concierge function: every reply that had pointed at the home page's contact section, gone since #143, now gives the phone, the email and /contact, and RULES answers the question first. "Start over" mints a new token and deletes nothing; "Report a problem" flags the conversation and pings the rail. Known: still no live model call.// PR #144 — 1 commit · 2026.10.15
2026.10.15/contact is a page again: the form moved there byte-identical, its script shared.26 files · +1025 −252 · site, concierge, functions, tests, docs/privatesite/contact.html had been a meta-refresh stub to /index.html#contact since 2026-07-24, and the home page carried the form and the public map in 1 section with the intake script inline. contact.html is about.html's shell with a 1-line headline, the phone and the email as links, the same form and the map under it; index.html keeps the map and shows the number, the address and 1 Contact button where the form stood; site/contact-intake.js serves both pages. The deploy preview showed the host-rewritten form on /contact and none on the home page.// PR #143 — 2 commits · 2026.10.15
2026.10.155 pages in the owner's words; /ledger is a page; 2 EZ Read reds retired; 1 footer rule.32 files · +872 −1706 · site, functions, tests, build scripts, config, docs/privateabout.html reads 9+ years and loses the coined-term footnote and the AART proof panel; tools.html opens on the tools, the full-screen notice and the Client Vault card gone; depth-skim.html's public view is a headline, 1 sentence and the fine print folded behind 1 closed disclosure; privacy.html's deletion section is 1 paragraph at no charge; nav.js colours every footer link cyan from 1 rule. index-full-ledger.html became ledger.html and netlify.toml forwards both old addresses to /ledger. 2 EZ Read pins now read current behaviour and leave KNOWN REDS.// PR #142 — 2 commits · 2026.10.15
2026.10.14A concierge chat on the 17 public pages: 1 page script and a Haiku-backed function.30 files · +1350 −9 · site, concierge, functions, tests, build scripts, config, docs/privateThe concierge script draws a wolf-head bubble, the panel, a blanket canvas and a greyed "Jacob" tab, with 1 random 32-hex token in localStorage, no cookie, kept up to 2 years per privacy.html. The concierge function (claude-haiku-5-5) answers from concierge-house.json, the pages' own text gathered at build, and nothing else; 4 limits precede any spend: $1 a day for everyone, 40 messages a day per conversation, 60 an hour per connection, 1200 tokens a reply; every 6 turns the older fold into facts. Known: no live model call.// PR #140 — 1 commit · 2026.10.14
2026.10.14EZ READ removed; the hero is label, headline and buttons; body copy heavier and brighter.26 files · +1004 −352 · site, tests, build scripts, docs/privateindex.html's hero had opened on a version stamp, an amber "degrade gracefully" line and a paragraph; all 3 are gone. The EZ READ toggle, which scaled every rem by 18%, left the bar, the drawer and nav.js, and the default it compensated for changed: body copy on the 10 public pages is weight 500, #d8eaf8, and 1 size larger on a phone. scripts/render-widths.cjs renders 375, 768, 1024 and 1440 in real Chrome. Known: 2 older tests still ask for the toggle and stay red.// PR #139 — 1 commit · 2026.10.14
2026.10.14The footer grid runs 4 columns from 760 px; the work is "custom-coded"; 3 cards, 1 answer.13 files · +443 −36 · site, tests, docs/privateThe footer's fault was density: on a touch screen every grid row is a 44 px target and the grid ran 1 column under 480 px and 2 to 860, so the 375 footer stood 843 px tall. nav.js now runs 4 columns from 760 px and 2 from 375. Every public page and its tags had used 2 older words for the work; the word is custom-coded. index.html's 3 cards became 1 section, "What does Relative Dynamics do?", marked for Jacob's voice.// PR #138 — 1 commit · 2026.10.14
2026.10.10The tab icon is the wolf head in all 3 files; the 4 rndlabs pages gained the 3 icon links.14 files · +233 −21 · site, tests, docs/privateThe SVG, the ICO (16, 32 and 48 px) and the 180×180 touch icon had carried the nav polygon; the 3 files are the wolf drop-in Jacob picked, pinned by sha256. The SVG is a 128 px raster inside an SVG, so it will not sharpen past that. The arc's grep found 4 lab pages with no icon link; they carry the same 3 links as the other 14. Known: index.html's JSON-LD logo points at the live site's copy of the touch icon, so it changes on promotion, not before.// PR #137 — 1 commit · 2026.10.10
2026.10.07A run started at a URL with a path crawls that path as the site; the board says so.163 files · +1062 −218 · site, functions, tests, build scripts, config, docs/privatedeep-crawl.js and depth-skim.html had both cut the path off a typed address and audited the whole host, so the 9 test businesses under /zoo/ could not be read as 9 sites. A path is now the site: the page at that address is the homepage, only pages beneath it are read, links to the rest of the host are counted, and the board and the report state the scope in a line; a bare domain behaves as before. Known: the map still draws from the host's root.// PR #136 — 1 commit · 2026.10.07
2026.10.02plan-sync-b-test's NOW text pin retired; NOW names the ledger drafts before the promotion.5 files · +14 −5 · site, tests, docs/privateProcess only; nothing a visitor sees changed. plan-sync-b-test.js had held BUILD_PLAN's NOW line word for word ("eyeball reldyn.io after the seven merges … then the promotion call"), so every handoff that moved the plan forward had to leave it where it was. The pin is retired as voice-pass-a's was on #123, with build-plan-shape-test.js still holding the line's shape, and NOW now reads: a look at the staging site, then the new ledger drafts voiced there, then the promotion (BUILD_PLAN.md −3 +2, the test −2 +1). Merged as #135 (0c1663b).// PR pending — 1 commit · 2026.10.02
2026.10.02The ledger is 1 file per entry; both pages generated; every merge has an entry.101 files · +1321 −116 · site, tests, build scripts, config, docs/privateThe ledger had been 2 hand-edited pages that drifted: the 09-20 entry reached the full ledger and never the homepage, 2 trailers shipped with no PR number, and of the 21 PRs merged from #113 to #133 only 3 had an entry. scripts/ledger-build.js assembles both pages' block from site/ledger/entries/; ledger-flow-test.js reds when a page differs from the generator or a merge has no entry; the 18 missing entries were written; npm run ledger:drafts exits 1 while any of the 25 new drafts is unvoiced.// PR #134 — 1 commit · 2026.10.02
2026.10.02Jacob's answers on plan-sync-b's 7 calls: all accepted and struck; the range moves.3 files · +28 −11 · tests, docs/privateProcess only; nothing a visitor sees changed. BUILD_PLAN.md: the 7 OWED lines from the plan-sync-b handoff (the moved voice-pass-a pins, the 4 landed handoffs, SITE-VISUAL-D struck, the B14 edit, the range, the runner fix, the #132 merge) are answered and struck; B10 and the promotion line now read #83–#132 where they had read #83–#130; ARC-RUNNER-HANDOFF is queued so a handoff session waits for its suite and commits before its worktree is removed. CONTEXT.md carries the dated answers, and plan-sync-b-test.js pins all 3.// PR #133 — 1 commit · 2026.10.02
2026.09.28–10.023 handoff-only PRs: site-visual-c, voice-pass-a and plan-sync-b closed into their notes.5 files · +177 −5 · tests, docs/privateProcess only; nothing a visitor sees changed. A piece of work here ends with a handoff file under _private/handoffs/ (Shipped, Red, Jacob decides) and its decisions copied into BUILD_PLAN's OWED list. 3 such closes merged as PRs of their own: #121 on 09-28 (site-visual-c's 9 Jacob-decides lines), #123 on 09-30 (voice-pass-a's 4, with the NOW text pin retired) and #132 on 10-02 (plan-sync-b, after #131 merged as 940ff87). Together: 2 handoff files, 1 test line and 31 lines of BUILD_PLAN.md. They share this entry so that every merge has 1.// PR #121, #123, #132 — 3 commits · 2026.09.28–10.02
2026.10.01BUILD_PLAN and CONTEXT absorbed the 7 merges of 10-01; 4 missing handoffs landed.10 files · +793 −23 · tests, docs/privateProcess only; nothing a visitor sees changed. 7 arcs ran unattended on 09-30 under a rule of no plan edits, and all 7 merged on 10-01. At that tip NOW still named the #83 to #122 promotion, 8 QUEUE lines named shipped work, and 4 of the 7 handoffs were not in the repo: 3 sessions ended before committing. BUILD_PLAN.md gained 1 DONE line per merge, the OWED lines from each handoff and the 8 strikes; CONTEXT.md gained 10 dated decisions; the 4 handoffs are committed.// PR #131 — 1 commit · 2026.10.01
2026.10.01site/fonts/fonts.css exists for the first time; crc.js's resize handler no longer throws.5 files · +329 −1 · site, tests, docs/private13 pages had linked /fonts/fonts.css since 2026-07-24, and no ref ever held the file: the deploy answered the site's 404 page and no @font-face existed anywhere under site/, so every page drew in the generic family. fonts.css now carries 6 @font-face rules, 1 per woff2, and pages draw in Rajdhani and Share Tech Mono. crc.js declared CRC as a top-level const, so crc-spawn's init never ran and its resize listener threw once per window resize; the handler now checks for its canvas. Known: the tapes' 503 is unexplained.// PR #130 — 1 commit · 2026.10.01
2026.10.01A placeholder homepage is 1 finding that holds the run; a wrong-host certificate is named.12 files · +861 −33 · site, functions, tests, config, docs/private4 of Jacob's own runs: homepages reading "doing some work, back soon", "Website Coming Soon!" and the builder default "Home | Mysite" each came back with a full board. skim-core/placeholder.js reads the homepage's own words first: when the page is the sign it records 1 placeholder finding quoting them and deep-crawl.js holds every other finding from ranking and resolve. The 4th run served a certificate for another name, once classed as conn; it is now a certificate finding naming the host asked for and the names carried.// PR #129 — 1 commit · 2026.10.01
2026.10.019 fictional business sites under site/zoo/, 8 seeded with 28 faults, 1 clean control.235 files · +26326 −1 · site, tests, build scripts, docs/privateThe instrument needs sites whose faults are known before it reads them. site/zoo/ holds 9 Tri-State businesses, 144 pages with their own style.css, robots.txt, sitemap.xml and security.txt; 8 carry 2 to 5 web-presence faults each, 28 in all, and the 9th is the clean control. Every address, email and phone is fake by design, site/robots.txt keeps search engines out, and scripts/zoo-pack.js packs them; the answer keys sit under zoo/, outside the published tree. Known: no audit has been run against them; until 1 is, they prove nothing.// PR #128 — 2 commits · 2026.10.01
2026.09.30The phone drawer starts at the bar's measured bottom, not 4.6rem; the dial sits inline.10 files · +446 −18 · site, tests, config, docs/privatenav.js: the full-width drawer under 480 px started at a constant top of 4.6rem, while the bar it must clear measures 51 px plus 1.4rem, 73.4 px only at a 16 px root; at 12 px the drawer rode over the bar and the menu button. The drawer now reads the bar's bottom into --rd-bar-bottom each time it opens. The particle script was 1 render-blocking request for 1 line; 3 heads set the dial inline. Known: a phone in a hand has not confirmed the measure.// PR #127 — 1 commit · 2026.09.30
2026.09.30"Relative Dynamics LLC" on every head surface voice-pass-a left behind: 13 pages.20 files · +388 −62 · site, tests, docs/private#122 applied the settled name to index.html's title and JSON-LD and left the rest: og:site_name read the bare name on 13 pages, og:image:alt led with it on 13, and 11 titles ended in it. All now read "Relative Dynamics LLC"; no title lost a word. The stale DRAFT comments beside strings Jacob kept on #122 came out of the markup. Not changed, and not decided: the wordmark in the menu, the card image, and "Relative Dynamics" in the about and privacy running copy.// PR #126 — 1 commit · 2026.09.30
2026.09.30The footer is 1 static link grid on the 7 public pages: 4 columns and the legal line.14 files · +804 −121 · site, tests, docs/private3 things had stacked at the bottom of every page: a status row set at 9.9 px, the 5-door row only index.html carried, and a dotted 1-line footer. Each of the 7 pages now carries 1 footer block with a nav grid of 12 links under 4 headings and the LLC-and-town line, styled once in nav.js; the Call link and "Leave a review" moved into the Contact column. Corrects: the first render animated its links in from browser blue in 3 of 42 frames, fixed before it shipped.// PR #125 — 1 commit · 2026.09.30
2026.09.30An image URL over the store's 768-byte key limit no longer loses the pages with it.11 files · +809 −20 · site, functions, tests, config, docs/privateRun 9100c84 logged store refusals and came back short of pages. The encoder cannot shorten a key: a page record keys imgDims and imgBy by full image URL, the encoder triples every dot and slash, and the store's key limit is 768 bytes, so 1 long source refused the whole patch, every page in the slice with it. skim-core/pages-store.js leaves unkeyable sources out and counts them; a refused patch is retried 1 page at a time, and a page that still will not land is a recorded miss.// PR #124 — 1 commit · 2026.09.30
2026.09.29Jacob's voiced strings applied: the title, 2 descriptions, "Audit my site", 1 name.13 files · +293 −44 · site, tests, docs/privateCopy only, no code path changed. index.html's title and og:title are now "Relative Dynamics LLC — Problems Move. So Do We."; depth-skim.html's and about.html's descriptions carry Jacob's lines (138 and 145 characters, left whole); the hero button, nav.js and the footer row all say "Audit my site" where 3 wordings of 1 door had stood; the JSON-LD name equals its legalName; rndlabs/aart/index.html asks search engines not to index it. bda978f recorded Jacob's answers: every other voice item kept as it is, and the OWED lines struck.// PR #122 — 2 commits · 2026.09.29
2026.09.26The run view's element ledger wraps its chips on a phone; the path label keeps its width.11 files · +395 −7 · site, tests, docs/privateIn depth-skim.html's element ledger at 360 to 480 px, .dl-page-stats was a nowrap flex item that could not shrink below its chips, and .dl-page-url was flex:1 with overflow hidden, so it took all the shrink; rows with more chips squeezed the path to 0 px and pushed the chips past the card. The chips now wrap under the name, which keeps min-width 6ch and the full path in a title. The particle script sets 1 density dial (1 to 2) for 3 ambient animations; the 3D map stays off it.// PR #120 — 1 commit · 2026.09.26
2026.09.24AART works in precomputed mode, prints data as text, and says what its data is.9 files · +1107 −415 · site, tests, config, docs/privatesite/rndlabs/aart/index.html (+927 −415): the drill-down link had put an unquoted asset ID into an onclick, Export looped a stub, "Load Precomputed" opened a file picker, every innerHTML sink interpolated dataset strings raw, the 5.6 MB bundle was fetched with cache: no-store, and all 9,473 report rows rendered before the gate was answered. Every control now works or is gone, every sink prints text, the bundle caches, the report draws 250 rows at a time, and the page names its source (NYC Parks AMPS) and its limits.// PR #119 — 1 commit · 2026.09.24
2026.09.24A directory listing kit under _private/listings/, never published.8 files · +265 −0 · docs/privateNothing visitor-facing: every file sits under _private/, which the publish boundary never serves. kit.md (210 lines) holds, copy-ready, the name, address, phone and description for Bing Places, Apple Business Connect and LinkedIn, the categories, each platform's steps, and 6 NAP mismatches flagged rather than chosen (the JSON-LD name "Relative Dynamics" against the footer's "Relative Dynamics LLC" among them); make-assets.cjs builds the 5 image assets beside it. The description lines are drafts for Jacob's voice. Known: whether any listing has been filed from the kit is not in the record.// PR #118 — 1 commit · 2026.09.24
2026.09.24Work left the nav; the door row moved to the footer; phone text floors at 12 px.17 files · +537 −36 · site, tests, docs/privateOn a 390 px phone the nav's first rail link was Work, gated and disabled; the hero carried a 6-link door row; 309 of 363 text blocks on the phone homepage were under 12 px. nav.js drops the Work entry to 1 commented gated line; index.html's door row moved to a static footer line of 5; a 12 px floor and 44 px touch targets ride a 480 px rule. Known: the bar still wraps to 2 rows from 861 to about 1070 px.// PR #117 — 1 commit · 2026.09.24
2026.09.234 faults from the visual pass: 2 pages wider than a phone, 3 throwing on load, 1 overlap.14 files · +920 −8 · site, tests, docs/privatedepth-skim.html laid out at 477 px on a 360 or 390 phone because .depth-input kept its intrinsic min-width beside the nowrap RUN button; the input now shrinks and under 480 px the row wraps. index.html stopped at 380 px because an unconditioned #orbital-canvas width rule sat after the phone rule and won; the order is fixed. about, services and privacy called drawMini before nav.js had injected #mini-logo, so the rest of the script died; the draw now waits. webp's footer Call link overlapped "Leave a review"; each link wraps whole.// PR #116 — 1 commit · 2026.09.23
2026.09.23BUILD_PLAN gained an OWED section: every call Jacob holds, 1 pinned line with its source.8 files · +260 −23 · tests, config, docs/privateProcess only; nothing a visitor sees changed. NOW had carried the open calls on 1 "also:" line, which held 6. BUILD_PLAN.md now has ## OWED between NOW and QUEUE, 1 line per call in the shape "- OWED · the call · src: path.md · since date", NOW is 1 line, and handoff.md appends every Jacob-decides line there; build-plan-shape-test.js pins the shape. Corrects: this PR's own handoff commit placed its 5 lines at the header's example line, splitting it above NOW; c4e2a88 moved them into the section.// PR #115 — 2 commits · 2026.09.23
2026.09.22The fit picks its yaw from the scene; only a moving hand releases it; the idle spin waits.8 files · +396 −13 · site, tests, docs/privateTape 2 (run 4ca67cc7): after the fit the site spanned 9.6% of a 1442×412 canvas because fitAll solved zoom and pan at the camera's yaw and the default yaw looks down the child rings end-on. depth-embed.js now tries every 15° and takes the yaw that frames largest; the site spans at least 40% of the width. The tape ended fit-released; the crawl path never writes fitted=false. A 0 px click no longer counts as a drag, a lost pointer no longer holds; which did it: inference, not evidence.// PR #114 — 1 commit · 2026.09.22
2026.09.22The topology fit dollies the camera back before framing; reset is the fit.10 files · +681 −64 · site, tests, docs/privateTape 1 (run 68861829): the /media child ring cut by the canvas bottom at every zoom, the top third empty, a child pit never in frame, and 6 ring labels colliding. fitAllZoom had measured only site towers and solved zoom alone, with the camera at a literal 220, so a far formation sat behind the near plane; fitAll now backs camDist off until nothing drawn is culled, then frames every tower, ring arc, pit, twin and label rect, and reset is the same fit at the default angle.// PR #113 — 1 commit · 2026.09.22
2026.09.21Site SEO: titles and descriptions in range, 1 JSON-LD graph, a door row, staging noindex.20 files · +827 −94 · site, tests, config, docs/privateThe instrument's own SEO pass over the 7 public pages read 9 passes: 3 titles about 25 characters, descriptions from 68 to 229, an empty static h1 on tools.html, a bare LocalBusiness with no telephone, and a sitemap listing a URL that 302s. #110 fixed each, added a 5-door row under the hero, a "Leave a review" link in the footer, and staging noindex in netlify.toml. #112: the other firm is never named in visible copy. Known: the parser reads a description only to its first apostrophe.// PR #110, #112 — 5 commits · 2026.09.21
2026.09.20The visual read's prompt names the capture viewport and encode scale; boxes return to px.12 files · +445 −38 · site, functions, tests, docs/privatevisual-core.js built its dimensions from the encoded still: the worker shrinks a still to its byte budget and records the encoded width beside scale, so the prompt called a 180 px image a 360 px viewport and the workbook labelled the model's box "mobile-min px"; at scale 0.5 every exported box was half its size and place. The prompt now states the viewport, the scale and the image's own pixels; a box returns to viewport px once. ai-error.js: an image past 8000 px is no longer "the model refused".// PR #109 — 1 commit · 2026.09.20
2026.09.181 pit per bleeding formation, in its own void sector; no bleed, no pit.6 files · +228 −32 · site, tests, docs/privatedepth-embed.js: the red pit that dead links drain to had been 1, in the void beyond the whole site. Each formation that carries a bleeding pylon now gets its own pit in its own stretch of void, placed outward and clear of every ring and twin; a formation with no dead links gets no pit, so a clean site draws none and the pit count reads as the count of bleeding regions. The main pit keeps its label, child pits draw smaller in the same red.// PR #102 — 1 commit · 2026.09.18
2026.09.18The topology rebuilt as the balloon layout, rings by depth; the first cut collapsed.31 files · +3407 −533 · site, functions, tests, docs/private#94 replaces the force layout with rings by structural depth, anchors tethered to their copies, spurs and sampled-family vertices; the trie view is retired. #95 (run 9a6a819): the completion repaint had collapsed the balloon to 1 polygon because the layout keyed families by a name the crawl never writes and the fixture declared the same name; a family now folds only when it is a flat cluster. #99: the home on the ring, chrome edges once, gears sized by √teeth, backend twins per formation.// PR #93–#101 — 12 commits · 2026.09.16–18
2026.09.16Render capture: stills, boxes and video on keyed runs; the camera off the render slot.38 files · +4367 −102 · site, functions, tests, build scripts, config, docs/private#83: on a keyed, gate-allowed run the render worker takes full-page stills at phone and desktop widths, records element boxes and a scroll video, behind signed URLs with a retire-by. #85: the dial defaults OFF, and a camera miss no longer darkens the renderer. #86: the slot renders and the camera rides beside it on an encode queue the crawl polls; capture-proxy.js serves the bytes. #89: Haiku triage of the still, dial off. #92: the snapshot is always taken at 1280×900, and the record says so.// PR #83–#92 — 13 commits · 2026.09.16
2026.09.15Every model road debits the meter; the provider figure is read in cents, its shape echoed.18 files · +742 −72 · site, functions, tests#78: the console showed $10.09 for the month and the inside meter $3.80, because only 3 of 8 model roads debited a run; every road now debits its run or a named month bucket, and ai-error.js turns a model refusal into a plain line and a ping. #79: meter.js summed a field the cost report does not carry, so the provider read 0 and the drift check said "within range"; it now walks buckets, results and amount, and echoes the shape beside the figure. #81: the amount is cents.// PR #78–#81 — 4 commits · 2026.09.15
2026.09.15Images are weighed at the seo close; a WebP converter page runs in the browser.15 files · +1948 −48 · site, functions, tests, config#74: skim-core/checks/images.js arrived; deep-crawl.js sends 1 HEAD per unique image at the close, robots.txt honoured on the site and on image hosts, 8 s each, and the finding reads "N images over 500 KB — X MB total" with the heaviest 5 and site chrome counted once; a failed HEAD reads "not reachable this run" and never counts; the threshold is a dial. #75 adds oversize-for-slot with the ratio stated, a per-page budget and the LCP image ranked first. #73: site/webp.html converts images to WebP client-side, nothing uploaded.// PR #73–#75 — 3 commits · 2026.09.15
2026.09.14A content gate at l1: 1 Haiku read of the homepage; a refusal names no category.10 files · +807 −28 · site, functions, tests, docs/privategate-core.js, gate-review.js and skim-core/content-gate.js arrived; deep-crawl.js calls the gate once per public run. The run is refused for exactly: sexual or adult content, hostility to visitors, hate or extremist material, illegal goods, scams, malware, any child-exploitation signal; regulated-but-legal, fiction violence and political sites are allowed. A thin static read is never a verdict: the gate re-runs once on the rendered homepage. The refusal offers 1 "refused in error" button, 1 per run; the admin key overrides, logged; scraped content is data in the prompt.// PR #69 — 1 commit · 2026.09.14
2026.09.14The vault runs ledger gained a sortable header row and a gate badge; abandoned reads so.6 files · +322 −22 · site, functions, tests#70: vault.html's runs list has a header row (date, tier, domain, pages, spend, status, gate); tapping a header sorts by that column and tapping again reverses, newest first by default, the choice kept in sessionStorage; allow rows wear a quiet "gate ✓" so a gate that ran is told from 1 that never did. #71 is the row below: abandonment measured from the last activity, with a 1-time sweep for the rows stuck as running. Corrects: the 09-05 entry claiming the abandoned rule already worked.// PR #70, #71 — 2 commits · 2026.09.14
2026.09.14The mint line counts the pages the report counts, and says what else the node holds.3 files · +59 −4 · site, functions, testsRun 151b2d4a: the mint line read "30 pages banked" where the report read 27. #49's report model had removed not-found routes from the Pages surface and the crawled count, but deep-crawl.js writes every graded route into the pages node (notFound: true with "answered 404", or the older "http-404" marker) and skim-invite.js's bundle check counted every key. The check now reads the same shape as the report and the line says "27 pages banked + 3 not-found routes"; a node holding only not-found routes reads "missing: page records" (invite-test.js).// PR #68 — 1 commit · 2026.09.14
2026.09.14Abandoned runs read abandoned; the 09-05 rule had compared a string and never fired.5 files · +155 −18 · site, functions, testsruns-ledger.js derived abandoned as Date.now() minus startedAt past 15 minutes, but l1 indexed startedAt as an ISO string, so the subtraction gave NaN and every unfinished run read "running"; 2 rows sat that way for 9 days. skim-store.js gained toMs; deep-crawl.js indexes a number and stamps meta.lastSeenAt on every slice; abandonment is measured from the last activity, so a silent run reads "abandoned · last seen" with the time; a keyed 1-time sweep stamps the rows already stuck. Corrects: the 09-05 entry claimed the rule worked.// PR #71 — 1 commit · 2026.09.14 · corrects the 09.05 entry
2026.09.13The mint's bundle check reads every PSI landing shape; a bank never erases a landed score.6 files · +411 −75 · site, functions, tests, docs/privateThe mint said "incomplete — missing: PSI raw" while the report carried Lighthouse 42/100: the check read the l1 slot only. #61 accepts the background landing in the perf node; #62 accepts the client retry's split shape, a perf flag plus its own psiraw node; #63 makes every road land PSI the same way, makes a bank carrying no PSI leave the living landing alone, and names every node read when the check still finds nothing. Corrects: the first 2 rounds mocked store states, passed, and missed live.// PR #61–#64 — 4 commits · 2026.09.13
2026.09.13Page reads run in batches of 7; the batch call moved to a background function.4 files · +671 −90 · site, functions, testsA 27-page run had issued 27 per-page Haiku calls, most of the prompt the same chrome 27 times. #58: above 5 readable pages, depth-skim.html plans batches (7 a batch, a dial), sends the chrome once with "appears on 27 pages" receipts, and analyze-site.js picks the model by tier. #59 turned the dial off after run 8e3693b5: 2 of 4 batches overran the 26 s function window and 14 of 27 pages came back unread. #60 moved the call to ai-batch-background.js, with 15 minutes of room.// PR #58–#60 — 5 commits · 2026.09.13
2026.09.13A capped list is never the count: findings state the measured number beside the sample.4 files · +111 −19 · functions, testsRun 3544692d: 27 pages shared 1 malformed chrome link and 1 dead-link target; the finding's list is capped at 10, the finding printed the list's length as the count, and the model was handed the list and counted it too, so a resolution said "on 10 pages". seo.js and deep-crawl.js now state the measured count and declare the sample ("appears on 27 page(s); the list below is a sample of 10"), and resolve-item.js tells the model to read the stated count instead of counting (riverwind-findings-test.js, facet #9, a 27-page estate).// PR #57 — 1 commit · 2026.09.13
2026.09.13A Lighthouse miss carries its real reason and pings; the 40 s call runs in the background.8 files · +475 −35 · functions, testsRuns 3544692d and 98b7aa91: 1 Performance sheet read only "not measured this run" and the other guessed "may have been rate-limited", though psi.js had returned the code and call count since 09-03; the performance.run callers dropped them and the l1 ping excluded well-dry. #55: performance.js's notReachedWhy builds 1 reason line for the channel and the export, and every miss pings with the run and the reason. #56: psi-refresh-background.js takes the call that can run 40 s past the function's 26, charging the psi well like l1.// PR #55, #56 — 3 commits · 2026.09.13
2026.09.13A data-acquisition section and a register addendum added to CLAUDE.md.1 files · +50 −0 · docs/privateProcess only: CLAUDE.md gained 50 lines and no code moved. The section states what the audit may do to learn about a site: official interfaces and roles a client grants come first; where a platform's terms forbid automated logged-in access the answer is no; the crawler names itself, honours robots.txt past the front door and resolves outbound links instead of crawling them; a pull that fails is "not reachable this run", never a finding about the site. The addendum names the public product "website audit".// PR #50 — 1 commit · 2026.09.13
2026.09.13The report model: menu openers are not pages, a 404 is authoritative, chrome counts once.7 files · +1105 −197 · site, functions, tests8 PRs from riverwindchurch.org runs. parse.js marks a nav anchor with a nested list as a menu parent, so an opener that 404s is noted, not a failed page; a rescued empty shell never aliases; quoted hrefs are stripped (#45). deep-crawl.js fingerprints each site's not-found page once (#47), a static 404 stays authoritative (#48), status is per element (#49), the drawer's copy of a nav anchor is the same anchor (#51), a malformed href is a real broken link (#52), and Dead? counts unique elements, chrome once (#53).// PR #45, #47–#49, #51–#54 — 8 commits · 2026.09.07–13
2026.09.072 stale structured-data expectations in the harness retired; the validator had moved them.1 files · +9 −2 · testsskim-core/harness.js: 2 checks in section F12 had expected structured-data at tier partial and sd-validation at unmeasured. Bisected to b72da7f (2026-08-23), which shipped the local JSON-LD validator (parse errors, the schema.org @context, required properties) and moved both to measured, with sd-validation a real finding even when a page carries no JSON-LD. The tests were wrong, not the code: both expectations now read measured, with the walk written beside them so the next red is bisected rather than guessed. 1 file, +9 −2, tests only; nothing a visitor sees changed.// PR #46 — 1 commit · 2026.09.07
2026.09.06A keyed meter page: the month's metered spend beside the providers' own numbers.7 files · +570 −52 · site, functions, tests, docs/privatemeter.js arrived with 2 halves behind the keyed password. Inside: the month's spend summed live from the runs the ledger already reads, split by tier and by resolve scope, beside today's well burn per tool, with 0 outbound calls. Providers, on a button press: Anthropic's month-to-date cost, the Netlify sites and a flat infra dial, each beside the instrument's own number with the delta, cached 10 minutes. #38: the Anthropic call answered 403, so the panel shows "Missing permissions" and the drift line reads "unknown", never "within range".// PR #37, #38 — 2 commits · 2026.09.06
2026.09.06Map keys are percent-encoded at the store boundary; the database had refused dotted keys.6 files · +210 −23 · site, functions, tests, docs/privatePublic runs were refused on their second write. The database rejects any node whose map keys carry a dot, slash or bracket, and the maps are keyed by exactly those: connected.external by registrable domain, the checkpoint's hosts by hostname, raw PSI audits by path; the first write passes because the maps are empty. skim-store.js now encodes every key on write and decodes on read, and a refused write's REST error body rides the rail ping. Corrects: #35 read it as a write-once rule, changed nothing, and was withdrawn.// PR #36 — 1 commit · 2026.09.06 · supersedes the withdrawn #35
2026.09.05A runs ledger behind the keyed door: 1 index line per run, spend read live, OPEN by token.8 files · +597 −15 · site, functions, tests, docs/private#30: at l1 every run writes runs-index/<yyyy-mm>/<runId>; the seo close patches pageCount, the verdict and completedAt, a failure patches failedAt and the reason; spend is never copied, runs-ledger.js reads it live from each run's meta and mints an admin token on OPEN. #34: rows wrap at 380 px, 1 keyed password feeds all 3 panels in memory only, and a store write returning false pings the rail with the path. Known: the index path moved under skim/ on a wrong guess.// PR #30, #34 — 2 commits · 2026.09.05
2026.09.056 production findings: every tier banks its board, public chat answers, leads captured.12 files · +437 −46 · site, functions, tests, docs/privatePublic boards were never banked, so an admin open fell to a replay that cannot rebuild the speed numbers; depth-skim.html now banks every run. Public chat was refused before the model and showed "answer lost"; resolve-item.js answers the free tier's 3 follow-ups on haiku, metered by the public resolve well. lead-request.js arrived: a public visitor asks for 1 text with the assessment link, stored once per run, a filled honeypot dropped, the rail pinged with the admin link and no digit of the number.// PR #32 — 1 commit · 2026.09.05
2026.09.05An ntfy rail pings each public run and failed call; the silence was an un-awaited fetch.12 files · +832 −51 · site, functions, tests, docs/private#28: notify.js arrived, 1 helper posting to ntfy.sh with a 3 s timeout and a rate limit per event kind, so a storm collapses into 1 ping; deep-crawl.js pings every public run at seo close with the domain, the verdict and a keyed-view link on a 7-day admin token, and every failed call pings with the function and the run. Nothing arrived: the pings were fired without await, and a serverless container freezes on return. #29 awaits the post and makes the run a lifecycle: started, failed, completed.// PR #28, #29 — 2 commits · 2026.09.05
2026.09.05A minted link reads performance, resolves, chat and sources live; findings stay frozen.5 files · +254 −5 · site, functions, tests, docs/privateRun 7d511ef4: the keyed export at 11:59 PM had the Performance sheet, a follow-up thread and a Source Files sheet; the minted export 2 minutes later had none of the 3, because the minted open read the board banked at mint time and merged the store only where the snapshot lacked a node. skim-run-notes.js now banks sources as its own node and re-banks the perf node when a PSI retry lands; generate-report.js merges store over snapshot for performance, resolves, chat and sources, while the other findings stay frozen.// PR #27 — 1 commit · 2026.09.05
2026.09.05A 3-turn follow-up chat under each finding, capped on the server, stored in 2 steps.6 files · +891 −56 · site, functions, tests, docs/private#25: resolve-item.js gained chat: up to 3 exchanges per finding, the cap enforced on the server whatever the page sends, answers grounded in the run's own report, an off-scope question answered with 1 canonical refusal, each turn metered. #26 fixed 5 things from the first minted runs: the resolve sheet could not scroll to the newest answer on a phone; the first off-scope question is free; the question is stored before the model call, so a lost reply leaves the question with "answer lost", not a gap.// PR #25, #26 — 2 commits · 2026.09.05
2026.09.04An admin config panel in the vault renders every dial through skim-config's 1 door.5 files · +406 −4 · site, functions, tests, docs/privatevault.html gained the panel behind the keyed password: _cfgRows walks everything skim-config's read path returns (well caps per tool, the mint dials, the tiers map) and each row shows the value in force, the code default and whether an override is set, with a RESET control. 1 SAVE posts the whole set through skim-config.js's existing validation; a refused write shows the server's reason and changes nothing on screen; skim-config.js learned to take null, so a reset clears the override. The honesty thresholds are not dials and never render.// PR #24 — 1 commit · 2026.09.04
2026.09.04Resolve tiers by scope: single, bundle, site and chat each dial their own model.9 files · +217 −32 · site, functions, tests, docs/privatewell-core.js: mint.defaultTier became the map mint.tiers { single, bundle, site, chat }, each opus, sonnet or haiku, defaults haiku, sonnet, opus and sonnet, the constants as floor, validated whole-or-nothing in skim-config.js; a stored defaultTier migrates to tiers.site and a write of the old key is refused with the rename named. resolve-item.js reads each path's tier from the map, so the single tap's fixed sonnet now defaults to haiku, 1 config write back; every reply and stored record carries the tier and generate-report.js names the model per read.// PR #23 — 1 commit · 2026.09.04
2026.09.04A funded token runs new sites from its balance; the per-run fee is charged on delivery.11 files · +521 −40 · site, functions, tests, docs/private#20: the minted view and the vault carry a domain box that runs any site through the keyed path, metered against the token's balance and never a well; the new run's meta points at the wallet, so debitRun and overBudget read it 1 hop away; an over-balance run is refused before the crawl, the balance named. #21: newRunCents, a per-run fee charged at l1. #22: charged at the door, a dead site still billed and a retry billed twice; the fee now lands once a homepage is stored.// PR #20–#22 — 3 commits · 2026.09.04
2026.09.04Resolve All — Site: 1 dialed call for every unresolved finding; 1 row renderer per paint.13 files · +936 −140 · site, functions, tests, docs/private#16: performance findings that landed late rendered without resolve buttons because _applyPerfResult kept a private copy of the row markup; _findingRowHtml is now the 1 renderer for first paint and repaint, and the PSI outcome is stamped on run meta. #17: resolve-item.js gained siteResolve, 1 call across every channel walled by the run's budget and tier, fanning answers into the per-finding records, nothing re-bought; generate-report.js leads the workbook with a Resolutions sheet, every finding in ranking order with its read or its reason. #19: the notAFix gate skips the spend.// PR #16, #17, #19 — 3 commits · 2026.09.04
2026.09.04Finding cards wrap on a phone; a long URL is shown short with the whole in the tooltip.7 files · +257 −28 · site, functions, testsA mobile keyed run of professionaltransportationinc.com: a detail's "\n" rendered as a space, a 200-character calendar URL could not wrap, the card widened past the viewport and the resolve panel sat off-screen. depth-skim.html: _detailHtml renders 1 element per line and truncates a displayed URL to about 80 characters with the full URL in title; .rdb-row carries min-width:0 and overflow-wrap:anywhere; context rows offer no fix. #18: the first wrap rule on the whole row had collapsed the evidence blocks; containment is scoped to the text, captions wrap, bytes scroll.// PR #15, #18 — 2 commits · 2026.09.04
2026.09.03The mint dials moved into config; a request above the ceiling is refused by name.10 files · +278 −37 · site, functions, tests, docs/privateskim-config.js's reserved mint key is filled: defaultBudgetCents, defaultDays, defaultTier, ceilingCents and maxDays live beside the well caps, the code constants (300¢, 7 days, ceiling 1000¢, 30 days) their floor, validated whole-or-nothing with the read path answering effective against default. skim-invite.js refuses a budget or day count above the ceiling with the limit named, never a silent clamp, and answers a dials read for the 2 mint UIs, so the placeholders in depth-skim.html and vault.html are the numbers in force (mint-dials-test.js). Raising a limit is a config write, not a deploy.// PR #14 — 1 commit · 2026.09.03
2026.09.03The 50-page budget is the only stop; external links resolve 1 hop and are never crawled.10 files · +371 −82 · site, functions, tests, docs/privatefrontier.js: the depth gate is off by default (maxDepth 0), the walk is breadth-first, and the board and export declare why it ended: budget spent, site exhausted, or a depth gate when 1 is set. External domains (up to 6) register for 1-hop resolution: fetched once through their redirects, classified (own property, service, social, parked, dead, shell), never queued and never counted against the 50; maxForeignPages is retired. #12 rewrote depth-skim.html's fine print to match: 50 pages, externals resolved not crawled, in place of "three layers deep · seventeen pages".// PR #12, #13 — 2 commits · 2026.09.03
2026.09.03l1 stores its rich homepage; snapshots load in crawl order; AI reads join by URL.7 files · +413 −23 · site, functions, testsRuns 07402c6b and 5d595f8b: the minted board's first card was /privacy.html with no "/" card, and /privacy.html carried the homepage's AI reads. l1 never wrote its rich homepage record, so the reconcile stored the client's slim copy and the snapshot loaded in store-key order, and reads were joined to pages by position. deep-crawl.js writes the full l1 record with a crawl-order number; skim-run-notes.js stores reads by URL and _joinAiReads attaches them by URL. #11 stops a remint re-running the paid pass.// PR #10, #11 — 2 commits · 2026.09.03
2026.09.03Public Lighthouse on its own well; a config node for the caps; the page pass minted.11 files · +550 −22 · site, functions, tests, docs/privateperf-only.js serves public callers: each Google call burns the new 'psi' well (cap 100 a day) and a dry well answers well_dry, never 401; psi.js reports the failure code and call count, so a 429 quota refusal and a timeout are no longer the same stored record. skim-config.js arrived: 1 admin-written, rate-limited record governs the well caps, the code's constants its floor. mintFromBoard runs the page pass when a run has none stored. Known: the public speed misses were Google's quota (429, 10 of 10).// PR #9 — 1 commit · 2026.09.03
2026.09.033 hotfixes: the dead public path refunded, the silent board bank, a same-day expiry.10 files · +551 −50 · site, functions, tests#6: public-skim.js's phase whitelist predated the frontier, so 'crawl' and 'resume' fell into the fresh-visit branch and burned the well again; every unkeyed run died and 3 failures took the maps well from 25 to 21. The phases pass through; well-core.js refunds a failed run in the invocation that burned. #7: psiRaw, megabytes of screenshots, rode inside the board put and killed it; it is its own node now. #8: an 11:09 PM mint read "expires 9/3"; a days value that is not positive takes the 7-day default.// PR #6–#8 — 3 commits · 2026.09.03
2026.09.03A minted board holds every channel the keyed board had; unknown is never a finding.7 files · +429 −22 · site, functions, tests, docs/privateRun 8ce80eda showed the keyed board with score cards and 4 channels, and the minted open of the same run with SEO and coverage only, plus false "No robots.txt" and "No sitemap.xml" findings: the courtesy open fell to the seo replay, which coerced an unknown probe state to absent. deep-crawl.js now reads an unprobed state as "not checked"; mint freezes the digest into the banked board, the invite path renders the same accordions and cards, and skim-invite.js pumps an AI read for every finding before the token exists.// PR #4, #5 — 2 commits · 2026.09.03
2026.09.02A minted run's stored pages now include the homepage; records are keyed by URL hash.2 files · +134 −2 · functions, testsdeep-crawl.js: run b77bc914 showed the keyed board with "/" and the minted board with 10 records and no "/", because the pages node was written only by crawl-slice checkpoints under collision-capable p{size}_{i} keys, l1 stored only meta, and the seo close received the client's full set and stored none of it. The close now reads the stored pages, diffs by normalised URL and patches in only the missing ones, awaited, a slim client record never overwriting a rich one; slice records are keyed by the URL's fnv1a hash (reconcile-test.js).// PR #3 — 1 commit · 2026.09.02
2026.09.02Staging reset to main; the knowledge kit, the house commands and the first tombstone.23 files · +1186 −10 · site, functions, tests, config, docs/privatePR #2 (3 commits): f1fd9bf added CLAUDE.md, CONTEXT.md, _private/rd/DOCTRINE.md, 4 bones and 7 commands under .claude/commands/ (ship, tombstone, ledger, register-check, mint-audit, staging-reset, history-walk) with the raw history walk; 1838544 unified the footer address to Newburgh on 3 pages; 8506a3b removed the doubled wellCore.bindBlobs(event) at 4 call sites (pasted twice on 07-28, idempotent, so it hid for a month), with bindblobs-test.js pinning 1 call per handler. The reset of staging to main was a git operation, its old tip kept as the tag staging-july-2026.// PR #2 — 1 commit · 2026.09.02 · staging reset preserved as tag staging-july-2026
2026.08.31The commit history audited, 185 commits walked diff by diff; the upload courier retired.Process only: no commit holds the audit, and the walk is filed as a private note. 185 commits from 2026-05-21 to 08-28 were read 1 at a time; 23 were flagged, every flag the upload workflow itself: empty commits, and a working set dropped at the repo root at 01:43 on 08-28 (35 files at the wrong paths, put back 1 deletion at a time over 17 minutes), no logic error among them. The courier is retired: the repository lives on a real machine and commits carry real messages.// record — 185 commits audited · 2026-05-21 → 08-28 · flags #64 #108 #139 #144 #182
2026.08.28Page records are awaited outright; only the checkpoint rides a clock; resume has 3 legs.3 files · +124 −24 · site, functionsdeep-crawl.js: page records and the 100 KB checkpoint had shared 1 write race of 2 s, and run cbddb818 lost 8 of 42 pages to it. rs.patch('pages') is now awaited, the checkpoint alone races a clock of 2 s (4 s on the last slice), and a slim seoState is written once when a run finishes; the resume phase tries checkpoint, then seoState, then pages-only before a 404 that names which records existed. skim-run-notes.js stores the finished board so a courtesy preload opens the banked board.// record #184–#185 — 2 commits · one night
2026.08.28Courtesy links: /scan/<site>/<token> minted, redeemed, read at the edge, expiring.16 files · +832 −51 · site, functions, edge functions, tests, configskim-invite.js mints an 18-hex token bound to a run (password-gated, its budget stacked on the prep spend) and redeems it, answering expired past its date; scan-invite-page.js serves the share card with the client's domain for a valid token and the public pitch for an unknown one, never a 404; scan-door.js reads a token riding the path so it is never taken for the target. resolve-walkthrough.js answers a budgeted run without a password and replays from the store; the checks attach evidence as received; vault.html gained the mint panel.// record #138 · #183 — 2 commits · same night
2026.08.28The vault admin knock re-bound to the shared nav logo, null-guarded, plus #admin.1 files · +41 −21 · sitevault.html: the 5-click knock had listened on #nav-logo, which a nav rework deleted; the null addEventListener threw and took every admin binding below it down. bindAdminKnock now targets #mini-logo, the mark nav.js injects on every page, retries for 5 s on slow loads, and every binding is null-guarded so a missing element cannot kill the login wiring; #admin in the URL opens the login directly, a fallback no rework can remove, because the password check is server-side and the knock was never the security.// record #140 — 1 commit · 1:24 AM
2026.08.26–27Unreachable is not broken; the frontier crawl, the run store and the digest arrived.21 files · +2286 −181 · site, functions, tests, docs/privatedeep-crawl.js now drives the crawl from skim-core/frontier.js in slices sized to the function clock: a sister domain is mapped, not graded, under its own robots.txt and crawl-delay, a third domain is never chained, and a connected-properties finding names the sister. skim-store.js and skim-overview.js arrived with a runId and a resume phase; digest.js ranks the summary; a host's rate limit and a dropped socket are no longer findings about the site; sampling is declared in every output; per-page automation rides Haiku on every tier.// record #130–#137 — 8 commits · 2 days
2026.08.24Rollups count only what rows prove; a report-only CSP; JSON-LD and expiry measured.13 files · +390 −197 · site, functions, tests, config, docs/privatemaze-core/rollup.mjs dropped the stitching: the 8/22 export showed the edge's hop counter resets across nodes (33k "hits:1" rows from 196 IPs), so stitched sources were invented; a day is now source, partial or untagged, sums trust only fully-tagged days, and uaFamily names the crawler per row. exhibit.html shows 1 stat per line with its definition. maze-signals.js returns when navigator.webdriver is set, so the site's own Skimmer is seen, not counted. site/_headers gained a report-only CSP. seo.js validates JSON-LD locally; expiry.js climbs aggregator, RDAP and WHOIS and names the rung.// record #125–#129 — 5 commits · 08.22 evening → 08.24
2026.08.22Maze events carry a daily-salted source token; the ledger has 1 recount path, not 2.13 files · +519 −120 · site, functions, edge functions, docs/privatemaze.js stamps each event with chain, the first 12 characters of the daily-salted token, never an address; without it every counter had fallen back to path, so the feed counted hops as visitors and the ledger counted path prefixes. maze-backfill-background.mjs walks the whole archive once and installs a v3 ledger by compare-and-swap; maze-drain.mjs lost 97 lines of its own recount. maze-core/rollup.mjs, maze-daily.mjs and maze-rollup-background.mjs add per-day rollups (this first cut stitched untagged rows into sources; the 08-24 row removes that). Known: the totals shown were mid-correction when this shipped.// record #117–#124 — 8 commits · one night, 23:38 → 11:14
2026.08.21X-Frame-Options to SAMEORIGIN; the exhibit keeps lifetime totals past the feed trim.6 files · +312 −80 · site, functions, configsite/_headers: DENY became SAMEORIGIN, because privacy.html frames the exhibit and DENY had the browser refuse the site's own page inside itself; external framing stays blocked. maze-drain.mjs gained updateLifetime: events and distinct chains accumulate in a ledger that survives the feed trim, backfilled once from the 365-day archive, with a v2 migration that counts the human archive in; FEED_KEEP rose from 2000 to 8000 after the 8/21 storm had compressed the feed's memory to about 30 minutes. maze-lifetime.mjs serves the ledger and exhibit.html prints ALL TIME with its since date.// record #112–#116 — 5 commits · one evening
2026.08.20A page that fails to load is reported as not retrieved, with the reason, never as empty.7 files · +274 −38 · site, functions, testsdeep-crawl.js: fetchPageStatic records a failReason (timeout, conn, http-status, soft-block-200) and retries a non-shield failure once at 20 s; a failed fetch digests with seo:null and 0 elements, so seo.js leaves it out of every denominator and names it in a pages-unretrieved finding. Launches are staggered 300 ms apart, and a post-retry failure spends a render as the last rung, with enrichment renders waiting 4 s so rescues reach the worker first. site/404.html added. Corrects: "no title present" had been written about pages nobody read.// record #103–#110 — 8 commits · one evening, 18:50 → 22:47
2026.08.20Surface Skim redirected to Depth Skim behind a banner; /scan/<site> opens prefilled.4 files · +263 −7 · site, edge functions, tests, confignetlify.toml 302s /surface-skim and /surface-skim.html to /depth-skim?from=surface (forced, so the old file is shadowed, not deleted) and /scan/* to /depth-skim?scan=:splat. depth-skim.html shows a maintenance banner only behind the surface door, reads the target from the path, and makes the first press open the attestation sheet with no input pre-checked; the guided walk runs for scan-door arrivals only and retires on first touch. scan-door.js, an edge function on /scan/*, rewrites the title and og: tags around the escaped target; the canonical stays /depth-skim.// record #98–#102 — 5 commits
2026.08.20The share card, favicons, security headers, a sitemap and canonicals on every page.19 files · +209 −4 · site, config432bac9 added site/_headers (X-Frame-Options DENY, nosniff, a referrer policy; no CSP yet, by the note in the file), sitemap.xml, 2 robots.txt lines, and a description and canonical link on each of 10 pages; 322bdd0 added og-card.jpg (1200×630, 165 KB); e514ef9 gave 13 pages the 3 icon links (SVG, ICO, touch icon) and the og: and twitter:card tags; 98a9808 added .well-known/security.txt. The morning self-skim had found the gaps these close: missing headers, no sitemap, bare canonicals, a title collision, no share card. Known: 2 flags were left standing by choice.// record #94–#97 — 4 commits · morning skim → evening deploys
2026.08.19A resolve button on every non-pass finding, and robots.txt read from 1 derivation.8 files · +510 −24 · site, functions, testsresolve-item.js arrived (138 lines): a tap sends the finding and the run's own evidence to Sonnet with the leash in the prompt and burns the resolve well (cap 12 a day) on public taps. depth-skim.html renders the answer as text under a fixed disclaimer, caches per run, caps public taps at 5, and runs its automatic pass on Haiku. crawl-guards.js gained describeRobots: seo.js, deep-crawl.js and generate-report.js read that 1 derivation, and the report prints the robots file rule by rule. Corrects: 2 sheets had disagreed about 1 robots file.// record #91–#93 — 3 commits
2026.08.01Email and expiry posture checks, a 6th confidence label, and a timer-free phone cockpit.8 files · +484 −19 · site, functions, testsskim-core/checks/email.js and expiry.js arrived; deep-crawl.js runs both (runPosture) in both lanes and merges them into the security channel, where expiry's measured cert finding supersedes the stub, and rawSeo now records whether robots.txt and the sitemap were probed. generate-report.js added "handler present · not invoked this run" beside the 5 confidence labels. depth-skim.html: the facts feed ticks on computed facts with no timers, clean pages print nothing, an end-of-crawl headline, the cockpit folded behind 1 toggle under 700 px. nav.js hides the EZ chip on the phone rail.// dated by the record · #85–#90 — 6 commits · one day
2026.07.3018 commits in 1 day: URL identity, robots on the walk, an honest UA, shields.21 files · +1988 −374 · site, functions, tests, docs/privateurl.js made 1 URL-identity rule, so a page is counted once and the render budget spends by identity. crawl-guards.js arrived: robots.txt honoured on every enqueued path with skips reported, fnv1a aliasing, and detectShield, so the tool's own page about bot walls no longer reads as 1. The spoofed Chrome UA became RD-DepthSkim/1.0. 839432f added orchestrated phases with continuation tokens, public-skim.js burning the well once, and removed depth-skim.html's fake phase timers. a22f76f cut 103 lines from deep-crawl.js; d098288 restored them 6 minutes later.// record #68–#89 — 22 commits · one day
2026.07.30The render-worker bridge, button probes and the escalation rule reached the crawler.17 files · +796 −118 · site, functions, testsrender-client.js arrived as the bridge from the functions to the render worker: it never throws, a budget caps renders, and a down worker leaves the static HTML in place. escalate.js decides which pages get a render (a hollow SPA shell does, a static small-business page never does), with escalate-test.js and escalation-seam-test.js against a mock worker. verify.js merges the worker's per-button probe verdicts into the parsed elements, and an unmarked "#" on a JS page now reads unverified, not dead. The same day's other 18 commits are the row below.// dated by the record · #68–#84 — same day as the entry above, told from the machinery's side
2026.07.28The site moved under site/, the open root was closed, and the well and skim-core arrived.126 files · +37722 −15707 · site, functions, edge functions, tests, config, docs/private33 delete commits (13:26–13:30) removed every page, script, note and the 14.5 MB build zip from the repo root. bb86c3c then added netlify/ (31 function and edge files, public-skim.js, perf-only.js, well-core.js and well-status.js among them), skim-core/ (parse.js, psi.js, 3 checks, a harness and 3 tests), recon-core/ and a netlify.toml with publish = "site"; 793b2b1 added site/ (the pages, scripts and 6 self-hosted fonts) and _private/ (the notes and harnesses). 1b44260, 8cdaa44 and 4995086 polished 5 functions and 7 pages. Only site/ is published from this day.// what the one-liner held: record #29–#66 — 38 commits · one afternoon, most inside four minutes. 35 legacy files retired in one sweep, the modular skim engine and the metered well arrive, and — the structural fix the record demanded — a real publish boundary. Only site/ is served from this day; notes, harnesses, and machinery live behind it by construction. The era of the open root ends here.
2026.07.24Self-hosted fonts and a rebuilt front page, landed inside the 07-28 sweep.No commit of its own: the 6 woff2 files under site/fonts/ (5 Rajdhani weights and Share Tech Mono) and the rebuilt index.html reached main inside the 07-28 sweep and are counted there. The pass held: fonts self-hosted so the first paint no longer flashes, the hazard tape retired, the portfolio rebuilt as Built & Running, the contact intake and a live Depth Skim moved to the front page, the wells as per-tool token gauges with global counters only, and the Markov blanket restored after a nav refactor had nulled it.// the record places this work inside the 07.28 sweep to main (record #29–#63); built in the days before, landed with it
2026.07.09The Maze edge function landed; the revert of an accidental push removed only its wiring.34 files · +1325 −14357 · site, functions, edge functions, config00cb982 added netlify/edge-functions/maze.js (457 lines) with asn-ranges.mjs, maze-core/ (classify, sign-origin, store), maze-drain, maze-export, maze-rtdb and the forge-* functions; 7c218ab added maze-signal.mjs and site-skim.mjs. 74c9d60, "Reverting main, accidentally pushed to main", removed 157 lines from 12 files: the maze and hub blocks of netlify.toml and the page links. Every new file stayed, unwired, until the 07-28 sweep. 26ad810 deleted rndlabs/ again (14156 lines). Known: the repo root was the site root until 07-28, so the notes and a build zip at the root were publicly fetchable.// record #17–#27 — 11 commits · one afternoon, 13:02 → 17:12 · flags #14 #16 #28
2026.07.09Telemetry v2 and the exhibit page, with the privacy page rewritten in the same commit.22 files · +1687 −108 · site, functions, tests, configdc731a5 added exhibit.html (363 lines), maze-signals.js (68), firebase-rtdb-rules.json, robots.txt (12 lines, 5 Disallow lines) and tools.html, rewrote depth-embed.js (+221) and privacy.html (+46), and gave netlify.toml the maze note, the hub redirects and the forge timeouts; 3560f8c added the live exhibit frame to privacy.html and the feed URL to exhibit.html. maze-signals.js and privacy.html say it: no cookies, no stored IP, writes batched in edge memory, a lost batch accepted by design. The privacy page moved in the same commit as the telemetry, as the covenant requires.// dated by the record · #17–#24 — 8 commits
2026.07.09The rndlabs pages landed twice: added, deleted 1 minute later, added again.6 files · +28271 −14115 · site1d33568 (13:06) added rndlabs/aart/index.html (6441 lines), rndlabs/lt64/index.html (6036), rndlabs/tools/convert, rndlabs/wildspeak/index.html (1558) and the AART datasets; 2876d3b (13:07) deleted them; ad29396 (16:50) added them back. The hub itself, tools.html (329 lines) with the /tools and /rndlabs redirects to it and the /ws door in netlify.toml, landed in dc731a5 the same afternoon (counted under the telemetry row); the forge-* functions, which take audio to Whisper for timestamps, landed in 00cb982 (the maze row). The revert at 17:12 deleted the rndlabs set once more.// dated by the record · #19–#23 — 5 commits, including one delete/re-add round trip
2026.06.28–29The recon cockpit landed with view modes and an annotated XLSX export.20 files · +3370 −430 · site, functions, tests, docs/privaterecon.html (715 lines) arrived with netlify/functions/recon.js, recon-auth.js and send-report.js, and recon-core/ (fingerprints.js, verdict.js, a harness and fixtures). generate-report.js gained buildDepthReport: Summary, Pages and Element Ledger sheets with impact, confidence and AI Read columns. analyze-site.js accepts a model choice (haiku, sonnet, opus); deep-crawl.js accepts the recon secret as well and drops URL fragments. depth-embed.js and assess-embed.js carry the embeds; a Pursue action hands a site to Depth Skim; the view modes live in recon.html. 3 commits carry weeks of work.// dated by the record · #14–#16 — 3 commits carrying weeks of work, landing as one batch
2026.05.26–06.28The recon discipline named KRF; the name first lands in the 06-29 batch.No commit of its own: the record has nothing between 05-26 and 06-28, and the KRF name first appears in 1f4a175 on 06-29 (recon-core/harness.js, CHRONICLER_RECON.txt). The entry stands for the naming; the AART manifest and the staging/production split the old entry described are in no diff.// dated by the record: staging-era — no matching commits in main; the date is the gap it happened inside (#13 → #14)
2026.05.24–25The tools launch shipped, was deleted 7 minutes later, and returned larger the next night.12 files · +6835 −2570 · site, functions, config1b5dd60 (05-24 06:24) added crc.js (1447 lines), crc-shapes.js, surface-skim.html (822 lines), a Tools link in the nav of 5 pages and a misplaced Netlify/Functions/vault-auth.js; by 06:31 c4a7c53 and 4 delete commits had removed all of it, 1 file at a time. 710b3ef (05-25 23:05) brought it back: crc.js at 1993 lines with its behaviours split out into crc-scripts.js (a script registry), nav.js as the 1 nav file, surface-skim.html at 1407 lines, and package.json with exceljs. The retraction and the return sit side by side in the record.// record #4–#10 — 7 commits · 2 days
2026.05.25Surface Skim hardened, its Excel export widened, and the first Depth Skim draft added.13 files · +2451 −180 · site, functions, configanalyze-site.js gained a 12000-character prompt cap; fetch-site.js arrived with an SSRF blocklist, a domain blocklist and a robots.txt check; generate-report.js gained a business-impact column, a hidden disclosure sheet and a scraped-elements sheet; surface-skim.html moved to "potentially deprecated / likely fine" wording and an attestation step; crc.js gained orbital bubbles, intent tags and the click, charge, chase and scatter interactions. depth-skim.html (655 lines), deep-crawl.js (a 3-layer crawler) and depth-auth.js are the first Depth Skim draft, with the 3D topology, the terminal tower and the pit of fractious intent.// record #10–#13 — 4 commits · one night, 23:12 → 00:04
2026.05.19First commits: 5 pages, the cursor script and the vault's admin-auth function.7 files · +3479 −0 · site, functionsThe repository's first 3 commits (2026-05-21) added about.html, index.html, privacy.html, services.html, vault.html and rd-cursor.js, then netlify/functions/vault-auth.js, which checks a POSTed password against VAULT_ADMIN_SECRET with a timing-safe SHA-256 compare. vault.html carries the client vault in its own script: Firebase Firestore, timed slots, access codes, AES-256-GCM; Stripe is deferred behind a request flow. The LLC was approved the same week. The entry is dated 05-19; the commits landed 05-21.// dated by the record: the repo's first commits land 2026-05-21 · record #1–#3 — the push described here reached main that day
2026.05.18The home page hero animation rebuilt.No commit holds this: it predates the repository's first commit (2026-05-21), so the record is the entry itself. The hero animation was rebuilt as a chaos system with ephemeral clusters, semantic concept arcs, chain-link rolls and a rotating anchor.
2026.05.17Services page added and the nav wired to it.No commit holds this: it predates the repository's first commit (2026-05-21), so the record is the entry itself. The services page was added, the nav was wired, and the hero copy moved to the problem-geometry framing.
2026.05.16Business email set up and the domain secured.No commit holds this: it predates the repository's first commit (2026-05-21), so the record is the entry itself. Google Workspace was activated, the business email was in progress, and the domain was secured.