initial commit
Some checks failed
ci / go (push) Has been cancelled
ci / admin-ui (push) Has been cancelled
ci / runtime-sdk (push) Has been cancelled
ci / helm (push) Has been cancelled
ci / openapi (push) Has been cancelled
ci / container (push) Has been cancelled
ci / release-config (push) Has been cancelled
ci / shared styling (push) Has been cancelled
ci / security (push) Has been cancelled
ci / all green (push) Has been cancelled

This commit is contained in:
Daniel Noulet 2026-10-07 15:11:35 +02:00
commit 951dd8d26b
175 changed files with 50041 additions and 0 deletions

124
hack/pilot-go-loose.js Normal file
View file

@ -0,0 +1,124 @@
/**
* The pilot check's reporter.
*
* It is injected into a *copy* of go-loose's page; go-loose's own source is untouched.
*
* The question it answers is narrow and specific: does the component shipped by
* go-bananas change the attributes that go-loose's own hand-written stylesheet already
* keys on? If it does, go-loose is themed by the shared contract without a single edit
* to its CSS, which is the entire claim of ADR 0005.
*/
import { getContractState } from '/rt/v1/components.js'
const results = []
/** @param {string} name @param {boolean} pass @param {string} [detail] */
const check = (name, pass, detail = '') => results.push({ name, pass: !!pass, detail: String(detail) })
const root = document.documentElement
const state = getContractState()
/** The computed background of go-loose's own page surface. */
function pageBackground() {
return getComputedStyle(document.body).backgroundColor
}
/**
* The value go-loose's page sees for a contract custom property.
*
* This is the claim worth testing: go-loose's stylesheet never mentions --bn-* or
* --surface being defined anywhere, yet reading the property off its own body proves
* the contract reached the page through the one stylesheet link.
*/
function contractValueOnHost(name) {
return getComputedStyle(document.body).getPropertyValue(name).trim()
}
/** The text colour go-loose's own CSS takes from --text. */
function pageText() {
return getComputedStyle(document.body).color
}
async function run() {
// The selector fetches its palette list from the service. The wait has to cover a
// real cross-origin round trip, not the instant rejection that used to happen when
// the service sent no CORS headers: that failure was fast enough to hide behind a
// short settle time, and the wait was tuned to it.
await new Promise((r) => setTimeout(r, 4000))
const selector = document.querySelector('bananas-theme-selector')
const toggle = document.querySelector('bananas-appearance-toggle')
const shadow = (el) => /** @type {ShadowRoot} */ (el.shadowRoot)
check('the selector element upgraded', !!shadow(selector), selector ? selector.tagName : 'absent')
check('the toggle element upgraded', !!shadow(toggle), toggle ? toggle.tagName : 'absent')
const buttons = [...shadow(selector).querySelectorAll('button')]
const labels = buttons.map((b) => b.textContent.trim())
check('palettes are listed from the service', buttons.length > 1, labels.join(', '))
// go-loose's four palettes must all be offered, because those are the slugs its own
// CSS has blocks for.
for (const slug of ['Tokyo Night', 'Catppuccin', 'Tomorrow', 'Kanagawa']) {
check(`go-loose's "${slug}" is offered`, labels.includes(slug))
}
// The contract stylesheet loaded and reached go-loose's page.
const bgTokyo = pageBackground()
check('go-loose\'s page is themed through the contract', bgTokyo !== 'rgba(0, 0, 0, 0)' && bgTokyo !== '', bgTokyo)
// The decisive test: change the palette with the component, and confirm go-loose's
// OWN stylesheet responded. Nothing in style.css was edited.
const startBg = bgTokyo
const startText = pageText()
const kanagawa = buttons.find((b) => b.textContent.trim() === 'Kanagawa')
if (!kanagawa) {
check('the Kanagawa button was found', false, labels.join(', '))
} else {
kanagawa.click()
await new Promise((r) => setTimeout(r, 60))
check('selecting a palette writes data-theme', root.getAttribute('data-theme') === 'kanagawa', root.getAttribute('data-theme'))
check('selecting a palette writes the legacy attribute', root.getAttribute('data-bananas-theme') === 'kanagawa', root.getAttribute('data-bananas-theme'))
check("go-loose's own CSS followed the palette", pageBackground() !== startBg, startBg + ' -> ' + pageBackground())
// The alias layer reached a page that never referenced it.
check('go-loose\'s page reads --surface from the contract', contractValueOnHost('--surface') !== '', contractValueOnHost('--surface'))
check('go-loose\'s page reads --bn-surface from the contract', contractValueOnHost('--bn-surface') !== '', contractValueOnHost('--bn-surface'))
check('the alias and the contract agree', contractValueOnHost('--surface') === contractValueOnHost('--bn-surface'),
contractValueOnHost('--surface') + ' vs ' + contractValueOnHost('--bn-surface'))
}
// And the appearance axis, which go-loose has never had.
const toggleButtons = [...shadow(toggle).querySelectorAll('button')]
check('the appearance toggle has three states', toggleButtons.length === 3, toggleButtons.map((b) => b.getAttribute('aria-label')).join(', '))
const light = toggleButtons.find((b) => b.getAttribute('aria-label') === 'Light')
if (light) {
light.click()
await new Promise((r) => setTimeout(r, 60))
check('light writes data-mode', root.getAttribute('data-mode') === 'light', root.getAttribute('data-mode'))
check("go-loose's own CSS followed the appearance", pageBackground() !== 'rgb(0, 0, 0)', pageBackground())
}
// Isolation: go-loose has a broad `.card button { all: unset }`-style surface, and a
// control that leaked would be reset by it.
const first = shadow(selector).querySelector('button')
const style = first ? getComputedStyle(first) : null
check('the control is not reset by the host page', !!style && style.padding !== '0px', style ? style.padding : 'no button')
check('the control is not inheriting the page font', !!style && !style.fontFamily.includes('DM Sans'), style ? style.fontFamily : '')
// The store is reachable, so go-loose can read or set the selection itself.
check('the contract store is reachable from the module', state && typeof state.selectTheme === 'function')
const failed = results.filter((r) => !r.pass)
const out = document.getElementById('pilot') || document.createElement('pre')
out.id = 'pilot'
out.textContent = failed.length
? 'PILOT FAIL ' + failed.length + '/' + results.length + ' :: ' + failed.map((f) => f.name + ' [' + f.detail + ']').join(' | ')
: 'PILOT PASS ' + results.length + ' :: ' + results.map((f) => f.name).join(' | ')
document.body.append(out)
}
run().catch((error) => {
const out = document.createElement('pre')
out.id = 'pilot'
out.textContent = 'PILOT FAIL the check threw: ' + (error instanceof Error ? error.message : String(error))
document.body.append(out)
})