commits
- top-bar logo gets hard-edge text-shadow (--logo-shadow flips per theme) for
contrast over the hero
- hero letterbox swapped from cream to var(--purple); canvas fades in only
after all slides have loaded (no pop-in)
- slideshow now renders two layers every frame: cover-scaled back layer +
smaller multiply-blended front layer half a slot out of phase, so the
white paper edges of the colored-pencil scans dissolve softly and the
hero is always crossfading between two compositions
- radial destination-out vignette feathers the canvas edges so the purple
background bleeds in around the imagery
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The desktop archive viewer's inline script declared `const top` at script
top-level, which collides with the non-configurable `window.top` global and
throws `SyntaxError: Identifier 'top' has already been declared` on load.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
slab/menubar: tile typography now scales by session state with cell geometry
locked — green (working) smallest, slate (complete) intermediate, orange
(awaiting) bumped, red (stale, new bg) largest. Near/Far still drives the
base scale so all tiers shift in lockstep.
papers covers: gen-cover.mjs STYLE_PREFIX rewritten for record-label /
silkscreen emblem look — single subject, no readable institution names
(only incidental product marks on depicted objects), brick-red/oxblood
added to the muted palette. Per-paper cover-prompt.txt files reworked to
match (single floating emblem, no scenery) and covers regenerated.
recap waltz: bed auto-sizes BARS to out/duration.txt so it plays once
through and resolves with narration; compose.fish drops -stream_loop in
favor of apad+atrim. New piano-roll bug (waltz-overlay.mjs → waltz-keys.ass)
sits bottom-left as a TV-station logo opposite PALS, two-octave window
C4–B5 covering ~87% of events, min-highlight floor so sixteenths register.
build-filter chains it as a second libass pass, and fixes a long-standing
fps issue: subtitles= needs fps=25 on [bg] up front or libass only renders
on slide-transition frames.
recap chat-fetch: align to actual API shape ({messages:[{from,text,when,
hearts}]}); previous coercion stack was looking for keys the endpoint
never returned.
recap debug-composition.py: face + shirt-logo OCR bbox detection with
cyan safe-band overlay so the slide layouter can route chrome around both.
reports: notepat three-implementations-strategy.md — strategy doc on
notepat web vs notepat-native vs menuband.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds:
- bin/merge.mjs — unifies the three markdown sweep tables into one JSON
manifest, deduping aliases and computing per-person track membership
- sweeps/track-a-papers.md — every named human across papers/ (1074)
- sweeps/track-b-contributors.md — git committers + GitHub mirror state
+ AC @handles in disks/ (11)
- sweeps/track-c-plans-todos-v1.md — narrow first pass over 78 SCORE/
PROGRESS/TODO files (95 names)
- sweeps/track-c-plans-todos-v2.md — wider sweep over 618 plan/lecture/
notes/sosoft/reports files (134 names; v1 ∪ v2 = 182)
- merged.json — 1238 unique humans deduped across all three tracks
Cross-track signal: A∩B=1 (Maya Man), A∩C=20, B∩C=9, A∩B∩C=1 (Maya Man,
the only human cited in papers AND a committer AND named in plans/todos).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Expand README with concrete per-folder content from dropbox-manifest.md and the locally-synced DO Spaces per-piece dirs (10 score↔video pairs already organized by piece-name).
- tools/dropbox-manifest.mjs: no-dep Node script that walks /Whistlegraph/ via Dropbox HTTP API using the vault OAuth token; writes dropbox-manifest.{md,json} + dropbox-files.json.
- tools/build-html.mjs: bundles the JSONs into ~/Desktop/whistlegraph-archive.html — a self-contained, terminal-themed browser with sortable folder summary, full file search/filter, preset chips (video/audio/image/scores/procreate), and pagination.
- Manifest reveals: Scores/Score Rev1 PDF/ filenames match paper figures (rosetta confirmed across paper, Spaces, Dropbox); Research/Whistlegraphs for GAN/ is an already-curated 217 MB ML training set; 40 .procreate files carry native per-stroke timing.
- Sized "analysis core" (Scores + Procreate + Research/GAN + TikTok + Manuscripts + Pixaki + Audio Drafts) is ~17.7 GB.
Note: dropbox-{manifest,files}.json contain filenames-only listings (no file contents) including business-doc paths (LLC/Taxes/Invoices). Safe for knot-only push; revisit if the GitHub mirror is reactivated.
Hero crossfade is now a 4-way rotation. New v4 (papers-header-v4.png) is
a first-person POV from inside a sunlit cafe / workshop: hands on the
Citrus-green Neo, three grad students at adjacent tables absorbed in the
arxiv-style papers, golden Grant-Wood hills + farmhouse visible through
the window. Generated with the canonical SHOOT_REFS plus 3 first-person
selfies pulled from the new screenshots bucket as POV-staging anchors.
Canvas slideshow (papers.aesthetic.computer/index.html):
- Switched from cover to contain so the full image is visible at every
viewport width; warm-cream letterbox (#efe2c8) matches the paper edges
the colored-pencil illustrations fade into
- Added per-slide focal anchor (jeffrey's face for v1/v2, laptop for v3/v4)
so the Ken Burns pan/zoom keeps the important content centered instead
of drifting into empty grass
- 4-slide rotation order: Johnny Appleseed → cafe POV → grad students POV
→ Washington crossing
Jeffrey platter:
- New buckets.screenshots in jeffrey-platter/manifest.json — 90 first-person
POV "selfies" of jeffrey's working environment (laptop, hands, desk)
imported from give.aesthetic.computer's screenshotsData. Framed in the
README as canonical first-person reference imagery for image-gen pipelines
(pass via --refs to generate-neo.py for POV-grounded gens, the way v4 was
generated). sync.mjs ran, give-page manifest updated in lockstep.
Switcher only swapped 19 of 39 papers because index.html carried a stale
hand-maintained translations object alongside the auto-generated
translations.json. Page now fetches the JSON at runtime, setLang reads
{title, subtitle} and re-appends the format/link suffix from the English
detail (e.g. "· arXiv 5pp", "· <a>interactive timeline</a>"), and papers
without translations fall back to English instead of half-swapping.
Also extended cleanLatex (\acrandname{}, Spanish accents, Danish letters
in {\x}/\x{}/\x\<sp> forms + LaTeX space-gobble), added Japanese to the
dropdown + /ja /jp redirects, and deferred the initial path-language
swap until the JSON has loaded so first paint isn't English-flash.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- ac-electron/ac-desktop: new `autodeploy` subcommand that probes knot SSH on an interval, then runs push → publish → install once the network cooperates (airline-wifi resilience).
- slides/notepat-keymap/template.html: PALS watermark composited ON TOP of the Jeffrey portrait in the corner; QR row goes side-by-side with implementations instead of stacked; smaller QRs to fit the new row.
- grants/lacma-2026/lacma-2026.pdf: revised draft.
- system/public/menuband/index.html: EN/ES language-switch chip pair (rounded glass capsule, top-right) — companion to the slab/menuband Localization scaffold.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Oven side:
- recap-builder.mjs builds a recap mp4 from a single audience config (e.g. jeffrey-73h-2026-05-02). Same job/log/SSE shape as native-builder.mjs / papers-builder.mjs so the dashboard can render it without special-casing.
- recap-git-poller.mjs auto-triggers a build when recap/audience/*.mjs changes land on origin/main.
- server.mjs adds /recap-build endpoints (list, get, SSE stream, mp4 download, manual POST trigger, cancel) gated by OS_BUILD_ADMIN_KEY, and starts the recap git poller alongside the native + papers ones.
- deploy.fish scps the two new builder files to /opt/oven/.
Recap pipeline:
- New audience configs: jeffrey-24h-2026-05-01.mjs, jeffrey-73h-2026-05-02.mjs.
- New tooling: chat-fetch.mjs, gen-photos.mjs, test-slide.mjs.
- scout.mjs touch-up.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PLORKing the Planet (arxiv-plork):
- Five figures landed: hardware-yoga hero, kidlisp-featured screenshot, ensemble-network TikZ diagram, KidLisp cards strip, platform-screenshot.
- Switched fontspec to explicit lmroman10 / lmsans10 / lmmono10 family files (Latin Modern via fontspec was picking up the wrong glyphs on some installs).
- Added §5.4 Palmer Luckey / Oculus → Anduril subsection — political-economy counter-arc to the AC OS proposition.
- references.bib: cnbc2019luckey, tablet2024vulcan, cbs2024luckey, anduril2026products, wiki2026anduril.
A Fraserin' Art + Tech (arxiv-fraserin, new):
- New research track: methodology essay + prior-art survey applying Andrea Fraser's institutional-critique grammar to the art-and-tech cluster, in a labor-folk register.
- First-pass 7-page draft built same day (`fraserin.tex` + ac-paper-layout, references, cover prompt/sources, qr.png, PLAN.md).
- Names the dossier series (rhizome / eyebeam / sfpc / recurse / pioneer-works / mellon / internet-archive / new-inc / machine-project / the-kitchen / studio-museum / heavy-manners-library / hathitrust / calarts / ucla-arts) as one coherent project under that lens.
Tooling + index:
- RESEARCH-DIRECTION.md tracks both threads + lists the Fraser-track acquisition queue.
- SCORE.md promotes fraserin from PLAN-only to 7-pp first-pass.
- People Platter (`papers/people-platter/TODO.md`) opened.
- cli.mjs / papermill.mjs / bin/gen-qrs.mjs: small wiring touches for the new platter.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Field reports of the iOS app sitting on the boot.mjs animation indefinitely with no recovery short of force-quit. Root cause was structural: no host-side detection of a stuck JS runtime, no failure path on WKNavigationDelegate, and the network monitor cancelled itself on the first satisfied path so mid-session drops were invisible.
- AppNetworkMonitor (long-lived) replaces the one-shot monitor; online↔offline transitions auto-reload.
- BootStatus 5s-poll watchdog flips `stalled = true` after 25s of no JS heartbeat; SwiftUI overlay surfaces a Reload button.
- WKNavigationDelegate wired so provisional/final nav failures populate `BootStatus.lastError` for the overlay.
- boot.mjs IIFE posts {type:"boot:heartbeat"|"boot:ready"} via webkit.messageHandlers.iOSApp every 1s during boot, every 8s after acHIDE_BOOT_LOG.
- Pull-to-refresh attached to the WebView's scroll view via UIRefreshControl.
- Scene-phase reload after >5min background (stale runtime / timed-out sockets).
- offline.html "Try again" button posts {type:"reload-online"} to force-load even if path monitor still reads offline (cell-handoff lag).
- Reload gating on Coordinator.lastLoadedKey so updateUIView only reloads on real URL/trigger changes, not every SwiftUI re-render.
Bump CFBundleVersion to 3 before archiving.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Menu Bar app:
- ClaudeSession adds a `complete` state ("turn done, idle") between working and stale; icon/dot/menu colors shift to green=working / slate=complete / amber=awaiting / gray=stale.
- Restore-threads submenu opens N fresh Terminal windows running `claude -r <id>` for the most-recently-modified sessions on disk that aren't already live (recovery hatch for when Terminal.app dies).
- Restart-all-active SIGTERMs every live session and respawns each in a fresh Terminal with --resume (warns first since it interrupts in-flight work).
- Auto-tile + Tile-now pack open Terminal windows into a square-ish grid with font size scaled to fit; "Near"/"Far" text-size radio shrinks the font for close-to-screen viewing.
- Theme-by-status pushes per-state background color + custom-title to each Terminal tab via a single batched osascript pass (memoized so it only fires when state/subject actually changes).
- New ClaudeHistoryReader.swift reads ~/.claude history JSONLs to source the "restore last N" picks.
Bash hooks + install:
- claude-prompt-log.sh derives a 4–8-word `summary` from the prompt and writes it both into active-prompts/<id>.json and as an OSC 0 title to the controlling TTY (so the Terminal title reflects the current task even when theme-by-status is off).
- claude-stop.sh prefers the new sinebells `all-done-waltz.mp3` when present, falling back to the legacy chime.
- install.sh copies any *.mp3 in slab/sounds/ alongside the .wav set so the waltz phrase is installed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Localization.swift adds plug-and-play L("key") with English + Spanish tables; popover rebuilds on language change.
- HoverLinkButton paints a real link/chip (idle + hover fill/border, pointing-hand cursor) for the Why-this-Keymap and brand badges.
- Music-note pill in KeyboardIconRenderer now hugs the actual digits of voiceNumber instead of reserving a fixed 12pt pad.
- viewDidChangeEffectiveAppearance re-resolves the popover background so light/dark toggles repaint cleanly.
- Bundles keymaps-social-software-26-arxiv.pdf as a resource for the Why-this-Keymap chip.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
waltz.mjs now exports the deterministic event list to
out/waltz-events.json alongside out/waltz.mp3 — same data the synth
mixer used to generate the audio, available for downstream tools.
New bin/waltz-overlay.mjs reads that event list and emits an .ass
(libass) overlay file with timed Dialogue lines that draw filled
rectangles on a two-octave (C3–B4) notepat-style keyboard. Octave-
coded hues distinguish the lower vs upper register.
Composed locally as ~/Desktop/waltz-piano-overlay.mp4 (95s, ~2.4MB)
to verify the visual/timing read. Slot into the recap pipeline next
by adding waltz-keys.ass as a second subtitles= filter in compose.
See feedback memory: feedback_recap_waltz_piano_overlay.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three Grant-Wood / golden-hour iterations of jeffrey distributing AC papers,
generated via portraits/jeffrey/bin/generate-neo.py with the platter refs:
v1 (washington-crossing) — heroic stride, drones delivering papers
v2 (johnny appleseed) — glasses + working on the green Neo as he walks,
paper-launching backpack cannon, no drones,
pages fall like maple seeds and are caught
v3 (first-person POV) — hands on the keyboard in foreground, ~14 grad
students seated on the grass reading arxiv-styled
papers (serif title bar + AC vignette + two-col
grey body), papers raining in upper-right
Site changes:
- Full-bleed hero banner (100vw, fades transparent → bg with a single linear
ramp so it reads in both light and dark mode)
- Three stacked .hero-bg layers with a 24s ease-in-out crossfade, gated on
prefers-reduced-motion
- Fixed corner-HUD top-bar modeled on give.aesthetic.computer (Times-italic
"papers" + AC pink wordmark, lang-selector top-right, var(--bg)→transparent
gradient strip)
- Times-serif italic for abstracts + colophon for the broadside / journal feel;
paper rows stay Berkeley Mono for legibility
- New papers-og.jpg (1200×630) center-cropped from v2 for social shares
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The pre-encoded subtitle webm path had two compounding bugs on the
oven build: libvpx-vp9 silently dropped alpha (encoded as yuv420p
instead of yuva420p, so every frame came through as opaque black and
hid the slides), and the concat-demuxer→fps filter pattern produced
sparse PTS that truncated the main encode at ~half length.
Switching to ffmpeg's `subtitles=` filter (libass) sidesteps both:
- Subtitles render directly into the video stream at composite time —
no separate alpha-codec encode required.
- Single filter, sub-second overhead instead of 5+ minutes of webm
pre-encode.
- Frame-perfect cue timing from the .ass Dialogue lines.
- Pill styling replicated via BorderStyle=4 (opaque box) +
PrimaryColour cream + OutlineColour magenta + translucent BackColour.
bin/subtitle-track.mjs now emits subs.ass instead of subtitle-track.webm.
build-filter.mjs adds a single `subtitles=...:fontsdir=...` filter on
the slide chain. compose.fish drops the subtitle-track input; waltz
moves from input #3 back to input #2.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
OpenAI billing raised; ran node papers/bin/gen-cover.mjs --all --force.
All 13 dossiers now have the canonical colored-pencil vignette covers
generated from their sourced cover-prompt.txt:
rhizome — tangled rhizome runners with CRT glyph
sfpc — book-as-circuit-and-handwriting with breadboard
eyebeam — circuit-iris eye
recurse — laptop with Mandelbrot recursion spiral
internet-archive — floating Greek Revival temple
mellon — brass balance scales with grant-letters
pioneer-works — arched window with Yellin glass-shards
new-inc — translucent hexagonal incubator pod
studio-museum — easel-and-stool with Adjaye facade
hathitrust — book stack with data-strands
the-kitchen — Sony Portapak with cable braid
machine-project — Echo Park storefront window
heavy-manners-library — dub-reggae sleeve with library checkout pocket
Each cover replaces either an old vertical-strip or a cream placeholder.
Sources documented in each dossier's figures/cover-sources.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The fps filter on inputs sourced from a concat demuxer with `duration`
directives (slides input #0, pre-encoded subtitle webm input #2)
truncates the output at ~half length. The demuxer emits sparse PTS
matching the duration directives; the fps filter mishandles that and
produces fewer output frames than expected.
Reproduced in isolation: slides+fps→libx264 = 157s output. Same chain
without fps filter = 281.6s. Fix is just to drop the filter — ffmpeg
honors the duration directives directly when the encoder consumes them.
The audio waveform overlay (showwaves rate=30) sets the timeline's
effective frame rate; slides + subs ride along.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Concat-demuxer + image2 produces a sparse PTS stream (one frame per
file= entry, with timing as a "duration before next frame" gap). When
that's piped into ffmpeg's overlay filter as input #2, the overlay sees
gaps and truncates the output stream — the previous build encoded only
~157s of a 281s timeline.
Fix: subtitle-track.mjs now does a 1-3 second pre-encode pass that
converts the concat-demuxer timeline into a proper 30 fps libvpx-vp9
WebM with yuva420p alpha (~hundreds of KB). The main compose just adds
that webm as -i input #2; build-filter overlays it once. Cache via
hash on (subs[*] timing + total duration); skip the encode when cached.
This is the previously projected fix for the 6-hour compose bottleneck
on oven, now actually working.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Versioned entrypoint mirroring papers/cli.mjs. Today it's a thin
wrapper around pipeline.fish with a `build` subcommand and a read-only
`cache` inspector. The cache work for individual steps still lives
inside each bin/* script (tts.mjs / transcribe.mjs / align.mjs already
hash their inputs and skip when valid).
Future iterations move the per-step orchestration here and let the
oven's recap-builder.mjs call \`node recap/cli.mjs build <audience>\`
instead of \`fish pipeline.fish\`. For now both work — pipeline.fish is
still the source of truth for ordering.
ac-24 build <audience>
ac-24 cache <audience>
ac-24 version
See feedback memory: feedback_recap_ac24_cli.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
transcribe.mjs + align.mjs now hash their inputs (recap.mp3 / words.json
+ segments) and skip work when outputs are already valid for the same
hash. --force overrides. Saves ~100s per rerun on the oven CPU.
Subtitles redesigned to fix the oven-encode bottleneck: subtitles.mjs
now renders full-frame 1080×1920 transparent PNGs (pill positioned at
y=1690) plus a blank.png. New subtitle-track.mjs emits a concat-demuxer
file that sequences subtitle PNGs and blank gaps with stored durations.
build-filter.mjs drops the 135-deep movie= overlay chain and replaces
it with a single overlay of the subtitle stream as input #2.
compose.fish takes the subtitle track as `-f concat -i subtitle-track.txt`
input #2, with waltz bumped to input #3.
Result: the compose ffmpeg's filter graph collapses from 276 lines to
~7. The previous 6+ hour projection drops to a few minutes — the deep
movie= chain was the wall, not the encoder.
See feedback memory:
- feedback_recap_subtitles_required.md
- feedback_recap_ac24_cli.md (next-iter cache layer)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ElevenLabs (via the /api/say proxy) is the only real-money step in the
recap pipeline besides photo gen. Hashing the narration text + voice
config + checking out/recap.mp3.hash lets reruns skip the API hit when
nothing changed. --force overrides.
This unblocks $0 reruns of an episode (audio + photos already cached).
First step toward the broader ac-24 CLI cache layer (see memory note
feedback_recap_ac24_cli.md).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Doctrine: every dossier cover illustration must be sourced, not blind-prompted.
Each visual element (founder, building, signature object, brand color) traces
to a real reference — photograph, interview, physical artifact, brand asset.
Per-dossier figures/cover-sources.md documents:
- the visual elements present in cover-prompt.txt
- the source for each (URL, photograph, founder name, building, etc.)
- founder + key people referenced (or deliberately not depicted)
- what was excluded and why
- citation log (URLs, ProPublica EINs, Wikipedia, primary docs)
Covers 13 dossiers: rhizome, sfpc, eyebeam, recurse, internet-archive,
mellon, pioneer-works, new-inc, studio-museum, hathitrust, the-kitchen,
machine-project, heavy-manners-library.
Cross-references called out: Kaganskiy (NEW INC → Eyebeam), Maya Man
(SFPC supporter + Heavy Manners web designer), 1200 N Alvarado tenancy
chain (Echo Park Film Center → Machine Project → Heavy Manners Library).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Earlier commit landed h264_videotoolbox by accident (works on Apple
Silicon, missing on Linux). Oven failed with "Unknown encoder
h264_videotoolbox". Switch to libx264 -preset ultrafast -crf 22 — works
everywhere, ~5 min encode for 280s of 1080×1920 with the 139-overlay
filter chain.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The 139-deep movie= subtitle overlay filter graph saturates a single
ffmpeg thread (1 core fully consumed, output file stalled at the
filter-init phase on the oven). Dropping libx264 from medium → ultrafast
trades ~2x file size for ~10x encode time. CRF 22 keeps quality
acceptable for 1080×1920 vertical reels. Without this the oven encode
projects to 5+ hours; with it, ~5 min.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
networkidle0 sometimes hangs on oven for slides with multi-MB base64
photos embedded inline (build 67f9ee23-8 timed out at slide 07_hp_plotter
after rendering 6 slides successfully). domcontentloaded fires once the
DOM is parsed, which is all we need before screenshot — data URLs render
synchronously, no network to wait on. 90s timeout for slow CPU safety.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
slides.mjs / subtitles.mjs / screenshots.mjs hardcoded the Mac-only
puppeteer module path, system/public/ font paths, and Google Chrome
executable. Resolve puppeteer dynamically across local-dev and
/opt/oven/node_modules; build font/PALS paths from a REPO constant; let
puppeteer use its bundled Chromium on Linux. screenshots.mjs picks up
the same puppeteer resolver so the (currently unused) screenshot-cache
path won't blow up if it's ever wired into a slide.
Recap pipeline now runs end-to-end on the oven.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
New first-pass dossiers (with full IRS XML / public-disclosure data folders):
- arxiv-eyebeam (Eyebeam, NYC 1996–, 14 FYs of P&L, 6-ED chain, 3 locations)
- arxiv-recurse (Recurse Center, NYC 2011–, recruiting-funded model)
- arxiv-internet-archive (IA, SF 1996–, Hachette + UMG cases, FY23 cliff)
- arxiv-mellon (Mellon Foundation 1969–, funder-flip dossier; recipient
spotlight cross-references Rhizome / IA / Eyebeam / Pioneer Works)
- arxiv-pioneer-works (Pioneer Works, Brooklyn 2012–, Yellin-as-funder)
New cover layout for all 7 dossiers (rhizome + sfpc rebuilt to match):
- pals SVG moved to top-right (3.5em), small but visible
- AI-generated colored-pencil illustration becomes the hero image
- creation date + revision counter line under URL
New tooling:
- papers/bin/gen-cover.mjs: colored-pencil cover generator using OpenAI
gpt-image-2 (no portrait refs; per-paper figures/cover-prompt.txt;
consistent style prefix baked in for series consistency)
- papers/hitlist.md: dossier candidate index, sorted by data tractability
Registration:
- All 7 added to papers/SCORE.md and papers/cli.mjs PAPER_MAP
- All 7 added to papers/metadata.json (created/revisions surfaced on cover)
- platter.html refreshed via sync-platter.mjs
Each dossier folder includes: <slug>.tex (full preamble OTF Latin Modern
via filenames so xelatex renders identically on macOS + Linux), data/
folder with README + per-org CSVs (financials/people/funders/grants/
timeline/locations/programs/etc), references.bib, figures/cover.png +
cover-prompt.txt.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- top-bar logo gets hard-edge text-shadow (--logo-shadow flips per theme) for
contrast over the hero
- hero letterbox swapped from cream to var(--purple); canvas fades in only
after all slides have loaded (no pop-in)
- slideshow now renders two layers every frame: cover-scaled back layer +
smaller multiply-blended front layer half a slot out of phase, so the
white paper edges of the colored-pencil scans dissolve softly and the
hero is always crossfading between two compositions
- radial destination-out vignette feathers the canvas edges so the purple
background bleeds in around the imagery
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
slab/menubar: tile typography now scales by session state with cell geometry
locked — green (working) smallest, slate (complete) intermediate, orange
(awaiting) bumped, red (stale, new bg) largest. Near/Far still drives the
base scale so all tiers shift in lockstep.
papers covers: gen-cover.mjs STYLE_PREFIX rewritten for record-label /
silkscreen emblem look — single subject, no readable institution names
(only incidental product marks on depicted objects), brick-red/oxblood
added to the muted palette. Per-paper cover-prompt.txt files reworked to
match (single floating emblem, no scenery) and covers regenerated.
recap waltz: bed auto-sizes BARS to out/duration.txt so it plays once
through and resolves with narration; compose.fish drops -stream_loop in
favor of apad+atrim. New piano-roll bug (waltz-overlay.mjs → waltz-keys.ass)
sits bottom-left as a TV-station logo opposite PALS, two-octave window
C4–B5 covering ~87% of events, min-highlight floor so sixteenths register.
build-filter chains it as a second libass pass, and fixes a long-standing
fps issue: subtitles= needs fps=25 on [bg] up front or libass only renders
on slide-transition frames.
recap chat-fetch: align to actual API shape ({messages:[{from,text,when,
hearts}]}); previous coercion stack was looking for keys the endpoint
never returned.
recap debug-composition.py: face + shirt-logo OCR bbox detection with
cyan safe-band overlay so the slide layouter can route chrome around both.
reports: notepat three-implementations-strategy.md — strategy doc on
notepat web vs notepat-native vs menuband.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds:
- bin/merge.mjs — unifies the three markdown sweep tables into one JSON
manifest, deduping aliases and computing per-person track membership
- sweeps/track-a-papers.md — every named human across papers/ (1074)
- sweeps/track-b-contributors.md — git committers + GitHub mirror state
+ AC @handles in disks/ (11)
- sweeps/track-c-plans-todos-v1.md — narrow first pass over 78 SCORE/
PROGRESS/TODO files (95 names)
- sweeps/track-c-plans-todos-v2.md — wider sweep over 618 plan/lecture/
notes/sosoft/reports files (134 names; v1 ∪ v2 = 182)
- merged.json — 1238 unique humans deduped across all three tracks
Cross-track signal: A∩B=1 (Maya Man), A∩C=20, B∩C=9, A∩B∩C=1 (Maya Man,
the only human cited in papers AND a committer AND named in plans/todos).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Expand README with concrete per-folder content from dropbox-manifest.md and the locally-synced DO Spaces per-piece dirs (10 score↔video pairs already organized by piece-name).
- tools/dropbox-manifest.mjs: no-dep Node script that walks /Whistlegraph/ via Dropbox HTTP API using the vault OAuth token; writes dropbox-manifest.{md,json} + dropbox-files.json.
- tools/build-html.mjs: bundles the JSONs into ~/Desktop/whistlegraph-archive.html — a self-contained, terminal-themed browser with sortable folder summary, full file search/filter, preset chips (video/audio/image/scores/procreate), and pagination.
- Manifest reveals: Scores/Score Rev1 PDF/ filenames match paper figures (rosetta confirmed across paper, Spaces, Dropbox); Research/Whistlegraphs for GAN/ is an already-curated 217 MB ML training set; 40 .procreate files carry native per-stroke timing.
- Sized "analysis core" (Scores + Procreate + Research/GAN + TikTok + Manuscripts + Pixaki + Audio Drafts) is ~17.7 GB.
Note: dropbox-{manifest,files}.json contain filenames-only listings (no file contents) including business-doc paths (LLC/Taxes/Invoices). Safe for knot-only push; revisit if the GitHub mirror is reactivated.
Hero crossfade is now a 4-way rotation. New v4 (papers-header-v4.png) is
a first-person POV from inside a sunlit cafe / workshop: hands on the
Citrus-green Neo, three grad students at adjacent tables absorbed in the
arxiv-style papers, golden Grant-Wood hills + farmhouse visible through
the window. Generated with the canonical SHOOT_REFS plus 3 first-person
selfies pulled from the new screenshots bucket as POV-staging anchors.
Canvas slideshow (papers.aesthetic.computer/index.html):
- Switched from cover to contain so the full image is visible at every
viewport width; warm-cream letterbox (#efe2c8) matches the paper edges
the colored-pencil illustrations fade into
- Added per-slide focal anchor (jeffrey's face for v1/v2, laptop for v3/v4)
so the Ken Burns pan/zoom keeps the important content centered instead
of drifting into empty grass
- 4-slide rotation order: Johnny Appleseed → cafe POV → grad students POV
→ Washington crossing
Jeffrey platter:
- New buckets.screenshots in jeffrey-platter/manifest.json — 90 first-person
POV "selfies" of jeffrey's working environment (laptop, hands, desk)
imported from give.aesthetic.computer's screenshotsData. Framed in the
README as canonical first-person reference imagery for image-gen pipelines
(pass via --refs to generate-neo.py for POV-grounded gens, the way v4 was
generated). sync.mjs ran, give-page manifest updated in lockstep.
Switcher only swapped 19 of 39 papers because index.html carried a stale
hand-maintained translations object alongside the auto-generated
translations.json. Page now fetches the JSON at runtime, setLang reads
{title, subtitle} and re-appends the format/link suffix from the English
detail (e.g. "· arXiv 5pp", "· <a>interactive timeline</a>"), and papers
without translations fall back to English instead of half-swapping.
Also extended cleanLatex (\acrandname{}, Spanish accents, Danish letters
in {\x}/\x{}/\x\<sp> forms + LaTeX space-gobble), added Japanese to the
dropdown + /ja /jp redirects, and deferred the initial path-language
swap until the JSON has loaded so first paint isn't English-flash.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- ac-electron/ac-desktop: new `autodeploy` subcommand that probes knot SSH on an interval, then runs push → publish → install once the network cooperates (airline-wifi resilience).
- slides/notepat-keymap/template.html: PALS watermark composited ON TOP of the Jeffrey portrait in the corner; QR row goes side-by-side with implementations instead of stacked; smaller QRs to fit the new row.
- grants/lacma-2026/lacma-2026.pdf: revised draft.
- system/public/menuband/index.html: EN/ES language-switch chip pair (rounded glass capsule, top-right) — companion to the slab/menuband Localization scaffold.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Oven side:
- recap-builder.mjs builds a recap mp4 from a single audience config (e.g. jeffrey-73h-2026-05-02). Same job/log/SSE shape as native-builder.mjs / papers-builder.mjs so the dashboard can render it without special-casing.
- recap-git-poller.mjs auto-triggers a build when recap/audience/*.mjs changes land on origin/main.
- server.mjs adds /recap-build endpoints (list, get, SSE stream, mp4 download, manual POST trigger, cancel) gated by OS_BUILD_ADMIN_KEY, and starts the recap git poller alongside the native + papers ones.
- deploy.fish scps the two new builder files to /opt/oven/.
Recap pipeline:
- New audience configs: jeffrey-24h-2026-05-01.mjs, jeffrey-73h-2026-05-02.mjs.
- New tooling: chat-fetch.mjs, gen-photos.mjs, test-slide.mjs.
- scout.mjs touch-up.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PLORKing the Planet (arxiv-plork):
- Five figures landed: hardware-yoga hero, kidlisp-featured screenshot, ensemble-network TikZ diagram, KidLisp cards strip, platform-screenshot.
- Switched fontspec to explicit lmroman10 / lmsans10 / lmmono10 family files (Latin Modern via fontspec was picking up the wrong glyphs on some installs).
- Added §5.4 Palmer Luckey / Oculus → Anduril subsection — political-economy counter-arc to the AC OS proposition.
- references.bib: cnbc2019luckey, tablet2024vulcan, cbs2024luckey, anduril2026products, wiki2026anduril.
A Fraserin' Art + Tech (arxiv-fraserin, new):
- New research track: methodology essay + prior-art survey applying Andrea Fraser's institutional-critique grammar to the art-and-tech cluster, in a labor-folk register.
- First-pass 7-page draft built same day (`fraserin.tex` + ac-paper-layout, references, cover prompt/sources, qr.png, PLAN.md).
- Names the dossier series (rhizome / eyebeam / sfpc / recurse / pioneer-works / mellon / internet-archive / new-inc / machine-project / the-kitchen / studio-museum / heavy-manners-library / hathitrust / calarts / ucla-arts) as one coherent project under that lens.
Tooling + index:
- RESEARCH-DIRECTION.md tracks both threads + lists the Fraser-track acquisition queue.
- SCORE.md promotes fraserin from PLAN-only to 7-pp first-pass.
- People Platter (`papers/people-platter/TODO.md`) opened.
- cli.mjs / papermill.mjs / bin/gen-qrs.mjs: small wiring touches for the new platter.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Field reports of the iOS app sitting on the boot.mjs animation indefinitely with no recovery short of force-quit. Root cause was structural: no host-side detection of a stuck JS runtime, no failure path on WKNavigationDelegate, and the network monitor cancelled itself on the first satisfied path so mid-session drops were invisible.
- AppNetworkMonitor (long-lived) replaces the one-shot monitor; online↔offline transitions auto-reload.
- BootStatus 5s-poll watchdog flips `stalled = true` after 25s of no JS heartbeat; SwiftUI overlay surfaces a Reload button.
- WKNavigationDelegate wired so provisional/final nav failures populate `BootStatus.lastError` for the overlay.
- boot.mjs IIFE posts {type:"boot:heartbeat"|"boot:ready"} via webkit.messageHandlers.iOSApp every 1s during boot, every 8s after acHIDE_BOOT_LOG.
- Pull-to-refresh attached to the WebView's scroll view via UIRefreshControl.
- Scene-phase reload after >5min background (stale runtime / timed-out sockets).
- offline.html "Try again" button posts {type:"reload-online"} to force-load even if path monitor still reads offline (cell-handoff lag).
- Reload gating on Coordinator.lastLoadedKey so updateUIView only reloads on real URL/trigger changes, not every SwiftUI re-render.
Bump CFBundleVersion to 3 before archiving.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Menu Bar app:
- ClaudeSession adds a `complete` state ("turn done, idle") between working and stale; icon/dot/menu colors shift to green=working / slate=complete / amber=awaiting / gray=stale.
- Restore-threads submenu opens N fresh Terminal windows running `claude -r <id>` for the most-recently-modified sessions on disk that aren't already live (recovery hatch for when Terminal.app dies).
- Restart-all-active SIGTERMs every live session and respawns each in a fresh Terminal with --resume (warns first since it interrupts in-flight work).
- Auto-tile + Tile-now pack open Terminal windows into a square-ish grid with font size scaled to fit; "Near"/"Far" text-size radio shrinks the font for close-to-screen viewing.
- Theme-by-status pushes per-state background color + custom-title to each Terminal tab via a single batched osascript pass (memoized so it only fires when state/subject actually changes).
- New ClaudeHistoryReader.swift reads ~/.claude history JSONLs to source the "restore last N" picks.
Bash hooks + install:
- claude-prompt-log.sh derives a 4–8-word `summary` from the prompt and writes it both into active-prompts/<id>.json and as an OSC 0 title to the controlling TTY (so the Terminal title reflects the current task even when theme-by-status is off).
- claude-stop.sh prefers the new sinebells `all-done-waltz.mp3` when present, falling back to the legacy chime.
- install.sh copies any *.mp3 in slab/sounds/ alongside the .wav set so the waltz phrase is installed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Localization.swift adds plug-and-play L("key") with English + Spanish tables; popover rebuilds on language change.
- HoverLinkButton paints a real link/chip (idle + hover fill/border, pointing-hand cursor) for the Why-this-Keymap and brand badges.
- Music-note pill in KeyboardIconRenderer now hugs the actual digits of voiceNumber instead of reserving a fixed 12pt pad.
- viewDidChangeEffectiveAppearance re-resolves the popover background so light/dark toggles repaint cleanly.
- Bundles keymaps-social-software-26-arxiv.pdf as a resource for the Why-this-Keymap chip.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
waltz.mjs now exports the deterministic event list to
out/waltz-events.json alongside out/waltz.mp3 — same data the synth
mixer used to generate the audio, available for downstream tools.
New bin/waltz-overlay.mjs reads that event list and emits an .ass
(libass) overlay file with timed Dialogue lines that draw filled
rectangles on a two-octave (C3–B4) notepat-style keyboard. Octave-
coded hues distinguish the lower vs upper register.
Composed locally as ~/Desktop/waltz-piano-overlay.mp4 (95s, ~2.4MB)
to verify the visual/timing read. Slot into the recap pipeline next
by adding waltz-keys.ass as a second subtitles= filter in compose.
See feedback memory: feedback_recap_waltz_piano_overlay.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three Grant-Wood / golden-hour iterations of jeffrey distributing AC papers,
generated via portraits/jeffrey/bin/generate-neo.py with the platter refs:
v1 (washington-crossing) — heroic stride, drones delivering papers
v2 (johnny appleseed) — glasses + working on the green Neo as he walks,
paper-launching backpack cannon, no drones,
pages fall like maple seeds and are caught
v3 (first-person POV) — hands on the keyboard in foreground, ~14 grad
students seated on the grass reading arxiv-styled
papers (serif title bar + AC vignette + two-col
grey body), papers raining in upper-right
Site changes:
- Full-bleed hero banner (100vw, fades transparent → bg with a single linear
ramp so it reads in both light and dark mode)
- Three stacked .hero-bg layers with a 24s ease-in-out crossfade, gated on
prefers-reduced-motion
- Fixed corner-HUD top-bar modeled on give.aesthetic.computer (Times-italic
"papers" + AC pink wordmark, lang-selector top-right, var(--bg)→transparent
gradient strip)
- Times-serif italic for abstracts + colophon for the broadside / journal feel;
paper rows stay Berkeley Mono for legibility
- New papers-og.jpg (1200×630) center-cropped from v2 for social shares
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The pre-encoded subtitle webm path had two compounding bugs on the
oven build: libvpx-vp9 silently dropped alpha (encoded as yuv420p
instead of yuva420p, so every frame came through as opaque black and
hid the slides), and the concat-demuxer→fps filter pattern produced
sparse PTS that truncated the main encode at ~half length.
Switching to ffmpeg's `subtitles=` filter (libass) sidesteps both:
- Subtitles render directly into the video stream at composite time —
no separate alpha-codec encode required.
- Single filter, sub-second overhead instead of 5+ minutes of webm
pre-encode.
- Frame-perfect cue timing from the .ass Dialogue lines.
- Pill styling replicated via BorderStyle=4 (opaque box) +
PrimaryColour cream + OutlineColour magenta + translucent BackColour.
bin/subtitle-track.mjs now emits subs.ass instead of subtitle-track.webm.
build-filter.mjs adds a single `subtitles=...:fontsdir=...` filter on
the slide chain. compose.fish drops the subtitle-track input; waltz
moves from input #3 back to input #2.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
OpenAI billing raised; ran node papers/bin/gen-cover.mjs --all --force.
All 13 dossiers now have the canonical colored-pencil vignette covers
generated from their sourced cover-prompt.txt:
rhizome — tangled rhizome runners with CRT glyph
sfpc — book-as-circuit-and-handwriting with breadboard
eyebeam — circuit-iris eye
recurse — laptop with Mandelbrot recursion spiral
internet-archive — floating Greek Revival temple
mellon — brass balance scales with grant-letters
pioneer-works — arched window with Yellin glass-shards
new-inc — translucent hexagonal incubator pod
studio-museum — easel-and-stool with Adjaye facade
hathitrust — book stack with data-strands
the-kitchen — Sony Portapak with cable braid
machine-project — Echo Park storefront window
heavy-manners-library — dub-reggae sleeve with library checkout pocket
Each cover replaces either an old vertical-strip or a cream placeholder.
Sources documented in each dossier's figures/cover-sources.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The fps filter on inputs sourced from a concat demuxer with `duration`
directives (slides input #0, pre-encoded subtitle webm input #2)
truncates the output at ~half length. The demuxer emits sparse PTS
matching the duration directives; the fps filter mishandles that and
produces fewer output frames than expected.
Reproduced in isolation: slides+fps→libx264 = 157s output. Same chain
without fps filter = 281.6s. Fix is just to drop the filter — ffmpeg
honors the duration directives directly when the encoder consumes them.
The audio waveform overlay (showwaves rate=30) sets the timeline's
effective frame rate; slides + subs ride along.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Concat-demuxer + image2 produces a sparse PTS stream (one frame per
file= entry, with timing as a "duration before next frame" gap). When
that's piped into ffmpeg's overlay filter as input #2, the overlay sees
gaps and truncates the output stream — the previous build encoded only
~157s of a 281s timeline.
Fix: subtitle-track.mjs now does a 1-3 second pre-encode pass that
converts the concat-demuxer timeline into a proper 30 fps libvpx-vp9
WebM with yuva420p alpha (~hundreds of KB). The main compose just adds
that webm as -i input #2; build-filter overlays it once. Cache via
hash on (subs[*] timing + total duration); skip the encode when cached.
This is the previously projected fix for the 6-hour compose bottleneck
on oven, now actually working.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Versioned entrypoint mirroring papers/cli.mjs. Today it's a thin
wrapper around pipeline.fish with a `build` subcommand and a read-only
`cache` inspector. The cache work for individual steps still lives
inside each bin/* script (tts.mjs / transcribe.mjs / align.mjs already
hash their inputs and skip when valid).
Future iterations move the per-step orchestration here and let the
oven's recap-builder.mjs call \`node recap/cli.mjs build <audience>\`
instead of \`fish pipeline.fish\`. For now both work — pipeline.fish is
still the source of truth for ordering.
ac-24 build <audience>
ac-24 cache <audience>
ac-24 version
See feedback memory: feedback_recap_ac24_cli.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
transcribe.mjs + align.mjs now hash their inputs (recap.mp3 / words.json
+ segments) and skip work when outputs are already valid for the same
hash. --force overrides. Saves ~100s per rerun on the oven CPU.
Subtitles redesigned to fix the oven-encode bottleneck: subtitles.mjs
now renders full-frame 1080×1920 transparent PNGs (pill positioned at
y=1690) plus a blank.png. New subtitle-track.mjs emits a concat-demuxer
file that sequences subtitle PNGs and blank gaps with stored durations.
build-filter.mjs drops the 135-deep movie= overlay chain and replaces
it with a single overlay of the subtitle stream as input #2.
compose.fish takes the subtitle track as `-f concat -i subtitle-track.txt`
input #2, with waltz bumped to input #3.
Result: the compose ffmpeg's filter graph collapses from 276 lines to
~7. The previous 6+ hour projection drops to a few minutes — the deep
movie= chain was the wall, not the encoder.
See feedback memory:
- feedback_recap_subtitles_required.md
- feedback_recap_ac24_cli.md (next-iter cache layer)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ElevenLabs (via the /api/say proxy) is the only real-money step in the
recap pipeline besides photo gen. Hashing the narration text + voice
config + checking out/recap.mp3.hash lets reruns skip the API hit when
nothing changed. --force overrides.
This unblocks $0 reruns of an episode (audio + photos already cached).
First step toward the broader ac-24 CLI cache layer (see memory note
feedback_recap_ac24_cli.md).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Doctrine: every dossier cover illustration must be sourced, not blind-prompted.
Each visual element (founder, building, signature object, brand color) traces
to a real reference — photograph, interview, physical artifact, brand asset.
Per-dossier figures/cover-sources.md documents:
- the visual elements present in cover-prompt.txt
- the source for each (URL, photograph, founder name, building, etc.)
- founder + key people referenced (or deliberately not depicted)
- what was excluded and why
- citation log (URLs, ProPublica EINs, Wikipedia, primary docs)
Covers 13 dossiers: rhizome, sfpc, eyebeam, recurse, internet-archive,
mellon, pioneer-works, new-inc, studio-museum, hathitrust, the-kitchen,
machine-project, heavy-manners-library.
Cross-references called out: Kaganskiy (NEW INC → Eyebeam), Maya Man
(SFPC supporter + Heavy Manners web designer), 1200 N Alvarado tenancy
chain (Echo Park Film Center → Machine Project → Heavy Manners Library).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Earlier commit landed h264_videotoolbox by accident (works on Apple
Silicon, missing on Linux). Oven failed with "Unknown encoder
h264_videotoolbox". Switch to libx264 -preset ultrafast -crf 22 — works
everywhere, ~5 min encode for 280s of 1080×1920 with the 139-overlay
filter chain.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The 139-deep movie= subtitle overlay filter graph saturates a single
ffmpeg thread (1 core fully consumed, output file stalled at the
filter-init phase on the oven). Dropping libx264 from medium → ultrafast
trades ~2x file size for ~10x encode time. CRF 22 keeps quality
acceptable for 1080×1920 vertical reels. Without this the oven encode
projects to 5+ hours; with it, ~5 min.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
networkidle0 sometimes hangs on oven for slides with multi-MB base64
photos embedded inline (build 67f9ee23-8 timed out at slide 07_hp_plotter
after rendering 6 slides successfully). domcontentloaded fires once the
DOM is parsed, which is all we need before screenshot — data URLs render
synchronously, no network to wait on. 90s timeout for slow CPU safety.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
slides.mjs / subtitles.mjs / screenshots.mjs hardcoded the Mac-only
puppeteer module path, system/public/ font paths, and Google Chrome
executable. Resolve puppeteer dynamically across local-dev and
/opt/oven/node_modules; build font/PALS paths from a REPO constant; let
puppeteer use its bundled Chromium on Linux. screenshots.mjs picks up
the same puppeteer resolver so the (currently unused) screenshot-cache
path won't blow up if it's ever wired into a slide.
Recap pipeline now runs end-to-end on the oven.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
New first-pass dossiers (with full IRS XML / public-disclosure data folders):
- arxiv-eyebeam (Eyebeam, NYC 1996–, 14 FYs of P&L, 6-ED chain, 3 locations)
- arxiv-recurse (Recurse Center, NYC 2011–, recruiting-funded model)
- arxiv-internet-archive (IA, SF 1996–, Hachette + UMG cases, FY23 cliff)
- arxiv-mellon (Mellon Foundation 1969–, funder-flip dossier; recipient
spotlight cross-references Rhizome / IA / Eyebeam / Pioneer Works)
- arxiv-pioneer-works (Pioneer Works, Brooklyn 2012–, Yellin-as-funder)
New cover layout for all 7 dossiers (rhizome + sfpc rebuilt to match):
- pals SVG moved to top-right (3.5em), small but visible
- AI-generated colored-pencil illustration becomes the hero image
- creation date + revision counter line under URL
New tooling:
- papers/bin/gen-cover.mjs: colored-pencil cover generator using OpenAI
gpt-image-2 (no portrait refs; per-paper figures/cover-prompt.txt;
consistent style prefix baked in for series consistency)
- papers/hitlist.md: dossier candidate index, sorted by data tractability
Registration:
- All 7 added to papers/SCORE.md and papers/cli.mjs PAPER_MAP
- All 7 added to papers/metadata.json (created/revisions surfaced on cover)
- platter.html refreshed via sync-platter.mjs
Each dossier folder includes: <slug>.tex (full preamble OTF Latin Modern
via filenames so xelatex renders identically on macOS + Linux), data/
folder with README + per-org CSVs (financials/people/funders/grants/
timeline/locations/programs/etc), references.bib, figures/cover.png +
cover-prompt.txt.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>