Repository navigation
[ai][mac][docs] Visualiser: set the Gerardus server address in Settings (Tailscale) - #832
Merged
Merged
Conversation
The address was the UserDefaults key alignment.serviceAddress with no UI, parsed as host:port by splitting on colons, so it could not take an IPv6 literal or omit the port, and changing it needed a restart. To reach Gerardus over Tailscale it has to be editable. - GerardusAddress.parse reads a host name or IP literal with an optional port (50061 by default): whitespace trimmed, names lower-cased, IPv6 with or without brackets, ports 1-65535, URLs and paths refused. It is kept as alignment.serviceAddress; the local server (127.0.0.1:50061) removes the key, so an unset preference behaves as before, and a value that no longer parses falls back to it. - Settings (Cmd-,) has the field, Connect and Use this Mac, and a status line naming the address in use and whether Gerardus answered there. - AlignmentSession.useServiceAddress drops the old channel and anything placed against it, closes the pane, saves the address and asks the new server at once (and every 30 s while connected). A late answer from the old server is ignored. The pane header names the server. - An IPv6 literal is dialled directly; names and IPv4 go through DNS. - NSLocalNetworkUsageDescription: Local Network privacy covers Wi-Fi and Ethernet networks, not VPNs (TN3179), so Tailscale needs no permission but a LAN address does. The sandbox already has network.client. Tests cover parsing (accepted and refused forms), persistence, the reconnect, the stale answer and the pane closing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ddol
added a commit
that referenced
this pull request
Oct 22, 2026
…ses, pose scoring and Snap (Gerardus #8) (#833) * [ai][mac] Alignment tests: two factories missed by the #831 and #832 merge #831 added two AlignmentTests sessions with the old client factory, `{ service }`, and #832 changed the factory to take the server address. Each passed alone; merged, the test target on main does not compile, and mac CI does not run on pushes to main. Both now take the address. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * [ai][mac][make] Alignment pane: automatic registration, hypotheses, pose scoring and Snap Gerardus PR 8 (05559d9) made Register run real ICP and EvaluatePose work. The pane now follows the operator loop of Gerardus's interface doc: - Register searches 30 m around the pose drawn now at every heading (10-25 s, with Cancel). Each hypothesis shows as it converges; when the run ends they are ranked, the best is drawn, and the six gates are listed with their values. A run with none leaves the operator's pose. - Picking a hypothesis draws it, and Accept records it by id: REGISTERED when every gate passed, else MANUALLY_PLACED. Moved off it, Accept records the pose as it stands (source MANUAL, or ICP if snapped). - Once the pose rests for 0.4 s, EvaluatePose scores it with a residual per uploaded scan point; the scan is drawn over its background coloured by residual (green on the surface to red at 0.5 m, grey out of reach). A late score of an earlier pose is dropped. Snap is EvaluatePose(refine). - The vendored proto moves to 05559d9: FitQuality gains facade_p75_m and facade_range_slope, which the pane shows. Tests cover streaming, ranking and drawing the best, accepting by id or by pose, failed runs, scoring on rest with residual colouring, stale scores, Snap, cancelling, and the residual palette. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * [ai][docs] Gerardus alignment pane: registration, scoring and residuals documented The hub doc covers what now ships: Register with its hypotheses and gates, what Accept records, scoring once the pose rests with the scan coloured by residual, and Snap. The operator's path table gains the hypothesis, nudge-and-score and Snap rows. The plan's pose-scoring item is delivered; it stays Parked on tie points and the pose endpoint. The backlog moves the item to Complete. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The visualiser's Gerardus server address can now be set in Settings (⌘,), so the app can reach Gerardus on another machine over Tailscale. Before, the address was the
alignment.serviceAddressUserDefaults key with no UI. It was parsed by splitting on:, so it could not take an IPv6 literal or leave out the port, and a change needed a restart.The server side is Gerardus's change to listen on
0.0.0.0:50061by default (branchdd/feat/tailscale-bind-1021). Nothing here waits for it: an unset preference still means127.0.0.1:50061.Changes
GerardusAddress(gRPC/GerardusAddress.swift) parses and normalises the address in one function,GerardusAddress.parse:127.0.0.1,machine.tailnet.ts.net,100.64.0.1:50061,[fd7a:115c:a1e0::1]:50061.user@host, malformed IPv6 and dotted numbers that aren't IPv4 are refused.alignment.serviceAddress. Choosing the local server removes the key, so an unset preference behaves exactly as before, and a saved value that no longer parses falls back to the local server.UI/AlignmentSettingsView.swift, the app's firstSettingsscene):AlignmentSession.useServiceAddressdoes the following:GerardusClienttakes the parsed address. An IPv6 literal is dialled directly, while names (MagicDNS included) and IPv4 go through the resolver.docs/ui/visualiser/gerardus-alignment.mdand the visualiser README.macOS network permissions
What I found:
com.apple.security.network.clientwas already inVelocityVisualiser.entitlements, so outgoing connections to any host were allowed. No change needed.utunand needs no Local Network permission. Confirmed below, with no prompt.NSLocalNetworkUsageDescription(asINFOPLIST_KEY_NSLocalNetworkUsageDescriptionin both configurations) so the system prompt explains why.Tests
Added to
VelocityVisualiserTests/AlignmentTests.swift:GerardusAddressTests:description, and 18 refused forms give the expected error;AlignmentAddressChangeTests:make test-macpasses: 1,341 Swift Testing tests plus the XCTest suite, 0 failures.make build-mac(Release) builds clean, and the builtInfo.plistcarries the usage string.Verified in the running app
I ran the Release build against the running velocity.report and the Gerardus now listening on
0.0.0.0:50061. Each run passed the address as a launch argument (-alignment.serviceAddress …), which saves nothing, and I read the app's sockets after 9 s:100.x)100.x:50061ESTABLISHED, no Local Network prompt100.x, ESTABLISHED192.0.2.1:50061(unroutable)127.0.0.1:1(refused)http://nope/(unreadable)127.0.0.1:50061, ESTABLISHEDIn every run the velocity.report stream (
50051) stayed up, the app stayed alive, and no crash report was written.Not verified: the Settings window itself, i.e. typing an address and reading the status line. This session can neither see nor click the app's windows. The same code path (
useServiceAddress) is covered by the tests above.Overlap
#831 (hint heading, open) also touches
AlignmentSession.swift,AlignmentTests.swiftand the hub doc, in other hunks. Whichever merges second may need a small merge.🤖 Generated with Claude Code