Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions aicontext/features/core/versioning/feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Feature: Versioning

> Owner: shared | Last reviewed: 2026-07-03 | Canonical: yes
> Scope: The independent version numbers across HSM — what each is, and when to bump it.

---

## Overview

HSM carries **four independent** version numbers, **one per product**. They are not tied to each other:
each tracks a different product, is allowed to diverge, and bumping one never implies bumping another.
Authoritative bump rules live in the directory `AGENTS.md` files.

## The four versions

| Product | Version (where) | When to bump |
|---|---|---|
| **Native (C++) collector** | `HSM_COLLECTOR_VERSION_{MAJOR,MINOR,PATCH}` — `src/native/collector/include/hsm_collector/hsm_collector.h` (mirror in `CMakeLists.txt project VERSION`) | **MAJOR** breaking ABI · **MINOR** new exported `hsm_*` function / appended struct field · **PATCH** backward-compatible behavior/logic change, no ABI change (e.g. a logging fix). → `src/native/collector/AGENTS.md` |
| **Managed (C#) collector** | `src/collector/HSMDataCollector/HSMDataCollector.csproj <Version>` | At a DataCollector NuGet release. |
| **HSM site / server** | `src/server/HSMServer/HSMServer.csproj <Version>` | At a server release. |
| **Agent** | `src/agent/CMakeLists.txt` → `project(HsmAgent VERSION …)` (`HSM_AGENT_VERSION`) | On **any change to the shipped agent binary** — including a native-collector change compiled into it — else self-update can't deliver it (it ships a build only when its version is *strictly greater* than the running agent's). → `src/agent/AGENTS.md` |

## Key points

- The **C++ collector** and the **C# collector** are two separate products. Each reports **its own**
version as the `.module/Collector version` sensor, and they may differ (C++ `0.x`, C# `3.4.x`). There
is no shared "product version" tying them together. Conformance compares the two collectors' wire
byte-for-byte but does **not** compare the version *value*, so the divergence is safe.
- The **agent** embeds the native collector but is its own product: a collector change bumps the
collector version **and** (because the agent binary changed) the agent version — two independent
bumps for two products.
55 changes: 24 additions & 31 deletions src/native/collector/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,27 @@ supplement the root [`AGENTS.md`](../../../AGENTS.md); where a rule here refines
specific rule wins. Sibling: [`../../agent/AGENTS.md`](../../agent/AGENTS.md) (the agent that embeds this
collector).

## Versioning — two numbers, do not confuse them

Both live in [`include/hsm_collector/hsm_collector.h`](include/hsm_collector/hsm_collector.h) and are
**distinct from any host application's version** (e.g. the agent's `HsmAgent VERSION`).

### 1. C ABI version `HSM_COLLECTOR_VERSION_*` — bump it when the C ABI grows

- **Rule:** whenever a PR **adds or changes an exported `hsm_*` C ABI function, or appends a struct
field**, bump this version **in the same PR** — `MINOR` for additive, backward-compatible growth;
`MAJOR` for any breaking change (reorder/remove a field, change a function's semantics). Policy is
stated in the header and `docs/native-collector-c-abi.md`.
- **Keep `CMakeLists.txt` `project(HsmCollectorNative VERSION x.y.z)` in sync** with the header macros —
it feeds the `find_package(hsm_collector x.y)` compatibility check, so a drift silently lets an
incompatible consumer link.
- This is the C++/native code's own version. **If you touch the native/C-ABI code in a way that changes
what a consumer can call or observe, this number moves.**

### 2. Product version `HSM_COLLECTOR_PRODUCT_VERSION` — pinned to the managed collector

- This is the `.module/Collector version` sensor value — the shared **HSMDataCollector product** number.
- **Keep it byte-identical to the managed collector** (`src/collector/HSMDataCollector/HSMDataCollector.csproj`
`<Version>`) so the native port and the C# collector report the same product version. **Do NOT bump it
native-only** — that diverges two collectors meant to report one product version.
- It moves only at a **DataCollector product release**, in lockstep on BOTH sides. A native-only parity
change (native catching up to existing managed behavior) does not move it.

**Precedent (#1221):** the built-in file logger added the C ABI function `hsm_collector_enable_file_logging`
but did **not** bump `HSM_COLLECTOR_VERSION` — an ABI-hygiene miss (a new function owes a `MINOR` bump).
It correctly left `HSM_COLLECTOR_PRODUCT_VERSION` at `3.4.12` (native parity with the managed collector,
which had no release). The fix bumped the ABI to `0.6.0` and resynced `CMakeLists.txt` (which had also
drifted to `0.4.0`).
## Versioning — the native collector's own version

The native collector has **one** version: `HSM_COLLECTOR_VERSION_{MAJOR,MINOR,PATCH}` in
[`include/hsm_collector/hsm_collector.h`](include/hsm_collector/hsm_collector.h) (keep `CMakeLists.txt`
`project(HsmCollectorNative VERSION x.y.z)` in sync — it feeds the `find_package(hsm_collector x.y)`
compatibility check, so a drift silently lets an incompatible consumer link). It is **INDEPENDENT** of
the managed C# collector, the host application (e.g. the agent's `HsmAgent VERSION`), and the server —
each is a distinct product with its own version. It is also the value the native collector reports as
the `.module/Collector version` sensor (`HSM_COLLECTOR_VERSION_STRING`, the `MAJOR.MINOR.PATCH` form).

**Bump it in the same PR as the change, per semver:**
- **MAJOR** — a breaking ABI change (reorder/remove a struct field, change a function's semantics).
- **MINOR** — additive, backward-compatible ABI growth (a new exported `hsm_*` function, an appended
struct field).
- **PATCH** — a backward-compatible behavior/logic change that does **not** touch the ABI (e.g. a
logging change).

Do **not** pin it to the managed C# collector (`HSMDataCollector.csproj <Version>`) — they are two
separate products and are allowed to diverge. Conformance compares the two collectors' wire
byte-for-byte but does **not** compare the `.module/Collector version` *value*, so a diverging version
is safe.

Full map of HSM's versions:
[`aicontext/features/core/versioning/feature.md`](../../../aicontext/features/core/versioning/feature.md).
2 changes: 1 addition & 1 deletion src/native/collector/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.21)

# VERSION tracks the C ABI semver (HSM_COLLECTOR_VERSION_* in include/hsm_collector/hsm_collector.h);
# keep the two in sync. It feeds the find_package(hsm_collector x.y) version check (#1100).
project(HsmCollectorNative VERSION 0.6.0 LANGUAGES CXX)
project(HsmCollectorNative VERSION 0.6.1 LANGUAGES CXX)

# ---------------------------------------------------------------------------
# Target topology (epic #1093 / issue #1095 §1 — "core lib / C ABI lib / C++
Expand Down
24 changes: 13 additions & 11 deletions src/native/collector/include/hsm_collector/hsm_collector.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,24 @@ extern "C"
{
#endif

/* ABI version. Bumped per the policy in docs/native-collector-c-abi.md: MINOR
for additive, backward-compatible growth (new functions, struct fields
appended); MAJOR for any breaking change (field reorder/removal, semantic
change). hsm_collector_version() returns the packed value at runtime. */
/* The native collector's OWN version (semver) — INDEPENDENT of the managed C# collector, the host
application (e.g. the agent), and the server; each is a distinct product with its own version.
Bump per src/native/collector/AGENTS.md: MAJOR for a breaking ABI change; MINOR for additive ABI
growth (a new exported hsm_* function / appended struct field); PATCH for a backward-compatible
behavior/logic change that does not touch the ABI (e.g. a logging change). hsm_collector_version()
returns the packed value at runtime; HSM_COLLECTOR_VERSION_STRING is the "MAJOR.MINOR.PATCH" form
reported as the ".module/Collector version" sensor. */
#define HSM_COLLECTOR_VERSION_MAJOR 0
#define HSM_COLLECTOR_VERSION_MINOR 6
#define HSM_COLLECTOR_VERSION_PATCH 0
#define HSM_COLLECTOR_VERSION_PATCH 1
#define HSM_COLLECTOR_VERSION \
((HSM_COLLECTOR_VERSION_MAJOR * 10000) + (HSM_COLLECTOR_VERSION_MINOR * 100) + HSM_COLLECTOR_VERSION_PATCH)

/* Collector PRODUCT version — the value reported as ".module/Collector version". This is the
HSMDataCollector product line and is DISTINCT from the C ABI version above (and from any host
application's own version). Keep it in sync with the managed collector's version
(src/collector/HSMDataCollector/HSMDataCollector.csproj <Version>) so the native port and the
C# collector report the same product version. */
#define HSM_COLLECTOR_PRODUCT_VERSION "3.4.12"
#define HSM_COLLECTOR_VERSION_STRINGIFY_(x) #x
#define HSM_COLLECTOR_VERSION_STRINGIFY(x) HSM_COLLECTOR_VERSION_STRINGIFY_(x)
#define HSM_COLLECTOR_VERSION_STRING \
HSM_COLLECTOR_VERSION_STRINGIFY(HSM_COLLECTOR_VERSION_MAJOR) \
"." HSM_COLLECTOR_VERSION_STRINGIFY(HSM_COLLECTOR_VERSION_MINOR) "." HSM_COLLECTOR_VERSION_STRINGIFY(HSM_COLLECTOR_VERSION_PATCH)

typedef struct hsm_collector_t hsm_collector_t;
typedef struct hsm_sensor_t hsm_sensor_t;
Expand Down
14 changes: 7 additions & 7 deletions src/native/collector/src/hsm_collector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3314,9 +3314,9 @@ namespace
}

// Optional host override for the reported ".module/Collector version". Empty (default) ->
// HSM_COLLECTOR_PRODUCT_VERSION (the collector product line). A host must NOT set this to its
// own application version: collector and host (e.g. the agent) are distinct products with
// distinct version lines. Reserved for embedders that genuinely re-brand the collector build.
// HSM_COLLECTOR_VERSION_STRING (the native collector's own version). A host must NOT set this
// to its own application version: collector and host (e.g. the agent) are distinct products
// with distinct version lines. Reserved for embedders that genuinely re-brand the collector.
void SetCollectorVersionOverride(std::string version) { collector_version_override_ = std::move(version); }
const std::string& CollectorVersionOverride() const { return collector_version_override_; }

Expand Down Expand Up @@ -7042,12 +7042,12 @@ hsm_result_t hsm_collector_add_collector_monitoring_sensors(hsm_collector_t* col
std::shared_ptr<NativeSensor> collector_version;
if (collector->impl->AddDefaultSensor(HSM_DEFAULT_COLLECTOR_VERSION, &params, collector_version) == HSM_RESULT_OK)
{
// Report the collector PRODUCT version (HSMDataCollector line), NOT the C ABI version
// and NOT the host application's version — collector and host (e.g. the agent) are
// distinct products. An explicit host override still wins if set.
// Report the native collector's OWN version (HSM_COLLECTOR_VERSION_STRING), independent of
// the managed C# collector, the host application (e.g. the agent), and the server — each is
// a distinct product with its own version. An explicit host override still wins if set.
const std::string& override_ver = collector->impl->CollectorVersionOverride();
const std::string version = override_ver.empty()
? std::string(HSM_COLLECTOR_PRODUCT_VERSION)
? std::string(HSM_COLLECTOR_VERSION_STRING)
: override_ver;
EmitVersionStartValue(collector->impl.get(), collector_version, version.c_str());
}
Expand Down
6 changes: 3 additions & 3 deletions src/native/collector/tests/hsm_collector_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4093,9 +4093,9 @@ namespace
saw_collector = true;
Contains(payload, "\"Type\":8");
Contains(payload, "Start:");
// Collector PRODUCT version (HSM_COLLECTOR_PRODUCT_VERSION) — NOT the C ABI version
// and NOT any host/agent version. Collector is a distinct product (#1189 follow-up).
Contains(payload, HSM_COLLECTOR_PRODUCT_VERSION);
// The native collector's own version (HSM_COLLECTOR_VERSION_STRING) — NOT the managed
// collector's, NOT any host/agent version. Collector is a distinct product.
Contains(payload, HSM_COLLECTOR_VERSION_STRING);
}
}

Expand Down
Loading