Merge current main into S2 GhostMaps and preserve updated import and voice behavior

This commit is contained in:
Mazeyar Moeini Feizabadi committed 2026-10-26 16:25:49 +01:00
commit 4da002bd42
515 files changed
+17681 -2202

No files matched your search

+65 -7
View File
@@ -247,6 +247,10 @@ test('no storage is touched from a default parameter position', () => {
test('the JS and CSS lists of screen-claiming surfaces stay in step', () => {
const module = fs.readFileSync(
new URL('./exclusiveSurfaces.js', import.meta.url),
'utf8',
);
const firstRun = fs.readFileSync(
new URL('./firstRunExperience.js', import.meta.url),
'utf8',
);
@@ -279,6 +283,8 @@ test('the JS and CSS lists of screen-claiming surfaces stay in step', () => {
module,
/export const EXCLUSIVE_SURFACE_CLASSES = Object\.freeze\(\[/,
);
// First run keeps exporting the one shared list (the phone shell reads it too).
assert.match(firstRun, /export \{ EXCLUSIVE_SURFACE_CLASSES \};/);
});
test('exclusiveSurfaceActive reads the live body classes', () => {
@@ -373,10 +379,6 @@ test('one ESC does one thing — the radio disclosure stops the launcher outrigh
new URL('./ui/radioBindings.js', import.meta.url),
'utf8',
);
const module = fs.readFileSync(
new URL('./firstRunExperience.js', import.meta.url),
'utf8',
);
// stopPropagation() does NOT stop later listeners on the SAME document, so the
// disclosure's earlier capture handler closed the disclosure and the launcher
@@ -911,6 +913,48 @@ test('markup, startup ordering and accessibility remain pinned', () => {
assert.match(choicesBlock, /overflow-y: auto;/);
});
test('the card closes without a keyboard: the ESC hint is a button, kept on phones', () => {
const html = expandApplicationHtml(
fs.readFileSync(new URL('../index.html', import.meta.url), 'utf8'),
);
const module = fs.readFileSync(
new URL('./firstRunExperience.js', import.meta.url),
'utf8',
);
// The whole stylesheet, so a hide rule added in any other file is caught too.
const css = readStylesheet(new URL('../style.css', import.meta.url));
const footer = html.slice(
html.indexOf('class="first-run-footer"'),
html.indexOf('data-first-run-status'),
);
assert.match(
footer,
/<button type="button" class="first-run-dismiss" data-first-run-dismiss>/,
);
assert.match(footer, /data-i18n>ESC to dismiss</);
assert.match(footer, /data-i18n>DISMISS</);
// It closes the way ESC does, through the one dismiss path, so the session
// flag and focus handling are the same.
assert.match(
module,
/querySelector\('\[data-first-run-dismiss\]'\)\s*\?\.addEventListener\('click', \(\) => dismiss\(\)\)/,
);
// Phones used to hide the hint, leaving no way out but picking a mission.
assert.doesNotMatch(css, /first-run-footer > span:last-child/);
assert.doesNotMatch(css, /\.first-run-dismiss\s*\{[^}]*display:\s*none/);
// A 44px touch target that does not add to the footer row's height.
assert.match(
css,
/\.first-run-dismiss::before \{[^}]*position: absolute;[^}]*height: 44px;/,
);
assert.doesNotMatch(css, /\.first-run-dismiss \{[^}]*min-height/);
// Touch screens read DISMISS rather than a key they do not have.
assert.match(
css,
/@media \(hover: none\) and \(pointer: coarse\) \{\s*\.first-run-dismiss-key \{\s*display: none;/,
);
});
test('the launcher keeps focus, restores it, and never disables the focused button', () => {
const module = fs.readFileSync(
new URL('./firstRunExperience.js', import.meta.url),
@@ -986,6 +1030,16 @@ test('the voice TOOL SCHEMA matches the pinned contract — the mission mapping
]);
// Cyber deliberately adds one layout; first-run missions still change no tools.
hudLayout.enum = hudLayout.enum.filter((layout) => layout !== 'cyber');
const cameraMotion = legacyTools.find((tool) => tool.name === 'move_camera')
.parameters.properties.motion;
assert.deepEqual(cameraMotion.enum, [
'orbit',
'pan',
'tilt',
'rotate',
'rotate_globe',
'stop',
]);
const block = JSON.stringify(legacyTools);
// Re-derived for the voice layer manifest (generated layer enums, alias and
// field hints), point-and-ask's pointer/referent arguments and the prompt
@@ -995,11 +1049,15 @@ test('the voice TOOL SCHEMA matches the pinned contract — the mission mapping
// list descriptions; the missions still ride existing tools.
// Street Level and GNSS extend the manifest; broadcast caveats describe tracked and analyst aircraft.
// Air quality (ECCC AQHI) extends the manifest.
// S2 GhostMaps extends the manifest.
assert.equal(block.length, 30723, 'serialized tool schema length drifted');
// Globe rotation adds one camera motion and its descriptions; Globe View
// framing/default guidance updates only move_camera and mode descriptions.
// Radio markup and the complete production-request comparison pin locality.
// Restore the base camera/Globe View wording with the globe-rotation append.
// S2 GhostMaps adds its layer id to the generated layer enums.
assert.equal(block.length, 30946, 'serialized tool schema length drifted');
assert.equal(
crypto.createHash('sha256').update(block).digest('hex'),
'5937f0e90d38bf4109136c71bb9561298dd3fca11464ff980a1f982b6c154e5b',
'be53b22c55e620fb36c6ea0f276bfe5a59de47fa02ead99188ada40c0bf48cc0',
'the first-run missions must ride EXISTING tools: no schema edit, no cache bust',
);
const instructions = fs.readFileSync(