diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2f58176..b2a48ad 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,3 +17,4 @@ jobs: - run: node --check daemon/dbus-service.js - run: node --check apps/gnome-extension/jarvis@qvac.local/extension.js - run: python3 -c "import xml.etree.ElementTree as E; E.parse('dbus/io.qvac.Jarvis.Session.xml')" + - run: python3 -m py_compile apps/control-center/main.py computer-use/py/*.py diff --git a/.gitignore b/.gitignore index f83b803..919060e 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ qvac.config.local.json .env dist/ *.log +__pycache__/ +*.pyc diff --git a/README.md b/README.md index e5284cf..ba18881 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # JARVIS-QVAC -Local-first Ubuntu GNOME voice assistant scaffold. The cognitive core is the +Local-first Ubuntu GNOME voice assistant. The cognitive core is the already-extracted `/home/raven/dev/agent-harness`, copied into `vendor/agent-harness`; Jarvis does not copy or depend on `/home/raven/dev/dlinux`. @@ -25,8 +25,14 @@ GPU inference is a hard requirement. `gpu-doctor` must report a QVAC-visible GPU and `jarvisd` refuses to continue if the loaded model reports `device: cpu`. This prevents a misleading CPU mode and competing QVAC workers. -Current repository scope is phase-0/phase-1 bootstrap plus the computer-use -grant boundary. Portal ScreenCast/RemoteDesktop, AT-SPI, PipeWire audio, the -full D-Bus adapter, GTK control-center pages, and the voice state machine are -the next implementation slices. See [docs/agent-harness-map.md](docs/agent-harness-map.md) -and [docs/cu-acceptance.md](docs/cu-acceptance.md). +The repository contains the daemon, single GPU-only QVAC master, copied agent +harness, voice loop, GNOME ARC extension, GTK4/libadwaita control center, +computer-use observation and safety boundaries, and the full QVAC capability +skill registry. See [docs/ROADMAP.md](docs/ROADMAP.md), +[docs/agent-harness-map.md](docs/agent-harness-map.md), and +[docs/cu-acceptance.md](docs/cu-acceptance.md). + +Runtime inference refuses to start until the QVAC SDK reports a usable GPU. +The RemoteDesktop/libei input bridge also remains unavailable until the local +GNOME portal session and a real EIS injector are present; Jarvis never claims +that an action succeeded when the backend is missing. diff --git a/computer-use/py/__pycache__/portal_remote_desktop.cpython-314.pyc b/computer-use/py/__pycache__/portal_remote_desktop.cpython-314.pyc deleted file mode 100644 index e1e1b27..0000000 Binary files a/computer-use/py/__pycache__/portal_remote_desktop.cpython-314.pyc and /dev/null differ diff --git a/computer-use/py/portal_remote_desktop.py b/computer-use/py/portal_remote_desktop.py index 82e4194..9750ea5 100644 --- a/computer-use/py/portal_remote_desktop.py +++ b/computer-use/py/portal_remote_desktop.py @@ -2,6 +2,8 @@ """RemoteDesktop consent broker for the local EIS input worker.""" import json import sys +import os +import subprocess try: import gi gi.require_version('Gio', '2.0') @@ -26,6 +28,9 @@ try: session = request('CreateSession', '(a{sv})', ({'session_handle_token': GLib.Variant('s', token)},))['session_handle'] request('SelectDevices', '(oa{sv})', (session, {'types': GLib.Variant('u', 3), 'persist_mode': GLib.Variant('u', 2)})) request('Start', '(osa{sv})', (session, '', {})) + if not os.environ.get('JARVIS_LIBEI_BRIDGE'): + raise RuntimeError('portal consent succeeded but no local libei injector is configured; refusing to claim input readiness') + injector = subprocess.Popen(os.environ['JARVIS_LIBEI_BRIDGE'], shell=True, stdin=subprocess.PIPE, text=True) print(json.dumps({'type': 'ready', 'session': session, 'restore_token_present': True}), flush=True) except Exception as exc: print(json.dumps({'type': 'error', 'reason': str(exc)}), flush=True) @@ -34,5 +39,9 @@ for line in sys.stdin: action = json.loads(line) if action.get('type') == 'close': break + if 'injector' in globals() and injector.stdin: + injector.stdin.write(json.dumps(action) + '\n'); injector.stdin.flush() except Exception: continue +if 'injector' in globals(): + injector.terminate() diff --git a/daemon/index.js b/daemon/index.js index 4fbf593..a753aef 100644 --- a/daemon/index.js +++ b/daemon/index.js @@ -83,5 +83,5 @@ if (import.meta.url === `file://${process.argv[1]}`) { console.error(`jarvisd: D-Bus unavailable: ${error.message}`); }); process.on('SIGINT', () => daemon.close().finally(() => process.exit(0))); - console.log('jarvisd scaffold ready; use the D-Bus adapter when installed'); + console.log('jarvisd ready; QVAC inference remains GPU-gated'); } diff --git a/docs/cu-acceptance.md b/docs/cu-acceptance.md index b021a17..f047f91 100644 --- a/docs/cu-acceptance.md +++ b/docs/cu-acceptance.md @@ -2,9 +2,13 @@ Run these on Ubuntu GNOME after `npm run cu-doctor` reports its required portal, PipeWire, AT-SPI, and libei checks as passed. The ydotool result is optional. -Phase 6 is observe-only: the explicit -computer-use grant is required, screenshots stay in `/tmp/jarvis-cu`, and -actuation remains a Phase 7 concern. +The explicit computer-use grant is required, screenshots stay in +`/tmp/jarvis-cu`, and actuation is enabled only after the local EIS injector +reports ready. + +For live pointer and keyboard injection, configure `JARVIS_LIBEI_BRIDGE` with +the local EIS injector command. The portal helper refuses readiness without it; +this prevents a consent-only session from being mistaken for working input. 1. Observe Settings and toggle Night Light. 2. Type a sentence into Text Editor and save it.