mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-09-28 04:24:51 +02:00
93 lines
4.8 KiB
JavaScript
93 lines
4.8 KiB
JavaScript
// The fn dead-key deadlock (Haik, exp.16, ~99% of devices): the dictation-used marker was only
|
|
// written by a successful transcription, the fn watcher only started once the marker existed, and
|
|
// fn was the default hotkey, so a never-dictated install could never dictate. The fix is a boot
|
|
// probe that arms fn WITHOUT ever prompting (IOHIDCheckAccess preflight) plus intent arming.
|
|
const test = require('node:test');
|
|
const assert = require('node:assert');
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
|
|
const swiftSrc = fs.readFileSync(path.join(__dirname, 'native', 'fn-watcher.swift'), 'utf8');
|
|
const hotkeySrc = fs.readFileSync(path.join(__dirname, 'voiceHotkey.js'), 'utf8');
|
|
|
|
test('the swift preflight refuses to prompt in --no-prompt mode', () => {
|
|
const preflight = swiftSrc.indexOf('--no-prompt');
|
|
const firstTap = swiftSrc.indexOf('func armTap');
|
|
assert.ok(preflight > -1, 'preflight missing');
|
|
assert.ok(preflight < firstTap, 'preflight must run before any tap can raise the TCC prompt');
|
|
assert.match(swiftSrc, /IOHIDCheckAccess\(kIOHIDRequestTypeListenEvent\)/);
|
|
});
|
|
|
|
test('boot probes fn silently when the marker is absent', () => {
|
|
const bootBlock = hotkeySrc.split("fs.existsSync(path.join(app.getPath('userData'), 'dictation-used'))")[1].slice(0, 400);
|
|
assert.match(bootBlock, /combo\.special === 'fn'.*startFnWatcher\(true\)/s,
|
|
'a fresh install with the default fn hotkey must get the no-prompt probe at boot');
|
|
});
|
|
|
|
test('rebinding to fn before tiers are armed also probes', () => {
|
|
assert.match(hotkeySrc, /else if \(combo\.special === 'fn'\) startFnWatcher\(true\);\n unregisterFallbackShortcut/);
|
|
});
|
|
|
|
test('a focused bare Fn keydown arms the tiers and toggles', () => {
|
|
const relay = hotkeySrc.split('installVoiceHoldRelay')[1].slice(0, 900);
|
|
assert.match(relay, /input\.key === 'Fn'/);
|
|
assert.match(relay, /armNativeTiers\(\)/);
|
|
assert.match(relay, /sendFallbackToggle\(\)/);
|
|
});
|
|
|
|
test('the probe flag reaches the spawn argv', () => {
|
|
assert.match(hotkeySrc, /spawn\(bin, noPrompt \? \['--no-prompt'\] : \[\]/);
|
|
});
|
|
|
|
// ---- The deaf-tap class (Eric, exp.20, and the same "99% of devices" report) ----
|
|
// tapCreate hands back a valid port even with Input Monitoring DENIED, and that tap then never
|
|
// delivers an event. So "the watcher process is alive" was read as "fn works" by every layer above
|
|
// it, and a permanently dead key looked identical to a key nobody had pressed yet. Measured live on
|
|
// a dev machine: `p denied` followed by a successful `t ok`.
|
|
|
|
test('the watcher reports its permission instead of leaving it to be inferred', () => {
|
|
assert.match(swiftSrc, /print\(hidGranted \? "p granted" : "p denied"\)/,
|
|
'permission must be stated on stdout, not guessed from the process still being alive');
|
|
});
|
|
|
|
test('a watcher without the grant refuses to run, so alive means working', () => {
|
|
const guard = swiftSrc.split('if !hidGranted {')[1] || '';
|
|
assert.match(guard, /e no-permission/);
|
|
assert.match(guard, /exit\(0\)/);
|
|
const guardAt = swiftSrc.indexOf('if !hidGranted {');
|
|
assert.ok(guardAt > -1 && guardAt < swiftSrc.indexOf('guard armTap()'),
|
|
'the refusal must come before the tap, or a deaf tap still gets created');
|
|
});
|
|
|
|
test('the grant is REQUESTED on the intent path and never on the boot probe', () => {
|
|
assert.match(swiftSrc, /if !hidGranted && !isProbe \{\s*\n\s*hidGranted = IOHIDRequestAccess\(kIOHIDRequestTypeListenEvent\)/,
|
|
'a denied machine can only be fixed by asking; the probe must still stay silent (ENG-341)');
|
|
});
|
|
|
|
test('the tap proves it is on the wire, separately from any fn press', () => {
|
|
assert.match(swiftSrc, /if !wireAlive \{/);
|
|
assert.match(swiftSrc, /print\("w"\)/);
|
|
});
|
|
|
|
test('every way fn can fail tells the user which chord still works', () => {
|
|
for (const reason of ['input-monitoring-denied', 'no-watcher-binary', 'tap-deaf']) {
|
|
assert.ok(hotkeySrc.includes(reason), `unhandled fn failure mode: ${reason}`);
|
|
}
|
|
assert.match(hotkeySrc, /notifyPrimaryUnusable\(`watcher-exit-\$\{code\}`\)/,
|
|
'a watcher that exits leaves no primary, so it must notify too');
|
|
assert.match(hotkeySrc, /fallback: fallbackCombo\.accel/,
|
|
'the notice is only useful if it names the chord that works');
|
|
});
|
|
|
|
test('the notice is remembered, not just fired', () => {
|
|
// Arming happens at boot and the renderer subscribes later, so a pure event reaches nobody.
|
|
assert.match(hotkeySrc, /lastHotkeyIssue = \{ ok: false, reason, fallback: fallbackCombo\.accel \}/);
|
|
assert.match(hotkeySrc, /ipcMain\.handle\('voice:hotkey-issue', \(\) => lastHotkeyIssue\)/);
|
|
});
|
|
|
|
test('a key that starts working retracts its own warning', () => {
|
|
const provenBlock = hotkeySrc.split("fn watcher PROVEN")[1].slice(0, 400);
|
|
assert.match(provenBlock, /lastHotkeyIssue = null/);
|
|
assert.match(provenBlock, /voice:primary-usable/);
|
|
});
|