feat(version): single-source semver, ext-state stamp, show-version action

Version "0.9.01" sourced once from CMake via configure_file'd header; pure
app_version module (parse/compare/classify) with CTest. Stamp rides the persist
save seam under "reasampler"/"version"; absent stamp reads as pre-versioning.
On-demand "show version" action, no startup print.
This commit is contained in:
2026-07-26 15:16:55 -04:00
parent 791a9c60eb
commit f6dddbf5a3
8 changed files with 409 additions and 2 deletions
+24
View File
@@ -19,6 +19,7 @@
#include <string>
#include "app_version.h"
#include "bank_book.h"
#include "bank_model.h"
#include "owned_manifest.h"
@@ -70,6 +71,14 @@ inline constexpr const char* kProjExtTailKey = "tail_setting";
// graceful, but the attribution safety net is lost until the next capture rebuilds it).
inline constexpr const char* kProjExtOwnedKey = "owned_files";
// The ext-state key holding the ReaSampler version that last WROTE this project
// (Phase V, V1). Written on every save alongside the banks/view/tail keys, so every
// saved .rpp records which build produced its state — the seam a future within-channel
// forward migration keys off ("this was written by 0.9.01, I am 0.9.05"). An absent
// key is the explicit pre-versioning case (a project saved before this shipped), read
// silently, never an error. FOREVER-STABLE key string once shipped.
inline constexpr const char* kProjExtVersionKey = "version";
// The ext-state key holding a GUID we mint per project to establish CONTENT-BASED
// project identity (REAPER exposes no stable per-project GUID). poll() uses it to
// tell a genuine Save-As (same GUID, new .rpp path) apart from a project switch
@@ -143,6 +152,15 @@ public:
OwnedFileManifest& owned() { return owned_; }
const OwnedFileManifest& owned() const { return owned_; }
// The ReaSampler version that last WROTE the active project, recovered from its
// ext-state stamp on load (Phase V, V1). PreVersioning when the project carries no
// stamp (saved before this feature), Unknown for a malformed stamp, Stamped with the
// exact stored string otherwise — all silent, never an error. Replaced on every load
// path (peer-symmetry with bank_/view_/tail_); default PreVersioning for an unsaved
// or never-loaded session. Exposed so a future migration step (or diagnostics) can
// reason about the origin build without re-reading ext state.
const WritingVersion& writingVersion() const { return writingVersion_; }
// Serialize the current book (under the `banks` key), view model, and tail setting
// to the active project's ext state (namespace "reasampler"), and clear the retired
// legacy `bank_index` key. Non-destructive beyond writing our own ext-state keys.
@@ -208,6 +226,12 @@ private:
// the in-memory set matches disk. Absent key -> empty is graceful (older project).
OwnedFileManifest owned_;
// The writing-version stamp recovered on load (Phase V). Default PreVersioning;
// loadFromProject replaces it on every load path (peer to bank_/view_/tail_), so
// switching to a pre-versioning project reports PreVersioning rather than inheriting
// the previous project's stamp. Read-only to consumers via writingVersion().
WritingVersion writingVersion_;
// The project identity last observed by poll(), used to detect load/Save-As.
// The GUID is the PRIMARY signal (a different stored GUID = a different project
// of record = Load, immune to pointer recycling). The pointer disambiguates the