Extract the connect/reconnect decision into a Qt-free module #192

Merged
mysticalsoap merged 2 commits from 123-decision-module into trunk 2026-08-28 15:18:15 -04:00
Owner

Problem

The connect/reconnect decision lived inline in the gui (#123): connect_last_server parsed last_server.json into a mode, connection_established/connection_established_bypass/kill_bypass wrote it back, and none of it was reachable from the cli — which also meant a cli connect never recorded itself, so autoconnect ignored it. #191 needs the same decision reachable from the service.

Fix

  • aqomui/decision.py (Qt-free, #83): reconnect_plan() parses the stored state into {main, hop, bypass} where main is replay / random-re-roll / profile-re-resolve; record_main / record_bypass / clear_bypass own the writes; random_server and profile_by_name cover the selection modes the catalog doesn't already.
  • Gui is the first consumer, behaviour-preserving: connect_last_server maps the plan onto its existing actions (choose_random_server, connect_profile, establish_connection); progress bars, favourite button and hop widget stay put. The three recording sites become one-liners.
  • Cli gains selection modes on connect: --random, --random-favourite, --profile NAME, composing with --via. Tags match the gui's, so reconnect semantics carry: a favourite pick re-rolls, a profile re-resolves, a plain --random pick deliberately replays as the concrete server. The cli now records established connections, so autoconnect no longer forgets cli connects.

Two deliberate edge changes: a failed random re-roll no longer leaves ovpn_dict pointing at the stale stored dict, and a stored "bypass": null is skipped instead of crashing establish_connection.

Verification

  • 17 new tests in tests/test_decision.py (plan parsing incl. the present-but-off random marker, record/clear round-trips, selection helpers); full suite 481 passed.
  • Live: gui autoconnect replay/re-roll and the new cli flags still need a check on a real connection.
## Problem The connect/reconnect decision lived inline in the gui (#123): `connect_last_server` parsed `last_server.json` into a mode, `connection_established`/`connection_established_bypass`/`kill_bypass` wrote it back, and none of it was reachable from the cli — which also meant a cli connect never recorded itself, so autoconnect ignored it. #191 needs the same decision reachable from the service. ## Fix - **`aqomui/decision.py`** (Qt-free, #83): `reconnect_plan()` parses the stored state into `{main, hop, bypass}` where main is replay / random-re-roll / profile-re-resolve; `record_main` / `record_bypass` / `clear_bypass` own the writes; `random_server` and `profile_by_name` cover the selection modes the catalog doesn't already. - **Gui is the first consumer, behaviour-preserving**: `connect_last_server` maps the plan onto its existing actions (`choose_random_server`, `connect_profile`, `establish_connection`); progress bars, favourite button and hop widget stay put. The three recording sites become one-liners. - **Cli gains selection modes on connect**: `--random`, `--random-favourite`, `--profile NAME`, composing with `--via`. Tags match the gui's, so reconnect semantics carry: a favourite pick re-rolls, a profile re-resolves, a plain `--random` pick deliberately replays as the concrete server. The cli now records established connections, so autoconnect no longer forgets cli connects. Two deliberate edge changes: a failed random re-roll no longer leaves `ovpn_dict` pointing at the stale stored dict, and a stored `"bypass": null` is skipped instead of crashing `establish_connection`. ## Verification - 17 new tests in `tests/test_decision.py` (plan parsing incl. the present-but-off random marker, record/clear round-trips, selection helpers); full suite 481 passed. - Live: gui autoconnect replay/re-roll and the new cli flags still need a check on a real connection.
connect_last_server owned three things at once: parsing
last_server.json into a mode (replay / random re-roll / profile
re-resolve), recording established connections back into it, and the
gui actions that carry the result out. The first two are policy any
client needs -- the cli today, the service with #191 -- so they move
to aqomui/decision.py; the gui keeps only the mapping onto its own
connect actions, per the #83 rule that cli-imported modules stay
Qt-free.

Two edge behaviours change deliberately:

- a failed random re-roll (no favourites) no longer leaves ovpn_dict
  pointing at the stale stored dict as if it were current
- a stored "bypass": null entry is skipped instead of being handed to
  establish_connection

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
change: cli gains selection modes on connect (#123)
Some checks failed
ci / test (pull_request) Successful in 29s
ci / test (push) Has been cancelled
e861c18b59
--random, --random-favourite and --profile NAME resolve through the
same decision/catalog code the gui uses, compose with --via, and tag
the dict the way the gui does so a later reconnect re-rolls a random
favourite and re-resolves a profile. A plain --random pick is
deliberately untagged: a one-off pick replays as the concrete server.

The cli also records its established connections now -- previously
only the gui wrote last_server.json, so a cli connect was invisible
to autoconnect.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
mysticalsoap deleted branch 123-decision-module 2026-08-28 15:18:15 -04:00
Sign in to join this conversation.
No description provided.