The Course pane lists the 21 lessons, shows a lesson's text and exercise, loads its starter, and checks the program in the editor with the engine (engine_course_check in the page, the same commands in the desktop app): each case's verdict, each rule, What went wrong? from the diagnostics, the verdict and the critique, the hints one at a time with the engine's pointer, and a hint from the assistant when a model is connected, any program in its answer held back. Progress is kept only in this browser and says so. The interface's words are data, locales/<locale>/<area>.json for every part, English the source and Simplified Chinese marked machine-assisted; the Studio follows the browser's language until the reader picks one with the switch. test/locales.test.mjs holds every locale to every key and placeholder. The e2e checks the course in English and in Chinese. wai-web's engine tests pin 23 native and 16 wasm32, a course check the same bytes in both. Co-Authored-By: Claude Opus 5.5 <[email protected]>
38 lines
1.9 KiB
JavaScript
38 lines
1.9 KiB
JavaScript
// A verdict as the Studio shows it: one badge for the level the engine
|
|
// checked to, never "valid", and the engine's own statement beside it.
|
|
//
|
|
// refused the engine did not read the program, or refused the job
|
|
// parsed it read the program and ran nothing
|
|
// executed it ran the program, and checked no intent
|
|
// evidence it checked every intent, one by random inputs (not a proof)
|
|
// proof it checked every intent by proof
|
|
//
|
|
// A verdict the job's receipt seals says so; one the Studio worked out here
|
|
// (for a result that carries none, or a refusal) says that instead.
|
|
import { el } from './dom.js';
|
|
import { t } from './i18n.js';
|
|
|
|
const WORDS = {
|
|
refused: t('verdict_view.refused'),
|
|
parsed: t('verdict_view.parsed'),
|
|
executed: t('verdict_view.executed'),
|
|
evidence: t('verdict_view.evidence'),
|
|
proof: t('verdict_view.proof'),
|
|
};
|
|
const CLASS = { refused: 'bad', parsed: '', executed: '', evidence: 'run', proof: 'ok' };
|
|
|
|
// The badge: its level as a word, the statement as its title.
|
|
export function levelBadge(v, id) {
|
|
const level = v?.level ?? 'parsed';
|
|
const holds = v?.holds === false && (level === 'proof' || level === 'evidence') ? t('verdict_view.fails') : '';
|
|
const attrs = { class: `qs-badge qs-level ${CLASS[level] ?? ''}${holds ? ' bad' : ''}`.trim(), 'data-level': level, title: v?.statement ?? '', text: `${WORDS[level] ?? level}${holds}` };
|
|
if (id) attrs.id = id;
|
|
return el('span', attrs);
|
|
}
|
|
|
|
// The badge with the statement, and whether the receipt seals it.
|
|
export function verdictLine(v, { sealed, id } = {}) {
|
|
if (!v) return el('span', { class: 'qs-note', text: t('verdict_view.no_verdict') });
|
|
const where = sealed ? t('verdict_view.sealed') : t('verdict_view.not_sealed');
|
|
return el('span', { class: 'qs-verdict' }, levelBadge(v, id), el('span', { class: 'qs-why', text: t('verdict_view.why', { statement: v.statement ?? '', where }) }));
|
|
}
|