mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 12:32:43 +00:00
Carry the configured flag onto the snapshot and digest wires
The dashboard snapshot copies it off the composite, the daily digest copies it off the snapshot, and the derived-metric payload already carries it inside the composite value. Optional on both DTOs like the score identity fields beside it, so older cached bodies stay valid. The digest's score object is additionalProperties:false and had never declared deltaReason, scoreVersion or composition, all of which it has been sending. A generated strict decoder would have rejected the real payload, so they are declared here too rather than left standing next to a field that documents itself correctly.
This commit is contained in:
1 parent
5d7d00949c
commit
c29055be1c
6 files changed
+84
-2
No files matched your search
+29
-1
@@ -28112,6 +28112,13 @@ components:
|
||||
- WELLBEING
|
||||
- FITNESS
|
||||
- LIPIDS
|
||||
configured:
|
||||
description: "True when the account's own recipe narrows the score's composition below what its defaults would resolve
|
||||
to today. Server-resolved, so a client never interprets a configuration blob: an account that kept
|
||||
every pillar reads false, and so does one whose disabled modules alone narrow the set. The
|
||||
configuration itself is never on this wire. Optional so older cached snapshots without the field
|
||||
stay valid."
|
||||
type: boolean
|
||||
deltaReason:
|
||||
anyOf:
|
||||
- type: string
|
||||
@@ -35262,13 +35269,34 @@ components:
|
||||
anyOf:
|
||||
- type: number
|
||||
- type: "null"
|
||||
configured:
|
||||
description: True when the account's own recipe narrows the score's composition below what its defaults would resolve to
|
||||
today. Resolved on the server and carried straight from the dashboard snapshot; the configuration
|
||||
itself never rides this wire. Optional so older cached digests without the field stay valid.
|
||||
type: boolean
|
||||
deltaReason:
|
||||
description: Why a delta was suppressed; null when it was not.
|
||||
anyOf:
|
||||
- type: string
|
||||
- type: "null"
|
||||
scoreVersion:
|
||||
description: Algorithm version that produced the value.
|
||||
type: integer
|
||||
exclusiveMinimum: 0
|
||||
maximum: 9007199254740991
|
||||
composition:
|
||||
description: Registry-ordered pillar ids the value was composed of.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
required:
|
||||
- value
|
||||
- band
|
||||
- delta
|
||||
additionalProperties: false
|
||||
- type: "null"
|
||||
description: Health score + band + week-over-week delta; null when none.
|
||||
description: Health score + band + week-over-week delta, plus whether the account authored the composition; null when
|
||||
none.
|
||||
topSignal:
|
||||
anyOf:
|
||||
- type: object
|
||||
|
||||
@@ -105,6 +105,12 @@ export interface DailyDigestScore {
|
||||
deltaReason?: ScoreDeltaReason | null;
|
||||
scoreVersion?: number;
|
||||
composition?: ScorePillarId[];
|
||||
/**
|
||||
* v1.35.0 — the resolved "this score is configured" flag, carried
|
||||
* straight from the snapshot's health-score block. Omitted by older
|
||||
* cached digests, like its siblings above.
|
||||
*/
|
||||
configured?: boolean;
|
||||
}
|
||||
|
||||
/** A broken integration, deterministically derived from `IntegrationStatus`. */
|
||||
|
||||
@@ -431,6 +431,7 @@ export async function loadDailyDigest(
|
||||
deltaReason: snapshot.healthScore.deltaReason,
|
||||
scoreVersion: snapshot.healthScore.scoreVersion,
|
||||
composition: snapshot.healthScore.composition,
|
||||
configured: snapshot.healthScore.configured,
|
||||
}
|
||||
: null;
|
||||
|
||||
|
||||
@@ -329,6 +329,17 @@ export interface DashboardSnapshotHealthScore {
|
||||
delta: number | null;
|
||||
confidence?: DerivedConfidence;
|
||||
composition?: ScorePillarId[];
|
||||
/**
|
||||
* v1.35.0 — the resolved "this score is configured" flag: true when the
|
||||
* person's own recipe narrows the composition below what the account's
|
||||
* defaults would resolve to today. Server-resolved so the hero, the
|
||||
* widget and the complication acknowledge an authored recipe without
|
||||
* interpreting a config blob; the blob itself never rides this wire,
|
||||
* and neither does any per-pillar config detail. Optional on the type
|
||||
* (additive contract) so older cached snapshots stay valid; the live
|
||||
* builder always sets it.
|
||||
*/
|
||||
configured?: boolean;
|
||||
deltaReason?: ScoreDeltaReason | null;
|
||||
scoreVersion?: number;
|
||||
bandSetter?: ScorePillarId | null;
|
||||
@@ -792,6 +803,7 @@ async function buildExtras(
|
||||
delta: scoreResult.delta,
|
||||
confidence: scoreResult.composite.confidence,
|
||||
composition: scoreResult.composite.value.composition,
|
||||
configured: scoreResult.composite.value.configured,
|
||||
deltaReason: scoreResult.deltaReason,
|
||||
scoreVersion: scoreResult.scoreVersion,
|
||||
bandSetter: scoreResult.composite.value.bandSetter,
|
||||
|
||||
@@ -69,9 +69,38 @@ const dailyDigestResponse = z
|
||||
value: z.number(),
|
||||
band: z.string(),
|
||||
delta: z.number().nullable(),
|
||||
configured: z
|
||||
.boolean()
|
||||
.optional()
|
||||
.describe(
|
||||
"True when the account's own recipe narrows the score's composition below what its defaults would resolve to today. Resolved on the server and carried straight from the dashboard snapshot; the configuration itself never rides this wire. Optional so older cached digests without the field stay valid.",
|
||||
),
|
||||
// The score's identity fields have ridden this wire since the
|
||||
// digest first carried a score, but the object is
|
||||
// `additionalProperties: false` and never declared them — a
|
||||
// generated strict decoder would have rejected the real payload.
|
||||
// Declared here rather than left standing beside a new field
|
||||
// that documents itself correctly.
|
||||
deltaReason: z
|
||||
.string()
|
||||
.nullable()
|
||||
.optional()
|
||||
.describe("Why a delta was suppressed; null when it was not."),
|
||||
scoreVersion: z
|
||||
.number()
|
||||
.int()
|
||||
.positive()
|
||||
.optional()
|
||||
.describe("Algorithm version that produced the value."),
|
||||
composition: z
|
||||
.array(z.string())
|
||||
.optional()
|
||||
.describe("Registry-ordered pillar ids the value was composed of."),
|
||||
})
|
||||
.nullable()
|
||||
.describe("Health score + band + week-over-week delta; null when none."),
|
||||
.describe(
|
||||
"Health score + band + week-over-week delta, plus whether the account authored the composition; null when none.",
|
||||
),
|
||||
topSignal: z
|
||||
.object({
|
||||
sourceMetric: z.string(),
|
||||
|
||||
@@ -1109,6 +1109,12 @@ export const dashboardSnapshotResponse = z
|
||||
]),
|
||||
)
|
||||
.optional(),
|
||||
configured: z
|
||||
.boolean()
|
||||
.optional()
|
||||
.describe(
|
||||
"True when the account's own recipe narrows the score's composition below what its defaults would resolve to today. Server-resolved, so a client never interprets a configuration blob: an account that kept every pillar reads false, and so does one whose disabled modules alone narrow the set. The configuration itself is never on this wire. Optional so older cached snapshots without the field stay valid.",
|
||||
),
|
||||
deltaReason: z
|
||||
.enum([
|
||||
"algorithm_changed",
|
||||
|
||||
Reference in new issue
Block a user