Steps as the first DailyMetric #8
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What to build
The tracer slice for ADR 0008 and the
DailyMetricmachinery. One metric end-to-end: domain value object, storage, manual write, read back, display.The shape matters more than the feature. A struct holding a kind beside a loose number makes invalid states constructible — a step count tagged as HRV compiles cleanly, because the kind is data and the value is untyped. Kind and value are therefore one type:
MetricKindsurvives as a payload-free discriminant for naming a kind without a value, but it is derived from the value and never stored beside it.Each newtype validates its own range in
new(), following the established value-object convention (new()validates,from_persistence()does not,value()reads). Units live in the type, not in a field name. Eleven near-identical bounded-integer newtypes justify a macro, as the existing identity-newtype macro already does for UUID types.SourceisManualor aProvider. ADailyMetricsourcedManualis never overwritten by an import; a manual write always supersedes a Provider's.(User, Date, MetricKind)is unique.Hydration is fallible in a way entry loading is not — a row can carry a kind this build does not know, or a value a later-tightened range rejects. Skip such rows and record them; do not fail the query.
Acceptance criteria
MetricValueis an enum of validated newtypes;MetricKindis derived from it(User, Date, MetricKind)is unique; re-writing a date upsertsManualmetric is not overwritten by aProviderwrite; aManualwrite always winsDateend to endDateresolution uses the rule from #2Blocked by