The page shows each of the 128 cases in 16 suites as it is run, in the standard's words (NOT RUN, RUNNING, PASS, FAIL, BLOCKED, DEFERRED): a header with the approval line and a thin segmented count bar (never a percentage), G0 and the five gates G1 to G5 plus the three named gates as cards whose state follows the standard's rule, one section per suite with an expandable row per case (setup, steps, accept, required evidence, the run's evidence record when present), the profiles (approved as proposed, P13 deferred, the P04 line read as a FAIL to work against), the fixtures, and the closing notes. site/lib/acceptance-render.mjs is the one renderer: build.mjs imports it for the build-time page and prints the same functions into the page's inline script, which polls /api/acceptance (site/api/acceptance.mjs: the registry from git.igneum.network master, cached 60 s, ok:false with status 200 on failure) and re-renders in place when a case state or source_sha256 moves. Hooks: the Learn panel, the nav check, the sitemap, capture.sh, the og card row, a lead link on /scorecard, the facts rows 1 to 7 name the case that will prove each. The never-served check strips the plan's own marked never-served list. Node tests (known-failed first) run in the gate; the registry and the standard text land with the page. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
45 lines
2.7 KiB
JavaScript
45 lines
2.7 KiB
JavaScript
// The acceptance registry, live. GET /api/acceptance: docs/plans/igneum-2.0-test-registry.json as it stands on master on the
|
|
// public git host (git.igneum.network), so /acceptance shows each case as it passes without a redeploy. The page renders its
|
|
// build-time copy first and polls this every 60 seconds; it re-renders only when a case state or the registry's source_sha256
|
|
// moves. Cached 60 s in this function instance and at the edge. On any failure the reply is { ok: false, reason } with
|
|
// status 200, and the page keeps the copy it has.
|
|
export const SOURCE_URL = 'https://git.igneum.network/api/v1/repos/igneum-network/igneum/contents/docs/plans/igneum-2.0-test-registry.json?ref=master';
|
|
export const SOURCE = 'git.igneum.network master';
|
|
export const TTL_MS = 60_000;
|
|
|
|
// the git host's contents reply: JSON with a base64 `content` field; the registry must carry its suites
|
|
export function decode(reply) {
|
|
if (!reply || typeof reply.content !== 'string') throw new Error('the git host reply has no content field');
|
|
const b64 = reply.encoding === 'base64' || !reply.encoding;
|
|
const text = b64 ? Buffer.from(reply.content.replace(/\s+/g, ''), 'base64').toString('utf8') : reply.content;
|
|
const registry = JSON.parse(text);
|
|
if (!registry || !Array.isArray(registry.suites)) throw new Error('the registry has no suites');
|
|
return registry;
|
|
}
|
|
|
|
export function createHandler({ fetchImpl = globalThis.fetch, now = () => Date.now() } = {}) {
|
|
let cache = null; // { at, body }: one per function instance
|
|
return async function handler(req, res) {
|
|
res.setHeader('Cache-Control', 'public, max-age=30, s-maxage=60, stale-while-revalidate=60');
|
|
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
if (req.method !== 'GET') { res.setHeader('Allow', 'GET'); return res.status(405).json({ ok: false, reason: 'method not allowed' }); }
|
|
const t = now();
|
|
if (cache && t - cache.at < TTL_MS) return res.status(200).json(cache.body);
|
|
try {
|
|
const ctl = typeof AbortController !== 'undefined' ? new AbortController() : null;
|
|
const timer = ctl ? setTimeout(() => ctl.abort(), 8000) : null;
|
|
let r;
|
|
try { r = await fetchImpl(SOURCE_URL, { headers: { accept: 'application/json' }, signal: ctl ? ctl.signal : undefined }); }
|
|
finally { if (timer) clearTimeout(timer); }
|
|
if (!r.ok) throw new Error(`the git host answered ${r.status}`);
|
|
const registry = decode(await r.json());
|
|
const body = { ok: true, fetched_at: new Date(t).toISOString(), source: SOURCE, registry };
|
|
cache = { at: t, body };
|
|
return res.status(200).json(body);
|
|
} catch (e) {
|
|
res.setHeader('Cache-Control', 'no-store');
|
|
return res.status(200).json({ ok: false, reason: String(e && e.message || e) });
|
|
}
|
|
};
|
|
}
|
|
export default createHandler();
|