mirror of
https://github.com/zoo-apps/zoolabs.io.git
synced 2026-10-30 14:56:27 +00:00
The chat had a function named generateIntelligentResponse: a keyword table that wrote replies in Blue's voice and streamed them a word at a time so they read as inference. Every path reached it — a failed fetch, a bad status, an empty stream — so the site always produced an answer and never had a way to say it could not. Around it a second table fabricated the evidence: hydrophone telemetry at "18.4 kHz - 120 kHz" from the "Cook Inlet Acoustic Array", a quiz with its own answer key, a field notebook, a code sample. None of it came from anywhere. The same shape ran through the rest of the app. login discarded the fetch result and wrote a session on a timer, so any password signed anyone in; signup and the social and wallet buttons invented identities outright. pricing collected a card number and CVC, discarded that fetch too, and showed a receipt for a person who does not exist. 3d, music, video and design posted to models that answer nothing and dressed the silence as generation. All of it is gone, with the auth pages: IAM issues tokens, and until zoolabs.io is registered with it there is nothing here to sign in to. What is left is what can be shown to be true. Blue talks to the model and reports, verbatim, whatever the endpoint says when it will not — today that is a browser CORS refusal, and behind it a 402 for anonymous use. The feeling Blue shows is the model's own choice, named in the reply and checked against the 24 clips that exist; a test asserts the vocabulary and the folder are the same list, which is the check the old code wanted, as it pointed Focused at a file that was never there. Research is the real corpus — 86 papers and 149 proposals, titles and abstracts read out of the sources by scripts/research.mjs, not the "130+" nobody counted. The look is zoo.industries: light, the mark's own five hues, hard black edges. It is built on @hanzo/gui and @hanzo/design, so the tokens come from the fleet. Tailwind is gone, and with it a styles/globals.css that had hand-written its own copy of Tailwind's utilities while importing Tailwind — two systems, one of them silently losing. Verified with Playwright at 390, 834, 1440 and 1920: no console errors, no sideways scroll, search narrowing 86 papers to 2 on "beluga", and the refusal notice appearing in place of an answer. Co-authored-by: Hanzo Dev <[email protected]>
74 lines
2.8 KiB
JavaScript
74 lines
2.8 KiB
JavaScript
// Drives the running dev server: every page at every breakpoint, plus the one
|
|
// behaviour that matters — an unreachable model must surface, never be answered
|
|
// around.
|
|
import { chromium } from 'playwright-core'
|
|
|
|
const [out, base] = process.argv.slice(2)
|
|
const SIZES = [
|
|
['mobile', 390, 844],
|
|
['tablet', 834, 1112],
|
|
['laptop', 1440, 900],
|
|
['desktop', 1920, 1080],
|
|
]
|
|
const PAGES = [['/', 'ask'], ['/research', 'research']]
|
|
|
|
const browser = await chromium.launch({ channel: 'chrome' })
|
|
const problems = []
|
|
|
|
async function open(path, name, width, height) {
|
|
const page = await browser.newPage({ viewport: { width, height } })
|
|
page.on('pageerror', (e) => problems.push(`${name}: ${e.message}`))
|
|
page.on('console', (m) => {
|
|
const t = m.text()
|
|
if (m.type() === 'error' && !t.includes('api.hanzo.ai') && !t.includes('ERR_FAILED')) {
|
|
problems.push(`${name}: ${t}`)
|
|
}
|
|
})
|
|
await page.goto(base + path, { waitUntil: 'networkidle' })
|
|
// The dev overlay is a fixed portal; it sits over the page and eats clicks.
|
|
await page.addStyleTag({ content: 'nextjs-portal{display:none!important}' })
|
|
await page.waitForTimeout(900)
|
|
return page
|
|
}
|
|
|
|
for (const [path, label] of PAGES) {
|
|
for (const [size, w, h] of SIZES) {
|
|
const page = await open(path, `${label}-${size}`, w, h)
|
|
await page.screenshot({ path: `${out}/${label}-${size}.png`, fullPage: true })
|
|
// Nothing may scroll the page sideways.
|
|
const overflow = await page.evaluate(
|
|
() => document.documentElement.scrollWidth - document.documentElement.clientWidth
|
|
)
|
|
if (overflow > 0) problems.push(`${label}-${size}: page scrolls ${overflow}px sideways`)
|
|
await page.close()
|
|
}
|
|
}
|
|
|
|
// Ask a question and watch what comes back.
|
|
const page = await open('/', 'ask-flow', 1280, 900)
|
|
await page.fill('#question', 'Why are beluga calves born grey?')
|
|
await page.click('form button')
|
|
await page.waitForSelector('div[role=alert], article', { timeout: 45000 })
|
|
await page.waitForTimeout(1200)
|
|
await page.screenshot({ path: `${out}/ask-answered.png`, fullPage: true })
|
|
|
|
const alert = page.locator('div[role=alert]')
|
|
if (await alert.count()) {
|
|
console.log('model refused →', (await alert.innerText()).replace(/\s+/g, ' ').slice(0, 140))
|
|
} else {
|
|
console.log('model answered →', (await page.locator('article').last().innerText()).replace(/\s+/g, ' ').slice(0, 140))
|
|
console.log('feeling shown →', await page.locator('figcaption').innerText())
|
|
}
|
|
await page.close()
|
|
|
|
// Research search actually narrows.
|
|
const r = await open('/research', 'research-flow', 1280, 900)
|
|
const all = await r.locator('h2').count()
|
|
await r.fill('#find', 'beluga')
|
|
await r.waitForTimeout(400)
|
|
console.log(`research: ${all} papers → "beluga" narrows to ${await r.locator('h2').count()}`)
|
|
await r.close()
|
|
|
|
await browser.close()
|
|
console.log(problems.length ? 'PROBLEMS:\n' + problems.join('\n') : 'no console errors, no sideways scroll')
|