From 123dad26d55f19a549131b97a407c1cb0a7b2800 Mon Sep 17 00:00:00 2001 From: Enrico Piovesan Date: Mon, 17 Aug 2026 22:53:25 -0600 Subject: [PATCH] docs: record traverse-registry 0.15.0 release (decision 60, closes #145 gap) Documents decision-log entry 60: the resolve usage-telemetry event (Spec 015), the ResolveTelemetry API shape, why FR-006 kept the internal transitive-dependency walk untelemetered, and publish/verification evidence for the 0.15.0 release. Co-Authored-By: Claude Sonnet 5 --- docs/decision-log.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/decision-log.md b/docs/decision-log.md index c631e84..7e41533 100644 --- a/docs/decision-log.md +++ b/docs/decision-log.md @@ -322,3 +322,13 @@ No FR text changed -- this is scope-clarifying, not requirement-changing (FR-002 **Followed the existing pipeline exactly** (spec `010-crate-publish-pipeline`): `git tag -a v0.14.0` + `git push origin v0.14.0` triggered `.github/workflows/publish-crate.yml`, which built, ran `cargo publish` with the org's `CARGO_REGISTRY_TOKEN`, and ran its built-in isolated-consumer smoke test -- all green. Confirmed independently via the crates.io API (`newest_version`/`max_version` both `0.14.0`) and via a second, genuinely isolated external-consumer project (fresh temp directory outside the workspace, `traverse-registry = "=0.14.0"` resolved from crates.io, `traverse-contracts` resolving to its own latest `0.9.1` rather than this repo's pinned `0.8.1`) that built and ran `resolve_executable_artifact`/`detect_artifact_drift` against the real published API end-to-end. **Registry remains the authoritative owner of this contract, per explicit instruction**: this entry is where the release is documented; nothing in `traverse-framework/traverse`'s own issue tracker was touched from this repo, and the activation/resolution model is not duplicated there. + +60. **`traverse-registry` 0.15.0 published: resolve usage-telemetry event per Spec 015, `#145` unblocked and closed (2026-08-18, registry-ops loop)**: `#145` had sat `Blocked` since decision 47 / spec `015-runtime-usage-telemetry-resolve-hook` was written, waiting on `traverse-framework/traverse`#927 to publish the `UsageTelemetrySink` trait in `traverse-contracts`. Checked directly rather than trusting the stale `blocked` label: `traverse`#927 closed 2026-08-04, and `traverse-contracts` 0.9.1 (already inside this repo's existing `>=0.8.1, <0.10.0` pin range) ships the trait, `NoOpUsageTelemetrySink`, and `UsageEvent`/`UsageEventKind` in a dedicated `usage_telemetry` module. The blocker was gone; the `blocked` label was stale. + +**Implementation, minimally scoped to spec 015's own text**: `resolve_version_range` (`semver_resolver.rs`) — the crate's caret-range/semver resolution entry point, spec 015 FR-001's literal target — gained a fifth parameter, `telemetry: Option>`, where `ResolveTelemetry { sink: &dyn UsageTelemetrySink, resolved_at: &str }` bundles the port with a caller-supplied ISO-8601 timestamp string. The caller-supplied-timestamp design (rather than this crate calling a wall clock itself) mirrors every other `registered_at`-style field already in this crate and matches how `traverse-cli`'s own `execute`-event caller stamps `Utc::now()` itself before calling `sink.record()` -- keeping `traverse-registry` fully deterministic and free of any new dependency (FR-004), which `cargo tree -p traverse-registry` confirms: the dependency set is unchanged beyond the `traverse-contracts` 0.8.1 -> 0.9.1 bump, no new crate. On success the sink is invoked exactly once with `UsageEventKind::Resolve` and `capability_ref: format!("{capability_id}@{version}")` -- the same `{id}@{version}` literal shape `traverse-cli` already uses for `execute` events (no `namespace/id` slash; this org's capability ids are already namespace-qualified dotted strings), so both counters stay comparable in the shared collector. Failed and ambiguous resolutions never invoke it. Per FR-006's explicit restriction against justifying further behavior changes, `dependency_resolver.rs`'s own internal call into `resolve_version_range` (the transitive-dependency walk, a different call path than "`registry sync` and equivalent callers") was left passing `None` -- untelemetered, unchanged. + +**Verified**: `cargo test -p traverse-registry --locked` (184 lib tests, including 5 new ones covering SC-001 exact-once-on-success, SC-002 across all three failure branches -- not-found, no-satisfying-version, and ambiguous-match -- and SC-003's byte-for-byte `Result` equality with/without telemetry, plus all pre-existing integration suites) and `cargo clippy -p traverse-registry --all-targets --locked -- -D warnings`, both clean, before tagging. + +**Followed the existing pipeline exactly** (spec `010-crate-publish-pipeline`): `git tag -a v0.15.0` + `git push origin v0.15.0` triggered `.github/workflows/publish-crate.yml`, which built, ran `cargo publish` with the org's `CARGO_REGISTRY_TOKEN` (`Published traverse-registry v0.15.0 at registry crates-io`), and ran its built-in isolated-consumer smoke test -- resolved `traverse-registry 0.15.0` from crates.io fresh and built it, all green. + +**Registry remains the authoritative owner of this contract, per explicit instruction**: this entry is where the release is documented; nothing in `traverse-framework/traverse`'s own issue tracker was touched from this repo.