Skip to content

feat(lbm-agent): the reconciler — display changes and engine hooking as one state machine - #623

Merged
mgth merged 1 commit into
masterfrom
feat/lbm-agent-reconciler
Sep 11, 2026
Merged

mgth merged 1 commit into
masterfrom
feat/lbm-agent-reconciler

Conversation

@mgth

@mgth mgth commented Sep 11, 2026

Copy link
Copy Markdown
Owner

Phase 3 of the v6 plan (docs/v6-architecture-plan.md on v6): the heart of lbm-agent, the reconciler — what the C# UI decided in DisplayChangeCoordinator, EngineController and MainService's daemon-event routing, as one state machine without I/O. The design and its deviations are written down in docs/v6-agent.md (French, like the plan).

Shape

  • Input in (a display change, a hook event, the user's Start/Stop/Refresh, a timer coming back), Effects out in order (Start, Stop, SaveEnabled, SaveLayout, a timer, a process seen). The layout is read and rebuilt through a World trait.
  • The runtime owns the clock and the I/O; the reconciler owns the decisions. Timers are effects, so tests run on a virtual clock, not on shrunk real delays.
  • One input is handled to completion before the next, and Effect::Start carries no zones: the runtime computes them from the current layout when it sends. The stale Start of Cursor gets trapped at screen edges after disconnecting and waking from sleep #607 cannot exist, and fix: never hook a layout the desktop no longer matches (#607) #609's LatestRequestGate is not needed here.

Rules (from C#), and the deviations

The C# rules are kept: 300 ms debounce with generations, settle loop (100 ms, 8 steps), idempotence guard that re-hooks instead of rebuilding (#412), Refresh past the guard (#443), user Start/Stop recorded before (un)hooking, foreign layouts simulated never adopted, no re-hook while asleep / against the user / over a running engine / while the watchdog drives, the post-resume watchdog (500 ms steps, 3 stable, 6 restarts, 60 steps), and the "Stopped right after Connected" hand-over.

Deliberate deviations, documented:

Tests

lbm-agent/tests/reconcile.rs: the 10 DisplayChangeCoordinatorTests and 19 EngineControllerTests, one Rust test per C# test, plus the hook routing. Where the C# test counted calls into its neighbour in isolation, the integrated Rust test checks what the call does, and says so.

Not wired to anything yet: the runtime (hook connection with --fake-hook, supervision per D5, Linux sources, persistence) comes next.

🤖 Generated with Claude Code

…hine

What the C# UI decided in DisplayChangeCoordinator, EngineController and
MainService's daemon-event routing — when a display change rebuilds the
layout, when the engine is hooked, how a wake is re-hooked — as one state
machine without I/O: inputs in, effects out, timers as effects that come
back as inputs, the layout read and rebuilt through a trait.

One input is handled at a time and a Start carries no zones (the runtime
computes them when it sends), so the stale Start of #607 cannot exist, and
#609's request gate is not needed. #609's other half is kept: a fresh layout
the user turned off sends Stop. One Start per event: a Start just sent is
given one step before the resume watchdog re-asserts it (C# sends it twice).

The C# tests of both classes are the specification: 29 ported one to one on
a virtual clock, plus the hook routing and focus reports. docs/v6-agent.md
records the design and the deviations.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@mgth
mgth merged commit a0665e2 into master Sep 11, 2026
3 checks passed
@mgth
mgth deleted the feat/lbm-agent-reconciler branch September 11, 2026 19:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant