Files
Behavision/agent
Suriyakumarvijayanayagam 50d122e5f0 An unused constant was a Stop() that could hang forever
Ran staticcheck across all three Go modules for the first time. server
(23k lines) and desktop came back clean. agent had seven findings, and
one of them was not tidiness.

`stopGrace = 10 * time.Second` was declared and wired to nothing.
Stop() cancels the context, cmd.Cancel kills the process tree, and then
Stop() blocks on cmd.Wait() - which, with no WaitDelay set, waits not
just for the process but for every writer of its stdout pipe to close.
One grandchild still holding that pipe hangs Wait, hangs Stop, and on the
desktop app that is the tray's Quit never returning. The constant named
the intent and nothing read it. cmd.WaitDelay = stopGrace is the line
that was missing.

The rest were real but small: an unused field in the live relay, an
unused sleep helper in the pump, and "net/url" imported twice under two
names - both genuinely used, in two functions doing the same job for the
same reason, so they are unified rather than one deleted. My first pass
deleted the wrong one on a bad grep and the build caught it immediately.

Three findings are suppressed rather than fixed, with the reason stated:

- Two "error strings should not end with punctuation". Both are
  multi-line messages a shop operator reads at a counter, not errors
  anything wraps. ST1005 exists because wrapped errors concatenate
  mid-sentence; stripping the full stops would run three sentences
  together to satisfy a rule that does not apply.
- A deliberately nil context in a pump test - the point of the test is
  that an unconnected client does not panic. It already carried
  //nolint:staticcheck, which is golangci-lint's directive and
  staticcheck ignores, which is why it kept being reported.

Also tidied agent/go.mod, which had paho and x/sys marked indirect while
being imported directly.

All three modules clean, all suites pass: 21 Go packages, 226 engine
tests.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KGcjxF1cNLcuwc3DAPcnfj
2026-09-30 15:14:09 +05:30
..

Behavision agent (Go)

The half of the edge install that touches the network. The Python engine keeps the cameras and the models; this keeps the tray icon, the UI shell, the MQTT connection and the offline queue.

┌─ agent (Go) ───────────────────┐        ┌─ engine (Python) ────────┐
│ tray icon + WebView2 window    │        │ RTSP capture             │
│ supervises the engine process  │───────▶│ YuNet / ArcFace / FAISS  │
│ MQTT publish + offline spool   │◀───────│ SQLite (biometric)       │
│ S3 handoff, tenant config      │  local │ localhost API + events   │
└────────────────────────────────┘  HTTP  └──────────────────────────┘

Why the split

Go cannot run ONNX, OpenCV or FAISS, so the engine stays Python and ships frozen. Go is here for what it is actually better at: a durable queue that survives a store's internet dropping, a supervised child process, and one language shared with the server so the MQTT contract has a single definition.

Why not a Windows service

A service runs in session 0 and cannot draw a tray icon — that is Windows session isolation, not a library limitation. Since the product is "user starts and stops it from the tray", the agent is a normal user-session process that spawns the engine as a child. That also means it never needs elevation at runtime: starting a child process does not, controlling a service does.

internal/engine is written so a service wrapper can be added later without touching the supervision logic.

Layout

main.go              entry point, mode dispatch
internal/engine      start/stop/supervise the Python engine, health polling
internal/spool       durable event queue (survives restart and outage)
internal/mqtt        broker client, publishes from the spool
internal/config      tenant identity, broker settings, credentials
frontend/            React UI served into the WebView

Build

go build ./...            # agent alone
wails build               # agent + frontend, once the UI is added