Hedgr is a multi-instance desktop client for OreStudio over NATS. It holds many instances at once, each with its own accounts and sessions, and draws each session’s work in its own floating window.
There is no per-window marker option and no notion of “the” instance. One Hedgr process holds the whole set, so there is nothing to tell apart.
Hedgr follows the OreStudio component conventions. Each component is a
single-module component: a CMake root that adds src, tests and modeling,
with include/<component>/ holding one folder per facet.
| Component | Holds |
|---|---|
hedgr.model | Value types, live state tables, commands and events. |
hedgr.store | The SQLite schema and its repositories. |
hedgr.session | The blocking NATS transport and the IAM login round trip. |
hedgr.runtime | The thread pool, the session workers and the state owner. |
hedgr.ui | ImGui and ImPlot rendering, icons and theme. |
hedgr.imgui | The executable: the GLFW window, the frame loop, the wiring. |
Dependencies run one way only. hedgr.model depends on nothing else in Hedgr,
and hedgr.ui does not depend on hedgr.runtime: the interface reads the state
tables and pushes commands, and the runtime applies them.
CONTEXT.mdis the glossary. Read it before naming anything.docs/adr/holds the decisions that were hard to reverse, with the alternatives that lost.
Hedgr consumes a pre-built OreStudio: its headers come from the OreStudio source tree and its shared libraries from an OreStudio build output.
build/scripts/build.sh # configure and build everything
build/scripts/build-target.sh hedgr.ui.lib # one target, no reconfigureThe release build lands in build/output/linux-clang-release/publish/.
The publish directory is the deployable artefact. The build copies OreStudio’s
shared libraries into publish/lib and rewrites their RUNPATH, so the tree
runs from wherever it is unpacked. Copying the files is not enough: a bundled
library that keeps an absolute RUNPATH resolves its own dependencies through
that path and fails even with the file beside it.
build/scripts/build-target.sh package_hedgr # publish/ -> hedgr-<ver>.tar.gz
build/scripts/deploy.sh # package, copy, unpack, verify
HEDGR_DEPLOY_HOST=goedel HEDGR_DEPLOY_DIR=hedgr build/scripts/deploy.shThe host keeps one directory per version and a current symlink, so a deploy
never overwrites a running version. The smoke test runs --version, which the
argument parser answers without opening a window, and it proves the bundle is
complete because the loader resolves every library before main runs.
patchelf is required to build the package.
The environment supplies the connection settings; Hedgr reads the ORES_HEDGR_*
variables and never persists a credential. It starts fullscreen; F11 toggles.
build/scripts/run.shA Wayland session needs its display named explicitly when the variable is not already exported:
export WAYLAND_DISPLAY=wayland-0
build/scripts/run.shMesa prints EGL warnings about a missing driver on a machine with no GPU. They are not fatal, and the run still produces a frame.
To check a change without a person watching, ask for one frame; the process writes frame eight and leaves.
HEDGR_CAPTURE=$PWD/.cache/verify/frame.ppm build/scripts/run.shOne frame shows what the interface drew first, and an interface that cannot be used draws its first frame just as convincingly as one that can. A capture can be driven instead, so the frame shows the result of an interaction:
HEDGR_CAPTURE=$PWD/.cache/verify/frame.ppm \
HEDGR_CAPTURE_INPUT="expand Development
click laboratory" \
build/scripts/run.shThe steps are one per line, as <gesture> <row> [| <label>]+, where the gestures
are =click, click_arrow, expand, collapse and focus. A row is named as
an operator sees it, in quotes when the name holds a space. click selects the
row, click_arrow works its expander, expand and collapse state which way
the expander should end, and focus only moves the pointer. A control that is
not a row – a toolbar button – is named by the label after the bar.
Each gesture is a move, a press and a release, three frames apart, and a row is resolved against the frame the gesture before it produced. That is what lets one script open a folder and then click a row inside it. A step that names nothing on screen is reported on stderr with its line number, rather than driving whatever happens to be there.
HEDGR_CAPTURE_FOCUS=<window id> brings one window to the front for the frame,
which matters because the windows float over one another, and
build/scripts/capture.sh writes a layout of its own so that two runs’ frames
are comparable.
Logging is off until --log-enabled is given, and then
it goes to the console and to a file. The file is hedgr.imgui.log in a log
directory beside the store (.cache/hedgr/log in a source build, otherwise
$XDG_DATA_HOME/hedgr/log or ~/.local/share/hedgr/log), so the desktop entry
and a terminal write the same file. --log-filename, --log-directory and
--log-level override the parts, and the line “Logging to …” at the start of
a run names the file. ORE Studio’s logging writes a file only when given a name,
which is why a bare --log-enabled once left no file; Hedgr now supplies the
default. The file grows without a limit, so it is worth deleting between
sessions.
A chart’s history reads log at info with the series, the request (limit and
offset, or the time range) and the count. A failed read, an answer that could
not be decoded or was refused, and an empty answer log at warning with the
reason. Search the log for Market points and Market history.
Three places, and the compiler checks two of them:
- a new alternative in
model::domain::window_stateand a new enumerator inmodel::domain::window_kind; - a renderer in the table in
hedgr.ui/src/render/renderer.cpp, which is aconstexpr std::arrayindexed by kind, so a missing entry fails to compile; - an entry in the Instance Manager’s open-window action.
build/scripts/build-target.sh hedgr.model.tests
build/output/linux-clang-release/publish/bin/hedgr.model.tests