Skip to content

session_info.hpp

SessionInfo + the §18.5 session header — provenance as the FIRST lines of every run.

This header declares 1 type (5 members), 1 free function, and 3 constants.

Extracted from include/shulib/diag/session_info.hpp — this page is that header's documentation, reformatted, so it cannot disagree with the code. Prose about how to think about the API lives in the user guide; worked recipes live in the cookbook; this page is the complete, mechanical list of what exists.

Contents

struct SessionInfo

struct SessionInfo

Provenance for one run. string_views: the caller keeps the storage alive for the emitSessionHeader() call only (they are read synchronously, never retained — RunSummary re-copies what it needs into bounded arrays).

struct, declared at include/shulib/diag/session_info.hpp:41.

SessionInfo::buildHash

std::string_view buildHash{}

From diag::compiledBuildHash() in the app's own TU. EMPTY = missing = LOUD.

field, declared at include/shulib/diag/session_info.hpp:43.

SessionInfo::routineId

std::string_view routineId{}

e.g. "redLeftTall"

field, declared at include/shulib/diag/session_info.hpp:44.

SessionInfo::alliance

std::string_view alliance{}

"red" / "blue" / "skills"

field, declared at include/shulib/diag/session_info.hpp:45.

SessionInfo::side

std::string_view side{}

"left" / "right"

field, declared at include/shulib/diag/session_info.hpp:46.

SessionInfo::portMap

std::string_view portMap{}

caller-authored at C5; G1 generates (header note)

field, declared at include/shulib/diag/session_info.hpp:47.

kMaxHashBytes

inline constexpr std::size_t kMaxHashBytes = 47

Bounds for the header's caller-controlled fields (sanitized appends; the sink itself re-sanitizes — defense in depth, and these keep one field from eating the line).

constant, declared at include/shulib/diag/session_info.hpp:53.

kMaxFieldBytes

inline constexpr std::size_t kMaxFieldBytes = 24

routine/alliance/side

constant, declared at include/shulib/diag/session_info.hpp:54.

kMaxPortMapBytes

inline constexpr std::size_t kMaxPortMapBytes = 96

the port map is the long one

constant, declared at include/shulib/diag/session_info.hpp:55.

emitSessionHeader

inline void emitSessionHeader(hal::ITelemetrySink& sink, const SessionInfo& info, units::Voltage batteryStart)

Emit the §18.5 session header: three [SES] Info lines (plus the [ERROR][SES] line FIRST when the hash is missing). batteryStart must be a live reading (header note). Byte shapes pinned by test/session_header_test.cpp. [t= 0.00] [SES] run start · build 0b4948a-dirty · routine "redLeftTall" [t= 0.00] [SES] alliance red · side left · batt 12.40V [t= 0.00] [SES] ports L1,2,3 R4,5,6 IMU10

free function, declared at include/shulib/diag/session_info.hpp:64.

Design commentary, from the header

The header opens with the reasoning behind these shapes. It is reproduced here in full because a reference that only lists signatures teaches nobody why.

The header’s own reasoning — 27 lines
 SessionInfo + the §18.5 session header — provenance as the FIRST lines of every
 run (WS13, chunk C5).

 §18.5: "First record of every run: git build hash + routine id + alliance/side +
 port map + battery start — lets us compare/reproduce runs and confirm exactly
 which binary produced a given log." The header is what turns a pile of logs into
 an archive: without it, two traces that disagree cannot even be attributed to
 two binaries.

 The header rides the log() channel as [SES]-tagged Info lines (the FaultLatch
 precedent: the OWNER formats structured text, the sink sanitizes and frames it),
 which is what gives it the exact "[t=…] [SES] …" §18.3 shape through TermSink —
 and lets a message-only sink capture provenance too.

 THE MISSING-HASH PATH IS LOUD (build_info.hpp carries the full rationale): an
 empty buildHash emits an [ERROR][SES] line FIRST — before anything else — and
 the header line renders the literal token MISSING. Never a plausible value.

 Field notes:
   * portMap is CALLER-AUTHORED text at C5 ("L1,2,3 R4,5,6 IMU10"): the core HAL
     deliberately has no port numbers (fakes don't have ports), so the honest v1
     is a pass-through string; G1's RobotBuilder generates it from the profile.
   * alliance/side are free text ("red"/"left"/"skills"); empty fields render as
     "-" so a blank never silently vanishes from a column.
   * battery start is READ, not caller-typed — a typed 12.6 that was actually
     11.9 is the lying-number class this chunk bans.

Last updated 2026-08-15 — published from the main release branch, commit fa545ff. This site tracks releases, so between them it can lag the repository — that lag is deliberate, and it is what keeps the development log off the public site. For the current state of the code, see the repository.