- llms.txt refreshed + linked in footer: The
/llms.txt from Session 10 still existed and was live but predated this sprint. Added an 'Artifacts & community voting' section (published entries, the 40-vote √-weighted model explained, voting close), a 'How to enter' subsection (native title + markdown body + image attachments + optional doc link, and the CC BY-SA 4.0 grant), and /artifacts to Key pages. Also added a visible llms.txt link to the site footer across all 13 pages + the SSR artifact page (it was previously undiscoverable, root-only by convention) so people/agents can find or copy it.
- Shuffle: added an Artifact Type card (4th pool):
/shuffle now draws a fourth prompt element — an artifact FORM to write as — from a 99-item pool (grocery list, police report, eulogy, billboard, epitaph, will & testament, YouTube comment, …; deduped). Grid moved from 3-across to a balanced 2×2 (still 1-col on mobile). The new card settles LAST in the slot-machine animation and now carries the completion callback (reveals the submit CTA). The drawn type is stored in the prompt object as artifactType (in sessionStorage + the shuffle_prompt recorded with each entry), and the /submit prompt banner shows an 'Artifact Type' row (guarded so older prompts without one don't render 'undefined'). Header + 'How it works' copy updated to four pools.
- Contest deadline surfaced on /artifacts + voting moved to Aug 2: The submission deadline wasn't prominent on the Artifacts page, so added a full-width amber countdown banner at the top: 'X days left to enter … (deadline July 31) — submit your artifact →', computed client-side in whole calendar days with final-day and closed states. SEPARATELY, moved the VOTING close from July 31 to end of August 2, 2026 (midnight PT =
2026-08-03T07:00:00Z, VOTE_CLOSE in _shared/voter.js) so there's a voting window on the final entries. Updated everywhere: server 403 message, on-page vote-bar copy, llms.txt. The two deadlines are now distinct and both surfaced (submissions July 31 via the banner, voting Aug 2 via the vote bar).
- Licensing decision — CC BY-SA 4.0 (researched): Investigated how shared-universe fiction projects license contributions. The SCP Foundation uses Creative Commons Attribution-ShareAlike (CC BY-SA 3.0) — attribution + share-alike, commercial use allowed — which is the proven model for keeping a universe freewheeling for remixing. The qntm precedent (There Is No Antimemetics Division, SCP → Del Rey 2025) is exactly the 'don't block the next commercial writer' concern: he could publish only by stripping SCP-licensed names/concepts, because ShareAlike binds derivatives that still carry shared elements. Decision: adopt CC BY-SA 4.0 (SCP is on 3.0; CC recommends 4.0). Accepted trade-off: a writer can go commercial with their own original material but not re-enclose the shared toybox. LOCKED IN.
- Required license checkbox + server enforcement (migration 006): Added a REQUIRED agreement checkbox to
/submit linking to the CC BY-SA 4.0 deed; the entry cannot be submitted unchecked (client + server). submit.js requires license === 'CC-BY-SA-4.0' and stores it in the new submissions.license column (schema/006_license.sql, applied to prod). Chosen now because there are still only 2 participants — cleanest moment to establish the grant. NB: the 3 pre-existing entries have license = NULL (submitted before the requirement); their grants must be collected out-of-band before those works are treated as CC-licensed.
- License marking across public + admin surfaces: CC requires the work be marked. Added a 'Licensed under CC BY-SA 4.0' notice (with author + link) to the foot of each SSR artifact page (
functions/artifacts/[slug].js, shown only when the entry actually carries the license), a licensing bullet on /contest, and a CC note on the /artifacts index. The admin dashboard + CSV export now show each entry's license (or 'none — pre-license entry'); export CSV also gained title + status columns.
- Voting deadline — closes July 31, server-enforced: Voting now closes at end of July 31, 2026 (midnight Pacific =
2026-08-01T07:00:00Z), defined once as VOTE_CLOSE in functions/_shared/voter.js. POST /api/artifacts/votes returns 403 after close so late ballots genuinely do not count (not merely hidden); GET /api/artifacts exposes voting_open + vote_close. The /artifacts page shows 'Voting closes July 31, 2026' while open, and after close disables the steppers/Save and shows 'Voting closed — scores below are final' while KEEPING scores visible. Verified both states locally (backdated the constant to force the closed path, then restored). Timezone is midnight Pacific — trivially changeable if a different cutoff is wanted.
- Admin review backend + cookie auth: Built a gated admin dashboard at
/admin/ to review and publish submissions instead of CSV/D1. Auth is stateless and Resend-free: POST /api/admin/login exchanges the existing ADMIN_SECRET for an HttpOnly cookie whose value is sha256(secret) (raw secret never in the cookie); functions/_shared/adminSession.js isAdmin() verifies the cookie OR the legacy X-Admin-Token header, so export.js keeps working. New endpoints: GET /api/admin/submissions (all entries + status + media), POST /api/admin/review (approve/reject/pending; approve sets pub_slug/pub_blurb, defaults pub_title from the entrant title, enforces slug uniqueness + reserves the-zoo/the-big-man). Note: Cloudflare Access on /api/admin/* is STILL not configured — the admin secret is currently the only gate.
- Submission model changed to native content (mid-contest): The contest moved from 'submit a Google Doc link' to native content: entrants now type a title + markdown body (stored in D1) and optionally attach images (stored in R2
jamverse-media, referenced in new submission_media table). The Google URL field is kept but OPTIONAL (for rich visual/comic layouts). Rewrote functions/api/submit.js to accept multipart/form-data (title/body required, up to 5 images at 5 MB each, image/* only), public/submit.html (native form), and public/contest.html copy. google_doc_url stayed NOT NULL at the SQL level (empty string when blank) to avoid a live-table rebuild. Locked-in decision after weighing the format-heterogeneity risk; existing Google-link entries are grandfathered.
- Safe markdown renderer:
functions/_shared/markdown.js renders entrant markdown with an escape-FIRST strategy — the whole string is HTML-escaped before any markdown transform runs, so users cannot inject raw HTML; only the tags this module emits appear. Links are restricted to http(s)/mailto. Supports headings, bold/italic, code, lists, rules, paragraphs. Verified live: <script> is escaped, javascript: links neutralised, while real markdown renders. Deliberately not full CommonMark — enough for prose fiction.
- R2 image attachments + gated media serving: Images upload to R2 under
submissions/<id>/<n>-<name>. New functions/api/media/[[key]].js serves an object ONLY if its owning submission is approved, or the requester is admin (so pending entries' images can be previewed in review but aren't publicly leakable). This is the first code to actually use the MEDIA R2 binding. Per decision, images are stored but NOT rendered inline yet — artifact pages link out to them; inline rendering can come later with no schema change.
- Per-artifact SSR pages + Artifacts index: Approved entries publish to a new Artifacts section (nav added across all pages).
functions/artifacts/[slug].js server-renders each artifact at clean URL /artifacts/<slug> (title, author, rendered body, image link-outs, optional original-doc link). Critical gotcha found + fixed: the dynamic function was SHADOWING the two hand-authored static pages (public/artifacts/the-zoo.html, the-big-man.html) in wrangler pages dev — the function now calls next() for those reserved slugs to fall through to the static asset. public/artifacts.html is the client-rendered index.
- In-place backfill tool for legacy entries: To migrate the pre-existing Google-link entries into the native model WITHOUT losing submitter attribution or creating duplicate rows, added
POST /api/admin/edit (multipart: id, title, body_md, appended images) + an 'Edit content' panel on each admin card. It only changes title/body/media — name/email stay with the original submitter. Used in prod to backfill Kannen's two entries; #3 (image-only) still needs its poster image uploaded, and Sachin's #1 is still pending backfill.
- Artifacts community voting (anonymous, √-weighted): Implemented the Protocol Institute symposium voting model WITHOUT login (per decision): each browser gets a 40-vote budget spent linearly across approved artifacts; an artifact's score = Σ√votes across voters, so concentration has diminishing returns and spreading is rewarded (no member tiers → weight 1). Identity is an anonymous
jv_voter HttpOnly cookie minted in functions/_shared/voter.js — the ONLY place identity is minted, so it can later be swapped for Turnstile/PIN without touching vote logic. artifact_votes table (migration 005); GET /api/artifacts returns scores + your ballot + budget (now no-store); POST /api/artifacts/votes is replace-all with budget enforcement + approved-id validation. Voting UI on /artifacts: steppers, remaining-budget bar, live scores, Save. KNOWN trade-off: clearing cookies yields a fresh ballot (soft integrity), accepted for a community vote.
- Email notification built but DORMANT:
functions/_shared/notify.js sends a best-effort Resend email to sachben91@gmail.com on each new entry, wired into submit.js via waitUntil (never blocks/fails a submission). It is a silent NO-OP unless RESEND_API_KEY is set. Deployed but not activated — user chose to rely on the admin dashboard for now. To enable: create a Resend account with sachben91@gmail.com (self-send needs no domain verification), then wrangler pages secret put RESEND_API_KEY. Can be removed if not wanted.
- Deployed to production + schema migrations 003/004/005: All of the above is LIVE. Applied additive migrations to prod D1:
003_review_and_publish.sql (status + pub_* on submissions), 004_native_content.sql (title, body_md, submission_media), 005_voting.sql (artifact_votes). Pre-flighted the prod schema first to avoid duplicate-column errors. NB: there are now 3 real entries (Sachin #1, Kannen #2/#3), not the 1 that status.md claimed. Test data lives only in the local miniflare store and was never pushed. A stray test ballot cast during prod smoke-testing was deleted.
- Local dev gotcha (record for next time):
wrangler pages dev does NOT read [[d1_databases]]/[[r2_buckets]] from wrangler.toml — bindings must be passed as flags: wrangler pages dev --port 8788 --d1 DB=jamverse-db --r2 MEDIA=jamverse-media. Also, the flag-bound local D1 store is a DIFFERENT sqlite file than the one wrangler d1 execute --local writes, so seed data must be applied directly to the pages-dev store (via sqlite3 on .wrangler/state/v3/d1/miniflare-D1DatabaseObject/*.sqlite). Secrets for local come from a gitignored .dev.vars.
- Site favicon (J mark): Added a brand favicon — a cream “J” on the amber accent (#9C4A00) square, square corners to match the brutalist look. Primary is
public/favicon.svg (scalable, used by modern browsers); fallbacks favicon.ico (16/32/48/64 multi-size) and apple-touch-icon.png (180px) were generated with Pillow via a disc-stamped round-stroke render. Favicon <link> block injected after the viewport meta on all 12 nav pages, and into scripts/devlog_render.py so the generated devlog.html keeps it. The two dev pages (dev-orientation, devlog source) use a different single-title header and were left as-is.
- New story — The Big Man: Elizabeth Maher’s Legends & Ledgers story (published 2026-06-12) added across the site. It is the newest story, so on the homepage it is now the hero/Latest feature. Added optional per-story
img support to the STORIES data + hero/grid renderers (s.img || IMAGES[badge]) so the actual cover (downloaded to /assets/story-the-big-man.png, the 1200×630 og:image) shows instead of the generic universe image. Also added to stories.html (L&L group), flipped from “forthcoming” to a published link on the universe page, and added to llms.txt. Story counts bumped 14 → 15 in stories.html intro and llms.txt (devlog history entries left untouched).
- Mobile hamburger nav: Top menu overflowed/clipped on phones (wide-tracked JAMVERSE wordmark + 4 links exceed ~360px). Fixed with a CSS-only hamburger (checkbox-hack, no JS): hidden
<input> + 3-bar <label> injected before <nav class=site-nav> on all 12 pages; at ≤640px the nav collapses to a full-width dropdown below the sticky header, burger morphs to an X. Shared rules live in style.css; index.html has its own inline <style> (does not link style.css) so a matching block was added there with its local vars.
- Contest rename — Jamverse Jam Contest: Per request, “Contest #4” / “Protocolized Writing Competition #4” replaced everywhere with Jamverse Jam Contest (index banner + contest-box label, contest/shuffle/submit titles & eyebrows, Stockton toybox copy, llms.txt). Locked-in name; theme is still Stigmergy, deadline July 31. Devlog history (devlog.json/html) intentionally not renamed.
- Contest banner mobile fix: The amber notice-bar (index only) is a fixed-36px sticky bar with
white-space:nowrap; overflow:hidden, so its 4 centered items clipped on phones — and the sticky header is pinned at top:36px, so wrapping to two lines is not an option. Solution: the title is now a link (.notice-title → /contest) and at ≤600px the bar collapses to just the contest name (long span, Enter CTA, and prompt link hidden), keeping one line. Note: verifying mobile via headless Chrome was unreliable (the engine clamped the viewport to ~500px and the sticky bar centers within full layout width, so cropped captures looked shifted); user confirmed it reads fine on a real phone.
- Standalone example-artifact pages: Added two full worked examples as their own pages under a new
public/artifacts/ directory — /artifacts/the-zoo (Zoothesia social history of “The Zoo,” a V1→V10+ protocol-evolution timeline) and /artifacts/the-big-man (Legends & Ledgers collectible product listing, “You Were Never Alone,” with a Keepsake Card verse and a “do not leave at the Disposition” care note that cross-references the existing Disposition plaque artifact). These complement — do not replace — the inline Example artifacts carousel on /contest, which was left untouched; the longer-form pieces are too big for a carousel card.
- Linked from “What’s an artifact?”: Added a two-item “Want to see one in full?” list at the end of the What’s-an-artifact section in
contest.html pointing at the two new pages. Used extensionless URLs to match the rest of the site (CF Pages serves .html at the clean path).
- Shared artifact-page styles: Added a reusable
.artifact-doc-* component block to public/assets/style.css (meta tag, title, subtitle, body card, version blocks, poem, prev/next nav) rather than duplicating per page. Reuses existing theme tokens and the universe .badge-* colors — no new colors introduced.
- Standalone-artifact refinement: Per review, removed the editorial “An example of what a contest artifact can look like…” kicker paragraphs and the “Example artifact ·” meta prefix so each page reads as the artifact itself, not a description of it — the h1 is now the artifact’s own title and the card is its body. Fixed odd headline spacing: dropped forced
<br> breaks, loosened title line-height, and moved the secondary line into a proper italic .artifact-doc-subtitle. The “example” framing now lives only on /contest where the links introduce them.
- AI assistance: checkbox → free-text field: Replaced the boolean 'I used AI' checkbox on
/submit with an optional textarea prompting entrants to describe what part of the process they used AI for. Changes span four layers: form (public/submit.html textarea named ai_usage + help text + client JS), backend (functions/api/submit.js now reads ai_usage and auto-derives the legacy used_ai flag = 1 when text is present), schema (new ai_usage TEXT column via schema/002_add_ai_usage.sql, applied to live D1; schema/001_init.sql updated to match for fresh installs), and CSV export (functions/api/admin/export.js now emits the full ai_usage text alongside the yes/no used_ai). Deployed and verified live. Note: any non-empty text sets used_ai=1, so an entrant typing 'no AI' reads as AI-used — blank means no AI.
- First live submission received + how to view: Test submission #1 (Sachin, stockton-chronicles) landed in the live DB, confirming the end-to-end form→D1 path works. Two review methods documented: direct D1 query via
wrangler d1 execute jamverse-db --remote --command "SELECT ..." (fastest for dev, uses existing token) and the admin CSV export at /api/admin/export (needs ADMIN_SECRET header; Cloudflare Access on /api/admin/* still pending). Test row #1 left in place for now — decide whether to delete before contest judging.
- Admin review-site design discussion (NOT built): Explored a future admin site to review/judge submissions instead of CSV/D1. Proposed shape: protected
/admin page + GET /api/admin/submissions JSON API + new D1 judging fields (status/score/notes); left list-filter + right detail with artifact rendered inline. Key fork is the submission model — current Google-link-based (cheap, embeds) vs. native uploads to the existing jamverse-media R2 bucket (text in D1, images in R2; nicer to judge but more build + moderation surface + changes the live contest flow). Auth options: PIN login (reuse PI website repo's email-PIN + session-cookie pattern, buildable now) vs. Cloudflare Access (cleaner but org-admin-dependent/pending). User leaning toward native R2 uploads + PIN login but wants to clarify scope before deciding — open questions: switching submission model mid-contest (live until July 31), text box vs. file uploader (or both per entry), R2 size/type limits + serving (public vs signed), admin allowlist (who judges). To be resumed next session.
- Protocolized GitHub access discrepancy flagged: While checking feasibility of reusing PI's member login, found the lead-dev GitHub token (
sachben91, scopes repo + read:org) can read all Protocol-Institute repos incl. private ones (website, c3po, admin) — broader than this project's CLAUDE.md isolation claim ('no access to any other PI infrastructure'). Only the public website auth code was read to answer the question; the admin keys/security repo was deliberately not opened. Worth org-admin attention: either the docs are wrong or the token scope is too broad.
- Session 11 tagline work deployed: Ran the first production deploy of the universe tagline refresh and Trainverse re-pitch (committed but undeployed at the end of Session 11). Verified live on
jamverse.protocolized.io by confirming the new Lisbon→Laos Trainverse copy serves from /llms.txt. Session 11's deployed flag was retroactively flipped to true to reflect this.
- Contest notice bar restyled to amber: The sticky top banner (
.notice-bar in index.html) was changed from a low-contrast light card background (--bg-card with muted text) to a full amber background (--amber, #9C4A00) with white text — base text at 85% white, strong and links at solid white, links bold and underlined (underline drops on hover). Goal was to make the contest call-out stand out more. The banner exists only on index.html, so no other pages needed updating. Note: this CSS change lives in index.html and is committed as part of this session's wrapup, but was deployed live before commit.
- Trainverse re-pitched: Replaced the old Trainverse framing (Lagos→Singapore, 2,347 passengers, 17 jurisdictions, 23,300km) with a new author-supplied pitch everywhere it appeared: a political thriller on a train from Lisbon to Laos through Eastern Europe, Siberia, China and Southeast Asia, framed as a moving special economic zone balancing priorities across legal jurisdictions. Updated in four places that previously carried the stale copy —
universe/trainverse.html (header desc), contest.html (toybox column desc), llms.txt (universe description), and the UNIVERSE_TAGLINES map in index.html. This closes the long-standing 'Trainverse tagline' open item in status.md; the 'motion is legal protection / ECOROUTE never stops' beats and the named toybox elements (bio-bands, Pono, Mirage Handler, Caduceus/Zoothesia DRZ, Car 7) were preserved.
- Universe taglines added to story UI: Introduced a
UNIVERSE_TAGLINES map (keyed by universe badge/slug) on both index.html and stories.html. On the front page the hero story now shows its universe tagline above the title (.hero-universe-tagline, italic serif), and story-grid cards reveal the tagline as an overlay caption on hover (.story-grid-img-caption over a darkened image; required adding position:relative to the image wrap). On stories.html, selecting a universe filter now displays that universe's tagline in a banner below the filter buttons; the banner hides on the 'all' filter. Taglines are defined inline in each page's script rather than centralized — keep the two maps in sync when copy changes.
- llms.txt published: Added
public/llms.txt following the emerging llms.txt convention (analogous to robots.txt for AI agents). The file gives any AI assistant or agent hitting jamverse.protocolized.io/llms.txt a complete structured picture of the site in one request: a one-paragraph site description; all four universe descriptions with named toybox elements and links to full universe pages; all 14 published stories with title, universe, publish date, author, hook, and direct URL to protocolized.io; full contest brief including the stigmergy definition, prizes, deadline, and links to /contest, /submit, and /shuffle; and an index of all key pages including the Protocol Lexicon. Format is clean markdown, no HTML.
- PR #1 merged — story links migrated to protocolized.io: Reviewed and merged PR by
vgururao. All 12 story links previously pointing to protocolized.summerofprotocols.com/p/* updated to protocolized.io/p/* across index.html, stories.html, and all four universe pages. The two Randy Lubin Stockton stories (The Caucus, Joan Henry vs the Algorithm) previously on randylubin.com now point to protocolized.io/p/* placeholder pages with series navigation and a coming-soon notice — these will upgrade automatically when the stories are published on Protocolized. Deployed immediately after merge.
- Brutalist design system: Complete visual overhaul of the site. Replaced the warm-dark magazine palette with a full brutalist system: ink-black (
#111) structural rules, amber (#9C4A00) for all interactive elements, warm cream ground (#FDFAF5) and parchment alternates. Zero border-radius across all elements. All buttons are 2px solid borders (amber fill or ink outline). Typography scaled up — h1 at clamp(2rem, 5vw, 3rem), h2 at 1.85rem, h3 as ruled uppercase labels with 2px bottom border. Nav: white background, 3px ink rule, JAMVERSE in tracked 0.3em all-caps. Footer: 3px ink rule top, all-caps ink links. Changes cascade from style.css globally to all pages.
- Magazine front page redesign (index.html): Stripped the previous universe-card grid in favour of a story-first magazine layout. Hero section: 2-column split (text left, universe image right), giant serif title at
clamp(2.75rem → 5.5rem), overline rule, monospace date, amber "Read on Protocolized" link. Recent stories: 2×2 grid, pure typography, 2px ink rules between cells, no images at rest. Archive: compact list, 1px light rule between items. Contest panel: hard 3px bordered box with inner rule dividing two halves. Universe directory: bold 2px bordered tag buttons. Story data defined as a JS array ordered most-recent-first — to feature a new story, prepend one entry.
- Hover image expansion on story cards: The 4 recent story cards in the featured grid now reveal a 210px universe artwork image on hover. The image wrapper starts at
height: 0 and expands to 210px via cubic-bezier(0.4, 0, 0.2, 1) transition. Card grows to accommodate the image — no layout shift on other cards. Images are already in public/assets/ from Session 6. The render function was updated to wrap card content in a .story-grid-content div so padding is preserved below the image.
- Intro tunnel animation: Full-screen intro overlay on first visit (per session via
sessionStorage). Background: jamverse-plate-1.png at 50% opacity over near-black (#080604) with dual vignette gradients. Title: JAMVERSE in Space Grotesk 700 at clamp(3.5rem → 11rem), white with heavy text-shadow. Tagline: full "you are a storyteller" declaration in Lora italic at clamp(1rem → 1.3rem). On first scroll/wheel/key/tap: tagline and eyebrow fade immediately, title scales to 4.5×, letter-spacing explodes to 2.5em, blur applied — tunnel effect. Overlay fades at 280ms, gone at 1000ms. Respects prefers-reduced-motion. Click also triggers for mobile users.
- Contest page redesign: Removed Stigmergy section entirely. New structure: dark parchment hero with prize row (2px ink borders), full inline toybox grid (4 columns, all 47 elements browsable), Oblique Protocols card (Eno-inspired prompt CTA), condensed body sections (artifacts, traffic jams, logistics), example artifacts carousel at the bottom. Carousel auto-advances every 60 seconds, side-arrow circular buttons, dot indicators. Toybox grid uses ink dividers — each universe column has badge, name, description, item list, and footer link.
- Real publish dates added to story ordering: Fetched actual publish dates from all 14 Protocolized/Substack URLs. Correct chronological order now drives the magazine layout: The Overloaded Train (May 22, 2026) is the hero, All You Can Do Here Is Leave (May 8) and The Headless Empire (Apr 23) in the recent grid. The Caucus and Joan Henry vs the Algorithm show 2023 (no date available on randylubin.com pages).
- /shuffle prompt generator: New standalone page at
/shuffle. Three dark cards — Technology, Thematic Question, Universe Element — each backed by a curated pool (15 technologies, 15 questions, 16 universe elements drawn from all four universes). Clicking Shuffle runs a staggered slot-machine animation: each card rapidly cycles through random pool items before snapping to the final result. Universe attribution badges appear on the tech and element cards after settle. "Submit with this prompt →" appears after the first shuffle; prompt is saved to sessionStorage. "Shuffle again" link if the first result doesn't land. Fully responsive — cards stack to 1-column on mobile at 760px.
- Prompt-aware submission form:
/submit reads sessionStorage('jamverse_prompt') on load. If a shuffle prompt is present, a dark banner appears at the top of the form showing the three drawn elements (technology, question, universe element) with a "Shuffle again →" escape. The prompt is submitted with the form as a shuffle_prompt field and stored in D1.
- D1 schema migration + Worker update:
schema/002_shuffle_prompt.sql adds a shuffle_prompt TEXT column to the submissions table — applied live via wrangler d1 execute --remote. functions/api/submit.js updated to accept and store the field. functions/api/admin/export.js updated to include shuffle_prompt in the CSV export column set.
- Contest page CTA + nav update: Dark CTA block added to the contest page intro (above the TOC): "Not sure where to start? Generate my prompt →". "Prompt" nav link added to all pages:
index.html, contest.html, submit.html, stories.html, all four universe pages, and dev-orientation.html.
- Legends & Ledgers universe page: The T.R.O.L.L. universe was renamed to Legends & Ledgers. Created
/universe/legends-and-ledgers.html with the full toybox provided by the universe author: overview, thematic questions, setting, shared geography & recurring figures (6 items), protocols & mechanisms (9 items), tone notes, all 5 stories (2 linked, 3 forthcoming), and a toybox section with 19 checkable elements across 4 categories. Updated all cross-references across stories.html, contest.html, index.html, and style.css — old /universe/troll is now a dead file, no longer linked. Story title updated from "TROLL" to "T.R.O.(L.L.)" everywhere.
- Protocol Institute → Protocolized: Removed all public-facing references to "Protocol Institute" and replaced with "Protocolized" — the magazine publishing the extended universes. Changes in:
index.html (page title, hero eyebrow), contest.html (stigmergy section, lexicon section), dev-orientation.html (subdomain description), data/devlog.json (description field). devlog.html regenerated. Internal dev docs (CLAUDE.md, wrangler.toml) retain "PI org" as a shorthand for the Cloudflare account context.
- Contest page rewrite: Full content rewrite of
contest.html. New intro with step-by-step "To enter" instructions. Worlds section moved before Artifacts and given new descriptions for all four universes (Stockton, Legends & Ledgers, Zoothesia from author copy; Trainverse placeholder pending). Stigmergy section expanded with four detailed worked examples (ants, termites, Wikipedia, Blum-Kozen maze automaton). Traffic Jams section updated to the new wording. Lexicon section removed (simplified). Protocol Lexicon requirement dropped from numbered entry requirements (now 3 requirements: toybox element, traffic jam, stigmergy). Toybox instruction updated to "at least one — preferably more than one".
- Form separation — /submit page: Submission form extracted from
contest.html into a new standalone public/submit.html at /submit. Contest page ends with a "Submit your entry →" CTA button linking to /submit. The submit page has a breadcrumb back to /contest. URL field updated to accept both Google Docs (docs.google.com) and Google Drive (drive.google.com) links — important for visual/comic panel submissions. Guidance note added under the URL field explaining both paths. Universe selection now validates (at least one required). All toybox JS and universe data live exclusively in submit.html.
- Pages Functions — submission handler + admin CSV export:
functions/api/submit.js patched: Google Drive URLs now accepted alongside Google Docs, returns actual D1 row ID as submission_number. New functions/api/admin/export.js at GET /api/admin/export — returns all submissions as a CSV (id, submitted_at, name, email, google_doc_url, universes, toybox_elements, used_ai). Protected by X-Admin-Token header checked against ADMIN_SECRET wrangler secret (set this session). A Zero Trust Access request was filed in zero-trust-requests.md for a CF Access policy on /api/admin/* as a second protection layer — pending org admin action. admin.local.md created (gitignored) as a local admin cheat sheet with the curl command and operational notes. CLAUDE.md updated: stack table, structure tree, secrets table, deployment section, and a new admin download section.
- Front page universe cards redesign: Four universe artwork images added to cards (zoothesia.jpg, stockton/cad.jpg, legends.png, trainverse.jpg) — served as static assets from
public/assets/. Cards restructured from outer <a> wrappers to <div> containers with separate inner links, enabling story links and explore links to coexist. Each card now shows: artwork image (3:2 ratio), badge, universe title (linked), description, 2–3 individual story links with ↗ arrows, and an "Explore →" footer link. Grid changed from auto-fill minmax(22rem, 1fr) to a fixed repeat(2, 1fr) — eliminates the orphaned-card blank space that appeared at wide viewports.
- Mobile responsiveness pass: Global input/textarea styles added to
style.css (full-width, border, focus ring). Tables made scrollable on mobile (display: block; overflow-x: auto). h2 and universe-header h1 font sizes reduced at 640px. Added 480px breakpoint in index.html — hero stacks to column, buttons go full-width, content-zone padding tightened. submit.html gets 600px breakpoint (form-wrap padding reduced, universe check badges unwrap). contest.html 600px breakpoint extended: submit CTA button full-width, stigmergy example boxes tighter padding.
- Zoothesia toybox complete: Wired the full Zoothesia toybox into
universe/zoothesia.html and the contest form JS. Universe page now covers: setting (Mayaford, Charntown, Chitram Row, Nayanaport, Shraville), technologies (The Zoo, Overlays, Kapala-Halo, Foulmaxxing/Phobisculting, Faceting, ProfBot), character (Oren — the Zoothetic psychopomp), thematic concerns, and the Zoo's slogans. Universe description rewritten to lead with Mayaford and the harm-prediction framing. Contest form JS array populated with 9 checkable elements. Contest world card description updated.
- First live deploy: CF API token received and placed in
.env (angle brackets from placeholder format removed after first failed auth attempt). Remote D1 initialised via wrangler d1 execute jamverse-db --remote --file schema/001_init.sql — 3 queries, schema live in WNAM. Site deployed via wrangler pages deploy public/ to jamverse.pages.dev. Deployment URL: 183b14ee.jamverse.pages.dev. Custom domain jamverse.protocolized.io pending DNS propagation confirmation from org admin. Form submissions now write to live D1.
- New Nature design direction: Replaced the warm off-white + teal magazine aesthetic with a new palette derived from the session artwork (Fig. 1): cool limestone background (
#E4E0D8), deep slate dark zone (#1A2028), phosphor teal accent (#00B8A8), geological badge palette per universe. Conceptual frame: natural history atlas meets Concrete Atlantis (Banham) — arcane + futuristic light. The X element is bioluminescent protocol signatures: the dark hero zone is the substrate, the phosphor accents are what the instruments detect. Outfit replaced with Space Grotesk throughout for UI labels — survey/instrument quality without going cold.
- Shared design system (
style.css): Extracted all shared styles into public/assets/style.css — CSS variables, reset, nav, typography, sections, cards, badges, buttons, story lists, universe page headers, toybox, tables, TOC, placeholder blocks, footer, responsive breakpoints. All six public pages now link to this file and carry only page-specific overrides inline. Previously each page had ~250 lines of duplicated inline CSS; now the shared file is the single source of truth for the design system.
- Landing page rebuild: Replaced the placeholder stub with a full two-zone layout. Dark slate zone: sticky nav, two-column hero (left: PI mark + wordmark + hook text; right: Plate I artwork with formal monospace caption). Limestone zone: contest strip, four universe cards in a seamless bordered grid with per-universe geological badge colors, stories CTA, dark footer. The artwork (
jamverse-plate-1.png) is treated as a natural history specimen plate — fish containing a city, literalising the New Nature concept.
- Jamverse hook copy placed: Final hook text placed in
contest.html intro section as italic body copy: "Your bio-band rekeyed at the Caduceus DRZ, unmaking the last twenty minutes from every record that had held them. The AI agent in the smart glasses has attended this conversation since before you sat down — diligent, accountable to someone else. The perceptual classifier withdrew three people from this room; they remained, warm, displacing air, resolved by nothing. The space has been narrowing since you entered. It keeps offering you one door. Welcome to the Jamverse." Draws specific details from all four universes; Virginia Woolf-influenced verb-agency on the technologies.
- Story hooks — all 14 stories: Fetched all 14 story pages to read actual opening paragraphs and subtitles, then wrote non-spoiler one-line hooks for each. Zoothesia stories correctly sequenced as chapters 1–6 (confirmed from subtitles — Perception Must Preserve is Ch. 1, Minor Differences Repeating Forever is the finale). Caught Elizabeth Maher as the author of All You Can Do Here Is Leave. Badge layout fixed: tags moved inside
.story-body to sit above the title rather than as a left-side flex item; display: inline-block so tags hug their content width.
- Developer environment setup: Cloned repo for the first time on lead dev machine. Wrangler 4.98.0 installed to
~/.npm-global/bin/wrangler (global /usr/local/lib was permission-locked); ~/.npm-global/bin added to PATH in ~/.zshrc. .env created with CLOUDFLARE_ACCOUNT_ID pre-filled and marked Dropbox-ignored via xattr. CLOUDFLARE_API_TOKEN placeholder remains — token not yet received from org admin. All wrangler commands are running against local miniflare; nothing has touched live CF infrastructure this session.
- Site architecture decision: Settled on six public-facing pages:
/ (landing), /stories (filterable index), /contest (full contest call + form), /universe/[slug] (four universe pages). Submission backend implemented as a CF Pages Function at functions/api/submit.js rather than a separate Worker — this keeps D1 bindings in one wrangler.toml and deploys atomically with the static site. Schema in schema/001_init.sql.
- Contest call page and submission form: Built
public/contest.html with the full Contest #4 (Stigmergy) call rendered as a navigable editorial page — TOC with anchors, sections for artifacts, stigmergy, traffic jams, lexicon, the four worlds, logistics/prizes, and the submission form. Form submits JSON to /api/submit; the Pages Function validates inputs, enforces the 3-submission-per-email cap, and writes to D1 (name, email, google_doc_url, universes, toybox_elements, used_ai, ip_hash). Toybox checkboxes are JS-driven: universe toggle reveals that universe's elements. TROLL and Zoothesia toyboxes are placeholder pending author input.
- Universe pages: Four pages at
/universe/[slug]. Stockton Chronicles and Trainverse are complete with full toyboxes: Stockton has 13 elements across technology, setting/economy, and thematic categories; Trainverse has the three absolute rules, technology (bio-bands, ECOROUTE, Pono, Mirage Handler), de-realized zones (Caduceus DRZ, Zoothesia DRZ), and the 'the train is ___' constraint. TROLL and Zoothesia pages have story links and styled placeholder blocks — the Zoothesia page includes a crossover note pointing to the Zoothesia DRZ in the Trainverse.
- Story index and landing page:
public/stories.html lists all 14 stories across the four universes with color-coded badges and JS universe filter tabs. public/index.html redesigned from the placeholder stub to a full landing page: contest banner (links to /contest), four universe cards in a responsive grid, 'browse all stories' CTA. Body copy writes the site as a stigmergetic project — each artifact becomes scaffolding for the next.
- Jamverse hook copy: Wrote the contest page opening hook: "Your bio-band rekeyed at the Caduceus DRZ, unmaking the last twenty minutes from every record that had held them. The AI agent in the smart glasses has attended this conversation since before you sat down — diligent, accountable to someone else. The perceptual classifier withdrew three people from this room; they remained, warm, displacing air, resolved by nothing. The space has been narrowing since you entered. It keeps offering you one door. Welcome to the Jamverse." Draws specific details from all four universes; Virginia Woolf-influenced treatment gives technologies verb-like agency. Placed in
contest.html as italic body copy above the TOC.
- Local dev environment: Local D1 initialized via
wrangler d1 execute jamverse-db --local --file schema/001_init.sql. Dev server running via wrangler pages dev public/ --port 3000 — serves static files and Pages Functions against miniflare. Form submission is fully testable locally. Deployment to live CF infrastructure requires the CLOUDFLARE_API_TOKEN in .env (not yet received); three commands deploy when ready: source .env, wrangler d1 execute --remote, wrangler pages deploy.
- Site-wide styling overhaul: All three public pages (
index.html, devlog.html, dev-orientation.html) restyled to match the protocolized.io aesthetic: warm off-white background (#F9F8F5), Instrument Serif for headings, Lora for body, Outfit for UI labels, JetBrains Mono for code, teal primary (#0F6E56) for links and accents. The original dark aesthetic was unreadable and inconsistent with the parent brand. The render script (scripts/devlog_render.py) was updated to produce the new styling on future devlog regenerations.
- Developer orientation HTML page: Created
public/dev-orientation.html — a styled, navigable HTML rendering of orientation.md served at /dev-orientation. Covers the full CF stack, wrangler auth, D1/R2/Worker bindings, secrets, Zero Trust, and session rituals. Includes a table of contents with anchor links. Hand-authored HTML (not auto-generated) since the orientation content changes infrequently and does not share the devlog's data-driven structure.
- Session rituals section and coding agent guidance: Moved the session rituals section to the top of the developer orientation (previously last). Added a new subsection on getting a coding agent to follow the ritual: Claude Code reads
CLAUDE.md automatically and enforces startup/wrapup when prompted; other agents must have the file pasted into context. The guidance names specific trigger phrases ("new session", "wrap up") so the dev knows exactly how to engage the agent. Updated both orientation.md (markdown source) and dev-orientation.html (rendered page) to match.
- Devlog github attribution: Added a
github field to the devlog entry schema — the GitHub handle of the session lead. Backfilled Session 1 with vgururao. The render script now outputs the handle as a linked @handle in the session meta line. Updated CLAUDE.md schema docs and orientation.md wrapup instructions to require the field. Attribution matters once there are multiple contributors.
- Landing page navigation links: Added two nav links to
index.html below the "under construction" notice: Devlog (primary teal button) and Developer Orientation (outlined secondary button). The landing page was previously a dead end with only a link back to protocolized.io.
- Repo and local clone: Created
Protocol-Institute/jamverse as a private GitHub repository. Cloned locally to protocol-institute/jamverse/. Initial scaffold: README.md, CLAUDE.md, status.md, .gitignore.
- Cloudflare Pages project: Created CF Pages project
jamverse on the PI org account (7e8c7969b2464d23795c555bc6a32af8) via CF API, then deployed stub index.html via wrangler — dark holding page with Protocolized wordmark and PI mark. Live at jamverse.pages.dev.
- Custom subdomain: Added
jamverse.protocolized.io as a custom domain via CF Pages API. CF recognized the zone (protocolized.io) is in the same account but could not auto-create the CNAME because the org token lacks Zone DNS:Edit scope — a known gap to address. Subdomain added through CF Pages dashboard UI as a workaround; DNS propagation and TLS provisioning pending at session close. Workers custom domains (e.g. c3po) handle DNS automatically via wrangler; Pages custom domains require a separate verification flow.
- D1 database: Created
jamverse-db (ID: 6826920c-3f30-438a-ab66-e34a26cda7d3) in region WNAM on PI org CF account. Single database for the full project: users, roles, content, submission metadata. Binding name: DB. D1/R2 creation is account-level and outside the dev token scope — org admin creates, dev operates.
- R2 media bucket: Created
jamverse-media on PI org CF account. Key convention: submissions/{id}/ for content media, avatars/{user_id}/ for profile images, assets/ for shared static assets. Binding name: MEDIA. PI mark (protocolized_mark.png) uploaded to assets/ as first R2 object.
- PI mark on stub page: Copied
protocolized_mark.png from protocolized-website/public/, uploaded to jamverse-media/assets/protocolized_mark.png via wrangler (--remote flag required — wrangler 4.x defaults to local miniflare when wrangler.toml is present). Also placed in public/assets/ for Pages static serving, since there is no Worker yet to proxy R2 objects. Wired into index.html inverted and at 25% opacity for the dark background.
- Dev API token: Created a scoped Account API Token (
jamverse-dev) for the lead developer via CF dashboard — Account API Tokens rather than user-profile tokens so the credential is owned by the org, not an individual. Scopes: Pages:Edit (jamverse project), D1:Edit (jamverse-db), Workers R2 Storage:Edit (jamverse-media bucket only), Workers Scripts:Edit (account-level, required for wrangler secret put). Initial token value was captured before creation was finalized and failed validation; rolled to get the live value. Developer does not need a CF account or dashboard access.
- Session rituals and devlog: Established mandatory startup/wrapup ritual in
CLAUDE.md: startup requires running date for accurate timestamps; wrapup requires a devlog entry, devlog re-render, status update, and wrapup checklist post before the session is considered closed. data/devlog.json is the source of truth; scripts/devlog_render.py renders it to public/devlog.html, served at /devlog. Renderer outputs newest-first, dark aesthetic matching index.html. Pattern copied from protocolized-website and PI website projects.
- Developer documentation:
orientation.md — full onboarding guide covering CF stack, wrangler auth (no CF account needed), D1/R2/Worker usage, session rituals, and Zero Trust request flow. zero-trust-requests.md — template for requesting CF Access policies; org admin acts on these, no code changes required on dev side. SECURITY.md — .env creation, Dropbox exclusion via xattr, no secrets in tracked files, accidental-commit response (roll immediately, treat as compromised). Access model: dev is fully self-sufficient for all day-to-day ops; org admin handles D1/R2 creation, DNS, and Zero Trust.