$ cat /forge/handforge.md —— SVA eyes + HandForge hands, one measured loop on a live Windows desktop

AutonomousScreenAgent: a self-hosted agent that sees, acts, and verifies, on homelab hardware.

Dragos Postelnicescu|AI Systems Engineer · 25+ years infrastructure · self-hosted on the Forge

Two subsystems close a real sensorimotor loop on a live, managed Windows desktop: SVA (the eyes) captures the screen over a live pipeline, and HandForge (the hands) actuate it over VNC-RFB. The agent perceives a frame, acts, and then verifies its own effect over a genuinely independent channel — the hand never grades its own homework. Everything below is one measured, recorded run on Miner360, with every phase timed honestly and the typed probe confirmed three independent ways. Built, run, and repaired end-to-end on my own multi-node platform, the Forge.

live screen · confirmed The typed probe line as it actually appeared on the live Miner360 VS Code editor: HANDFORGE closed-loop reproduction 20260921-001552 - SVA eyes and asyncvnc hands - safe to discard
> The hand's output as the eyes saw it — a unique-timestamp probe typed into VS Code on the live Miner360 desktop, then read back and confirmed. Cropped from the run's own after frame (full 1920×1080 frames below).
92.61 msagent's own sensorimotor work
4.53 send-to-end wall (mostly deliberate waits)
1.54 smeasured VNC observation latency
3×independent confirmations of the probe
Δ 0.02tab-bar delta — workspace left as found

Read this first. This is a self-hosted research milestone from a solo lab (NexCore AI), shown honestly. It is a free, self-hosted peer to Google Mariner, OpenAI Computer Use, and Anthropic Computer Use — the difference is the reliability and governance layer, not the demo. One clean run is shown here; the technique was exercised repeatedly this session. The actuation muscle used is VNC-RFB — a deliberately “blind” muscle: it is barred from irreversible actions, restricted to reversible changes on the normal desktop, and cannot reach the Windows secure desktop. Every number below is measured from the run's own instrumentation — no estimate is dressed as data.

A self-hosted peer to the big computer-use agents — where the differentiator is trust.

The frontier labs have shown that a model can drive a screen. The open question is not whether it can click, but whether you can trust it to act on a machine you care about. That is an engineering problem — verification, safety boundaries, and etiquette on a live system — and it is the part this project is built around.

The peersGoogle Mariner · OpenAI Computer Use · Anthropic Computer Use
Frontier, hosted, model-driven screen agents. Impressive reach — and each one runs in someone else's cloud, on someone else's terms. This system aims at the same capability class, free and self-hosted, on hardware I own and administer end to end.
The differentiatorAn independent verification channel
The channel that verifies the effect (SVA's persistent VNC capture plus its vision pipeline) is a different connection and subsystem from the channel that acted (the asyncvnc hand). The hand never confirms its own success — a separate eye does. That single discipline is what makes the loop's “it worked” believable.
The differentiatorA blind-muscle safety boundary
VNC-RFB gives no application-level acknowledgement, so the architecture treats it as a blind muscle: it is structurally forbidden from irreversible actions (submit, send, pay, delete), reversible and normal-desktop only. Dangerous capability is absent from what this muscle can do, not a rule it must remember.
The differentiatorWork-alongside etiquette
The agent shares the machine with a person. It opens a disposable scratch surface, does its work, removes it, and hands control back — leaving the workspace exactly as it found it. In this run the operator's own tabs came back byte-identical (delta 0.02). It works alongside you, not over you.

One loop, two muscles, a ratified safety spine.

The agent runs a closed sensorimotor loop — perceive → plan → act → verify → heal — over eyes and hands that are deliberately separate subsystems. The safety rules below are not aspirations; they were argued through my own multi-model Council and are recorded, with their ratification jobs, in the Forge dossier.

The eyes are SVA (Screen Vision) — a foveal screen-vision agent that captures over a warm, persistent VNC session and can read a region back with a vision-language model. The hands are HandForge — keystroke and pointer actuation issued over the VNC-RFB protocol with asyncvnc. The loop perceives a frame, plans the action, acts, then verifies the expected post-state through the eyes before it believes anything happened, and is designed to heal — retry or escalate — rather than halt in fear.

perceive · SVA eyes→ plan→ act · HandForge (VNC-RFB)→ verify · independent eye→ heal / hand back
The two muscles
01VNC-RFB — the blind muscle (live here)
Proven, low-friction keystroke/pointer injection over RFB. No application-level ack, so it is ineligible for irreversible actions and cannot reach the Windows UAC secure desktop. Reversible, normal-desktop actuation only. This is the muscle used in the run below.
02Native + secure-desktop — gated on a demo
A native / CDP / UIA actuation path with application-level acknowledgement is design-approved and would also drastically cut the observation latency — but it is deliberately gated on a real end-to-end demonstration before it is trusted. It is the next build, not a current claim.
The Council-ratified safety spine
Canonical record — Forge dossier
::HandForge_learnable_targeting · Council-ratified council_6c803b131a7a ::HandForge_vnc_input_transport · proven ::HandForge_hands_lane · Council-ratified council_c8aaec40fcf5 ::HandForge_ps_over_ssh ::work_alongside_deontology ::ScreenVision_SVA_v3

One recorded loop, timed honestly.

Run 20260921_001552, host Miner360 (192.168.5.6:5900), 1920×1080. Recorded live with script so it can be replayed at any speed. Every phase below is measured with perf_counter; nothing is rounded into a nicer story.

PhaseMeasured
perceive — SVA eyes capture a frame (PNG, lossless)45.79 ms
act — asyncvnc hand issues the keys (98-char probe)1.05 ms
verify — SVA eyes re-capture45.77 ms
agent's own sensorimotor work (perceive + act + verify)92.61 ms
deliberate UI-settle waits (Ctrl+1 0.60s · Ctrl+n 1.50s · i 0.80s — conservative, tunable)2903.18 ms
VNC observation latency (measured — poll until the probe is genuinely visible)1538.19 ms
end-to-end wall (everything, including every deliberate wait)4533.98 ms

Side measurements from the same run: hand connect 4.49 ms; independent VLM readback 1298.74 ms. On the JPEG operational path the agent's own work is roughly ~19 ms (an SVA JPEG capture measures ~8.5 ms); the 92.61 ms above is the run's own lossless-PNG path.

> The headline, stated carefully: the agent's own sensorimotor operations cost ~93 ms (~19 ms on the JPEG path). The ~4.5 s end-to-end is almost entirely deliberate waits for the UI to respond (~2.9 s) plus the VNC observation channel's propagation (~1.5 s, measured). The bottleneck is watching the screen — not the agent thinking, and not the agent acting. The hand is faster than the UI it drives, and faster than the eyes can confirm over VNC. This is not a 93 ms end-to-end loop, and is not presented as one.

Replay the recording
$ cd /mnt/t/HandForge/research/runs && scriptreplay -T 20260921_001552.timing 20260921_001552.typescript
handforge_20260921_001552.typescript — console excerpt (exit 0)
target: miner360 (192.168.5.6:5900)
probe : 'HANDFORGE closed-loop reproduction 20260921-001552 - SVA eyes and asyncvnc hands - safe to discard'  (98 chars)
[hand ] asyncvnc connected  fb=1920x1080  (4 ms)
[percv] SVA capture 45.8 ms (wall 66, frame_age 3.30s) bright=388  -> ..._1_before.png
[act  ] inject(focus+newtab+insert+type 98) = 1.05 ms  | deliberate UI-settle waits = 2903 ms
[vrfy ] probe visible after 1538 ms (5 polls)  bright 388->667 (thr 600)  confirmed=True  -> ..._2_after.png
[vlm  ] independent readback 1299 ms  token_match=True
         -> "HANDFORGE closed-loop reproduction 20260921-001552 - SVA eyes and asyncvc hands - sa"
[disc ] :q! sent  bright 667->388 (probe gone)  tab-bar Δ(before->restored)=0.020  clean_restore=True
=== MEASURED ===  machine_work_ms = 92.61   end_to_end_wall_ms = 4533.98   observe_latency_ms = 1538.19
Script done on 2026-09-21 00:16:01+03:00 [COMMAND_EXIT_CODE="0"]

Raw recording for scriptreplay: ./typescript  ·  ./timing

The loop, in three frames
Before frame: the operator's live VS Code desktop on Miner360, tabs and Vim buffer as found
1 · before — the operator's live desktop, as found.
After frame: the unique-timestamp probe typed into a new scratch tab, visible in the editor
2 · after — probe typed into a scratch tab, confirmed visible.
Restored frame: the scratch tab discarded with Vim :q!, the workspace back exactly as found
3 · restored — scratch discarded with :q!, workspace as found.

A hallucination cannot reproduce that timestamp.

The probe carries a unique run timestamp, 20260921-001552, generated at launch. Three independent readings all agree on that exact string — so the probe genuinely reached the screen; no single reader is being taken on faith.

> Three channels — a deterministic pixel measurement and two vision models on different tiers — independently produce the same unique timestamp. A model that was hallucinating could not have reproduced a string it never saw. That agreement, not any one reading, is the proof the hand's keystrokes reached the live screen.

An earlier verifier was confidently wrong — and a strong reader caught it.

This is the part I would most want a reviewer to see, because it is where the engineering actually happened. The first version of this harness verified the action with a naive pixel-delta — “did the editor region change?” It reported success before and independently of whether the probe had landed. Here is exactly why it lied, and exactly how it was fixed.

Two measured root causes
The fix — verify expected content, and measure the wait

> The lesson generalises past this harness: a verifier that checks for motion is unsafe, because a UI produces motion for reasons that have nothing to do with your action. Check the expected post-state. It is the same reason the safety spine says a verifier hit is never terminal for an irreversible action — and it is why the whole loop was built so the eye that checks is independent of the hand that acted.

Three pieces, verbatim.

Lifted unchanged from the run's harness (milestone_loop_harness.py, v3) — the hand, the eyes, and the verify. Minimal and readable on purpose.

the hand — asyncvnc actuationinjection timed separately from the deliberate UI-settle waits
# ACT (asyncvnc hand): inject cost separated from deliberate UI-settle waits
inj = 0.0
t_seq = time.perf_counter()
for keys, wait in ((("Ctrl", "1"), 0.60), (("Ctrl", "n"), 1.50), (("i",), 0.80)):
    t = time.perf_counter(); hand.keyboard.press(*keys); inj += time.perf_counter() - t
    await asyncio.sleep(wait)
t = time.perf_counter(); hand.keyboard.write(probe); inj += time.perf_counter() - t
act_seq = (time.perf_counter() - t_seq) * 1000.0
t_ms["act_inject_ms"] = inj * 1000.0
t_ms["act_ui_settle_ms"] = act_seq - inj * 1000.0
t_ms["act_sequence_ms"] = act_seq
the eyes — SVA capturereturns frame_age so staleness is observable, not silent
def sva_capture(host):
    """SVA EYES: grab a frame from the warm persistent VNC session.
    -> (png_bytes, capture_ms, wall_ms, fb, frame_age_s)."""
    t0 = time.perf_counter()
    d = _post("/api/vnc/capture", {"host": host, "image_format": "png", "return_b64": True}, 20)
    wall = (time.perf_counter() - t0) * 1000.0
    png = base64.b64decode(d["jpeg_b64"])
    age = float((d.get("meta") or {}).get("session_last_frame_age_s") or 0.0)
    return png, float(d.get("capture_ms") or 0.0), wall, tuple(d.get("framebuffer_size") or []), age
the verify — poll until genuinely visiblecalibrated content check, not a bare pixel-delta
def bright_count(png, box):                      # BRIGHT=190, PROBE_VISIBLE=600
    g = np.asarray(Image.open(io.BytesIO(png)).convert("L"))
    x1, y1, x2, y2 = box                          # ROI = (358, 88, 1260, 112)
    return int((g[y1:y2, x1:x2] > BRIGHT).sum())

# VERIFY: poll until the probe is genuinely visible (and MEASURE observe latency)
t0 = time.perf_counter(); after_png = before_png; bright_after = 0; polls = 0
while (time.perf_counter() - t0) < OBSERVE_TIMEOUT:
    after_png, cap_after, _, _, age_after = sva_capture(HOST); polls += 1
    bright_after = bright_count(after_png, ROI)
    if bright_after > PROBE_VISIBLE:
        break
    await asyncio.sleep(0.30)
t_ms["observe_latency_ms"] = (time.perf_counter() - t0) * 1000.0
confirmed = bright_after > PROBE_VISIBLE

It works alongside a person, and leaves no trace.

The operating mentality is to learn the environment and work alongside it non-destructively — never halt in fear, never trample the operator's state. In this run the agent opened a scratch Untitled tab, typed the probe, and discarded it with Vim :q!. The operator's Welcome / VS Code release-notes tabs, live PowerShell, and Vim buffer were untouched.

Editor tab bar before the run
tab bar · before — the operator's tabs at the start of the run.
Editor tab bar after the run, byte-identical to before
tab bar · restored — after the run. Mean absolute delta against the before tab bar: 0.02 — byte-identical for practical purposes.

> The agent adds a disposable surface, does its work, removes it, and hands control back — leaving the workspace exactly as found (clean_restore = true). That courtesy is not decoration: it is the precondition for an agent that shares a live machine with a human instead of taking it over.

What this is not — stated plainly.

The strongest version of this work is the one that is honest about its edges. None of the following is hidden.

How this was engineered.

AutonomousScreenAgent did not appear from nowhere. It is the actuation stage of a vision line that has been building for over a year, and it was engineered through the same dossier-and-Council process as the rest of the Forge.

2025
RrrBot
The first screen-watching experiments — the eyes before they were a system.
2025–26
ScreenVision v1 / v2
Capture pipelines and change detection maturing into a real vision lane.
2026
SVA v3 · EyeForge
Foveal screen vision: cheap peripheral glances, expensive reads only where something moved. Exposed fleet-wide as first-class vision tools.
2026 · now
HandForge
The hands: actuation over VNC-RFB, closing the loop with the eyes — the run on this page.

The rigour is the point. Each deliverable — targeting/verification, the input transport, the PowerShell-over-SSH admin boundary, and the hands command/feedback lane — landed as a canonical dossier entry, and the load-bearing safety decisions were ratified by my multi-model Council before they were built on. This page documents a measured run; the dossier and the Council jobs behind it are how it was engineered honestly, the same way every system in the portfolio is.

Who built this.

AI Systems Engineer — 25+ years across enterprise infrastructure and telecom, most recently as a Principal Technical Support Engineer. This is real software I designed, built, and operate solo, self-hosted end to end on my own multi-node GPU platform. MSc Open Systems Architecture and BSc Electronics & Computer Science, Politehnica University of Bucharest. Oracle Cloud Infrastructure 2025 Generative AI Professional and AI Foundations Associate.

Open to senior AI / infrastructure engineering and forward-deployed roles — full-time or B2B contract.

>Bucharest, EU · remote-ready >self-hosted agentic systems >verification & governance by design >25+ yrs infrastructure

Talk to me.

Email is the front door — or use the form on the main site. Prefer voice? Request a call by email and I'll confirm a slot.

./email me ./contact form ./linkedin ./full portfolio
Calls
By appointment — request via email
Base
Bucharest, EU · remote-ready