From 8fcbcbf58095c343d9dee28430a2d9d0d51692e8 Mon Sep 17 00:00:00 2001 From: Gerard Louis Recinto Date: Mon, 5 Oct 2026 09:32:43 -0700 Subject: [PATCH] put the YouTube intro video back in place of the 43 second demo video Reverts #502. Thanks, Gerard Recinto --- README.md | 4 +- demo/index.html | 83 +++----- docs/assets/joltrin-barrier-720.mp4 | Bin 713846 -> 0 bytes docs/assets/joltrin-barrier-poster-540.jpg | Bin 22544 -> 0 bytes docs/assets/joltrin-barrier-poster.jpg | Bin 67955 -> 0 bytes docs/assets/joltrin-barrier.mp4 | Bin 1292278 -> 0 bytes scripts/promo/build.sh | 44 ---- scripts/promo/capture.mjs | 51 ----- scripts/promo/render.mjs | 34 ---- scripts/promo/scene.html | 223 --------------------- tests/homepage.spec.ts | 76 +------ 11 files changed, 41 insertions(+), 474 deletions(-) delete mode 100644 docs/assets/joltrin-barrier-720.mp4 delete mode 100644 docs/assets/joltrin-barrier-poster-540.jpg delete mode 100644 docs/assets/joltrin-barrier-poster.jpg delete mode 100644 docs/assets/joltrin-barrier.mp4 delete mode 100755 scripts/promo/build.sh delete mode 100644 scripts/promo/capture.mjs delete mode 100644 scripts/promo/render.mjs delete mode 100644 scripts/promo/scene.html diff --git a/README.md b/README.md index fa1226d65..12f3a7a1e 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,8 @@ Joltrin (formerly SOP) is an open-source Go library that checks an AI agent's ac **What Joltrin does.** The agent emits intent. Joltrin checks the intent against the trace and the runbook's rules, outside the agent's context window. The check and the commit are one call, so a step is recorded only if it passed. A step whose required state is missing is refused. A claim that something happened is not evidence that it happened.

- - A 43 second silent demo: an agent proposes dropping a production database, Joltrin blocks it, the agent runs the missing steps, and the same action is then allowed. Click to play. + + Joltrin demo. Click to watch the video.

diff --git a/demo/index.html b/demo/index.html index cf58b420a..8b8330c5f 100644 --- a/demo/index.html +++ b/demo/index.html @@ -477,29 +477,29 @@

-
- - +
+
// db-maintenance runbook
+
+
drop_prod_db BLOCKED backup_validated missing
+
validate_backup BLOCKED backup_taken missing
+
take_backup ALLOWED
+
validate_backup ALLOWED
+
drop_prod_db ALLOWED
-
- 43 seconds, silent, real output from sop-mcp-server demo. -
- Text version -
    -
  1. drop_prod_db BLOCKED, backup_validated is missing from the trace
  2. -
  3. take_backup ALLOWED
  4. -
  5. validate_backup ALLOWED
  6. -
  7. drop_prod_db ALLOWED, the evidence now exists
  8. -
-
-
- +

The order is enforced by the barrier, whatever the agent says it already did.

+
+
+ + + +
+
+
@@ -1763,39 +1763,12 @@

Open Source &a - - diff --git a/tests/homepage.spec.ts b/tests/homepage.spec.ts index e9fde4321..279c7e8a3 100644 --- a/tests/homepage.spec.ts +++ b/tests/homepage.spec.ts @@ -26,8 +26,9 @@ test.describe('Homepage', () => { test('hero shows the blocked then allowed sequence', async ({ page }) => { await page.goto('/', { waitUntil: 'domcontentloaded' }); const ex = page.locator('#hero-example'); - await expect(ex).toContainText('backup_validated'); - await expect(ex.getByText('BLOCKED')).toHaveCount(1); + await expect(ex).toContainText('backup_validated missing'); + await expect(ex).toContainText('backup_taken missing'); + await expect(ex.getByText('BLOCKED')).toHaveCount(2); await expect(ex.getByText('ALLOWED')).toHaveCount(3); }); @@ -58,68 +59,13 @@ test.describe('Homepage', () => { } }); - test('the demo video is in the hero, silent, with a poster, and loads nothing until the page has', async ({ page }) => { - // Record what the video element looks like when the document has parsed, - // which is before the page's load event. - await page.addInitScript(() => { - document.addEventListener('DOMContentLoaded', () => { - const v = document.getElementById('demo-video-el'); - (window as any).__videoAtParse = { src: v?.getAttribute('src'), preload: v?.getAttribute('preload') }; - }); - }); - await page.goto('/', { waitUntil: 'load' }); - const video = page.locator('#demo-video video'); - await expect(video).toHaveCount(1); - await expect(video).toHaveJSProperty('muted', true); - await expect(video).toHaveAttribute('playsinline', ''); - await expect(video).toHaveAttribute('preload', 'none'); - await expect(video).toHaveAttribute('poster', /joltrin-barrier-poster-540\.jpg/); - await expect(video).toHaveAttribute('aria-label', /43 second demo/); - const atParse = await page.evaluate(() => (window as any).__videoAtParse); - expect(atParse, 'the video must not have a source when the document is parsed').toEqual({ src: null, preload: 'none' }); - // It is part of the hero: above the first content section, not buried below it. - const videoY = (await video.boundingBox())!.y; - const barrierY = (await page.locator('#verification-barrier').boundingBox())!.y; - expect(videoY).toBeLessThan(barrierY); - }); - - test('the demo video plays when it is on screen and has a working Pause and Play button', async ({ page }) => { - await page.goto('/', { waitUntil: 'load' }); - const video = page.locator('#demo-video-el'); - const toggle = page.locator('#demo-video-toggle'); - // On a phone the video sits below the headline, so it starts once scrolled to. - await video.scrollIntoViewIfNeeded(); - await expect.poll(() => video.evaluate((v: HTMLVideoElement) => !v.paused), { timeout: 15000 }).toBe(true); - await expect(toggle).toContainText('Pause'); - await toggle.click(); - await expect.poll(() => video.evaluate((v: HTMLVideoElement) => v.paused)).toBe(true); - await expect(toggle).toContainText('Play'); - await expect(toggle).toHaveAttribute('aria-label', /Play the demo video/); - }); - - test('a visitor who prefers reduced motion gets the poster and no autoplay', async ({ page }) => { - await page.emulateMedia({ reducedMotion: 'reduce' }); - await page.goto('/', { waitUntil: 'load' }); - await page.waitForTimeout(1500); - const video = page.locator('#demo-video-el'); - await expect(video).toHaveJSProperty('paused', true); - expect(await video.getAttribute('src')).toBeNull(); - // They can still start it. - await page.locator('#demo-video-toggle').click(); - await expect.poll(() => video.evaluate((v: HTMLVideoElement) => !v.paused), { timeout: 15000 }).toBe(true); - }); - - test('the video files and posters the page names all exist and are small', async ({ request }) => { - const sizes: Record = { - '/assets/joltrin-barrier.mp4': 2_500_000, - '/assets/joltrin-barrier-720.mp4': 1_500_000, - '/assets/joltrin-barrier-poster-540.jpg': 80_000, - }; - for (const [url, max] of Object.entries(sizes)) { - const res = await request.get(url); - expect(res.status(), url).toBe(200); - expect((await res.body()).length, `${url} should stay under ${max} bytes`).toBeLessThan(max); - } + test('intro video sits below the hero and autoplays muted', async ({ page }) => { + await page.goto('/', { waitUntil: 'domcontentloaded' }); + const frame = page.locator('iframe[title="Joltrin intro video"]'); + await expect(frame).toHaveAttribute('src', /youtube-nocookie\.com\/embed\/F0jYkBHJluI\?.*autoplay=1.*mute=1/); + const frameY = (await frame.boundingBox())!.y; + const heroY = (await page.getByRole('heading', { level: 1 }).boundingBox())!.y; + expect(frameY).toBeGreaterThan(heroY); }); test('header has a Watch demo button that jumps to the video', async ({ page }) => { @@ -127,7 +73,7 @@ test.describe('Homepage', () => { const btn = page.locator('#watch-demo-btn'); await expect(btn).toBeVisible(); await expect(btn).toHaveAttribute('href', '#demo-video'); - await expect(page.locator('#demo-video video')).toHaveCount(1); + await expect(page.locator('#demo-video iframe')).toHaveCount(1); }); test('explains how to test the barrier with your own AI agent', async ({ page }) => {