From dded00564edefd4506c4a060a83c1fd3d201591d Mon Sep 17 00:00:00 2001 From: Andrei Date: Fri, 3 Jul 2026 18:56:38 +0200 Subject: [PATCH 1/2] =?UTF-8?q?docs(aicontext):=20add=20versioning=20featu?= =?UTF-8?q?re=20=E2=80=94=20the=20independent=20version=20numbers=20+=20wh?= =?UTF-8?q?en=20to=20bump?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit One short map of HSM's independent versions (agent / native collector library / collector product / API DTO / server), where each lives, and the rule for bumping each. Notably: the collector LIBRARY version (HSM_COLLECTOR_VERSION, C++ ABI/build, PATCH for behavior fixes) is distinct from the collector PRODUCT version (.module/Collector version, 3.4.x, shared with the managed collector). Points at the authoritative AGENTS.md rules. Co-Authored-By: Claude Opus 4.8 --- aicontext/features/core/versioning/feature.md | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 aicontext/features/core/versioning/feature.md diff --git a/aicontext/features/core/versioning/feature.md b/aicontext/features/core/versioning/feature.md new file mode 100644 index 000000000..2d52b205d --- /dev/null +++ b/aicontext/features/core/versioning/feature.md @@ -0,0 +1,43 @@ +# 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 several **independent** version numbers. They are not tied to each other — each tracks a +different thing, so bumping one does not imply bumping another. This is the map; the authoritative +bump rules live in the directory `AGENTS.md` files. + +## The versions + +| Version | Where | What it tracks | +|---|---|---| +| **HSM Agent** | `src/agent/CMakeLists.txt` → `project(HsmAgent VERSION …)` (`HSM_AGENT_VERSION`) | The self-update **delivery key**: the server delivers a build only when its version is *strictly greater* than the running agent's. | +| **Native collector — library** | `src/native/collector/include/hsm_collector/hsm_collector.h` → `HSM_COLLECTOR_VERSION_{MAJOR,MINOR,PATCH}` (mirror in `CMakeLists.txt project VERSION`) | The C++ collector's own semver. Feeds `find_package(hsm_collector x.y)` + `hsm_collector_version()`. **Not** reported to the server. | +| **Collector product** | `HSM_COLLECTOR_PRODUCT_VERSION` (native) **and** `src/collector/HSMDataCollector/HSMDataCollector.csproj ` (managed) | The value of the `.module/Collector version` sensor — the shared **HSMDataCollector product** number. Native and managed are two language ports of one product, so they carry the **same** number (kept in lockstep; conformance compares them byte-identically). | +| **Shared API DTO** | `src/api/HSMSensorDataObjects/HSMSensorDataObjects.csproj ` | The wire-contract package shared by server, collector, and wrappers. | +| **Server** | `src/server/HSMServer/HSMServer.csproj ` | The HSM server application. | + +## When to bump + +- **Changed the agent binary** — including a native-collector change compiled into it → bump the + **Agent** version (patch). Otherwise self-update cannot deliver it. → `src/agent/AGENTS.md` +- **Native collector — ABI grew**: added/changed an exported `hsm_*` function or appended a struct + field → **MINOR** of the collector library version. +- **Native collector — breaking ABI**: removed/reordered a field or changed a function's semantics → + **MAJOR**. +- **Native collector — behavior/logic fix that does NOT touch the ABI** (e.g. a logging change) → + **PATCH** of the collector library version. → `src/native/collector/AGENTS.md` +- **DataCollector product release** → bump the **product** version on **both** native + (`HSM_COLLECTOR_PRODUCT_VERSION`) and managed (`.csproj`) in lockstep. A one-language behavior fix + does not move it on its own. → root `AGENTS.md` "Versioning" +- **Server / API-DTO release** → bump that `.csproj`. → root `AGENTS.md` "Versioning" + +## Don't conflate the two collector numbers + +The **library** version (`HSM_COLLECTOR_VERSION`, `0.x`) tracks the C++ ABI/build. The **product** +version (`.module/Collector version`, `3.4.x`, shared with the managed collector) is the release +identity reported to the server. They are different numbers for different purposes. From 42140e30bbcfc13daeecdb61733a8dd6a934fe86 Mon Sep 17 00:00:00 2001 From: Andrei Date: Fri, 3 Jul 2026 19:33:33 +0200 Subject: [PATCH 2/2] chore(native): decouple collector version from the managed collector + versioning docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per the agreed model (one independent version per product), the native C++ collector now reports its OWN version as .module/Collector version instead of a pinned copy of the managed collector's number. Remove HSM_COLLECTOR_PRODUCT_VERSION; add HSM_COLLECTOR_VERSION_STRING (MAJOR.MINOR.PATCH from the existing macros); report it. Bump the collector 0.6.0 -> 0.6.1 (PATCH, the log-quality fix #1225 owed) and add the PATCH rule to src/native/collector/AGENTS.md. Rewrite aicontext/features/core/versioning/feature.md to the 4-independent-versions model (C++ collector / C# collector / server / agent). Conformance-safe: the corpus golden captures only the collector_version REGISTRATION (value wildcarded), so C#(3.4.x) vs native(0.x) divergence does not affect PR CI. NOTE: the nightly diff-fuzzer does a direct C#-vs-native byte-compare — if it emits the collector-version sensor value it will need that value excluded (build-specific, not portable); watch the nightly lane. Co-Authored-By: Claude Opus 4.8 --- aicontext/features/core/versioning/feature.md | 50 +++++++---------- src/native/collector/AGENTS.md | 55 ++++++++----------- src/native/collector/CMakeLists.txt | 2 +- .../include/hsm_collector/hsm_collector.h | 24 ++++---- src/native/collector/src/hsm_collector.cpp | 14 ++--- .../collector/tests/hsm_collector_tests.cpp | 6 +- 6 files changed, 67 insertions(+), 84 deletions(-) diff --git a/aicontext/features/core/versioning/feature.md b/aicontext/features/core/versioning/feature.md index 2d52b205d..54c8729bf 100644 --- a/aicontext/features/core/versioning/feature.md +++ b/aicontext/features/core/versioning/feature.md @@ -7,37 +7,25 @@ ## Overview -HSM carries several **independent** version numbers. They are not tied to each other — each tracks a -different thing, so bumping one does not imply bumping another. This is the map; the authoritative -bump rules live in the directory `AGENTS.md` files. +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 versions +## The four versions -| Version | Where | What it tracks | +| Product | Version (where) | When to bump | |---|---|---| -| **HSM Agent** | `src/agent/CMakeLists.txt` → `project(HsmAgent VERSION …)` (`HSM_AGENT_VERSION`) | The self-update **delivery key**: the server delivers a build only when its version is *strictly greater* than the running agent's. | -| **Native collector — library** | `src/native/collector/include/hsm_collector/hsm_collector.h` → `HSM_COLLECTOR_VERSION_{MAJOR,MINOR,PATCH}` (mirror in `CMakeLists.txt project VERSION`) | The C++ collector's own semver. Feeds `find_package(hsm_collector x.y)` + `hsm_collector_version()`. **Not** reported to the server. | -| **Collector product** | `HSM_COLLECTOR_PRODUCT_VERSION` (native) **and** `src/collector/HSMDataCollector/HSMDataCollector.csproj ` (managed) | The value of the `.module/Collector version` sensor — the shared **HSMDataCollector product** number. Native and managed are two language ports of one product, so they carry the **same** number (kept in lockstep; conformance compares them byte-identically). | -| **Shared API DTO** | `src/api/HSMSensorDataObjects/HSMSensorDataObjects.csproj ` | The wire-contract package shared by server, collector, and wrappers. | -| **Server** | `src/server/HSMServer/HSMServer.csproj ` | The HSM server application. | - -## When to bump - -- **Changed the agent binary** — including a native-collector change compiled into it → bump the - **Agent** version (patch). Otherwise self-update cannot deliver it. → `src/agent/AGENTS.md` -- **Native collector — ABI grew**: added/changed an exported `hsm_*` function or appended a struct - field → **MINOR** of the collector library version. -- **Native collector — breaking ABI**: removed/reordered a field or changed a function's semantics → - **MAJOR**. -- **Native collector — behavior/logic fix that does NOT touch the ABI** (e.g. a logging change) → - **PATCH** of the collector library version. → `src/native/collector/AGENTS.md` -- **DataCollector product release** → bump the **product** version on **both** native - (`HSM_COLLECTOR_PRODUCT_VERSION`) and managed (`.csproj`) in lockstep. A one-language behavior fix - does not move it on its own. → root `AGENTS.md` "Versioning" -- **Server / API-DTO release** → bump that `.csproj`. → root `AGENTS.md` "Versioning" - -## Don't conflate the two collector numbers - -The **library** version (`HSM_COLLECTOR_VERSION`, `0.x`) tracks the C++ ABI/build. The **product** -version (`.module/Collector version`, `3.4.x`, shared with the managed collector) is the release -identity reported to the server. They are different numbers for different purposes. +| **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 ` | At a DataCollector NuGet release. | +| **HSM site / server** | `src/server/HSMServer/HSMServer.csproj ` | 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. diff --git a/src/native/collector/AGENTS.md b/src/native/collector/AGENTS.md index 6e50e20cf..4edb47ab3 100644 --- a/src/native/collector/AGENTS.md +++ b/src/native/collector/AGENTS.md @@ -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` - ``) 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 `) — 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). diff --git a/src/native/collector/CMakeLists.txt b/src/native/collector/CMakeLists.txt index a810273a4..d9362a9fb 100644 --- a/src/native/collector/CMakeLists.txt +++ b/src/native/collector/CMakeLists.txt @@ -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++ diff --git a/src/native/collector/include/hsm_collector/hsm_collector.h b/src/native/collector/include/hsm_collector/hsm_collector.h index 7b643075b..18ff4bf91 100644 --- a/src/native/collector/include/hsm_collector/hsm_collector.h +++ b/src/native/collector/include/hsm_collector/hsm_collector.h @@ -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 ) 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; diff --git a/src/native/collector/src/hsm_collector.cpp b/src/native/collector/src/hsm_collector.cpp index c568744bf..7baeac383 100644 --- a/src/native/collector/src/hsm_collector.cpp +++ b/src/native/collector/src/hsm_collector.cpp @@ -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_; } @@ -7042,12 +7042,12 @@ hsm_result_t hsm_collector_add_collector_monitoring_sensors(hsm_collector_t* col std::shared_ptr collector_version; if (collector->impl->AddDefaultSensor(HSM_DEFAULT_COLLECTOR_VERSION, ¶ms, 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()); } diff --git a/src/native/collector/tests/hsm_collector_tests.cpp b/src/native/collector/tests/hsm_collector_tests.cpp index a81b9a7ca..5c395180c 100644 --- a/src/native/collector/tests/hsm_collector_tests.cpp +++ b/src/native/collector/tests/hsm_collector_tests.cpp @@ -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); } }