Skip to content

onboarding: stop publishing how band width is measured - #35

Merged
DrAlexHarrison merged 1 commit into
mainfrom
bandimpactdocs
Aug 13, 2026
Merged

onboarding: stop publishing how band width is measured#35
DrAlexHarrison merged 1 commit into
mainfrom
bandimpactdocs

Conversation

@DrAlexHarrison

Copy link
Copy Markdown
Member

What was published

guides/onboarding.mdx is live at docs.saturday.fit on a public repo. Two lines together
form a working inversion of the prescription engine.

:35 published the mechanism: "Band width is measured by running the engine against each
missing field at its plausible extremes."

:23 published a worked example carrying the output: "band_impact": { "carb_g_per_hr": 0.4, "sodium_mg_per_hr": 86.1, "fluid_ml_per_hr": 79.0 }.

The reported number is a half-width scaled by a constant and divided by the caller's own
duration, so a reader with two responses at different durations recovers
|f(axis=hi) - f(axis=lo)|, the engine's own output difference along an axis they chose,
for fourteen axes in one response. Measured against the engine in
SaturdayInc/fuel-backend#643: recovery error zero on all fourteen.

What changes

  • :35 says what the field is for, which is the collection order. The measurement method
    is gone.
  • :23 carries values on the increment the bands themselves render on.
  • :38 states the rounding, and tells a partner to take the order as given rather than
    re-sorting on the numbers, because rounding can leave two fields tied.
  • The <Note> at :49 justified the required/recommended split by claiming the
    recommended fields "move the numbers less", which is a sensitivity ranking. It now states
    the classification and that exactness needs all of them.

Two confidence-score sentences (guides/safety.mdx:120, guides/nutrition-calculation.mdx:126)
said the score is derived from band width. That is an implementation detail, and it is not
what production computes: with apiob_gate absent from fuel-app-prod,
nutrition_service.go:177 uses calculateConfidence(req), a request-shape tally. Both
sentences now state the observable property, which holds under either implementation.

Nothing a partner builds against changes. missing_fields order, display_label,
required, message and onboarding.url are all unchanged.

Why the gate did not catch this

scripts/check-engine-constants.py rule B looks for a number next to a printed unit
(86.1 mg/hr). In a JSON response body the value follows the key and the key spells its
unit in underscores ("sodium_mg_per_hr": 86.1), so rule B sees neither. That blind spot
covered every response example on the site, which is exactly where this got in.

The new impact-resolution rule is deliberately narrow: only values inside a band_impact
object, and only when they are off the band's own increment. A first attempt matched every
per-hour field and flagged 20 legitimate sample prescriptions across five guides; a sample
prescription is a number the API hands the caller, which this file already calls
documentation, so the rule was narrowed rather than allowlisted.

Verification

check-engine-constants.py, this tree                     exit 0, 19 allowed, no findings
check-engine-constants.py, prose reverted, gate kept     exit 1, 3 findings, all onboarding.mdx:23
check-engine-constants.py, the on-grid 100 seeded to 86.1 exit 1, 1 finding
check-docs-drift.py --backend fuel-backend               exit 0, 116 spec operations, 16 webhook events

The middle two lines are the point: the rule is proven to fire on the text that shipped,
and proven not to be vacuous on the text that replaces it.

Not addressed here, deliberately

The whole precision object is gated off in production. Whether to withdraw the pages or
flip apiob_gate is already Decision 1 on Alex's list and is not an editorial call.

…example

The precision page told a public reader that band width is measured by running
the engine against each missing field at its plausible extremes, and printed a
worked band_impact of 0.4 g/hr, 86.1 mg/hr, 79.0 mL/hr. Those two together are
an inversion: the reported number is a half-width scaled by a constant and
divided by the caller's own duration, so a reader recovers the engine's output
difference between that field's two extremes, at an operating point they chose,
for fourteen axes in one response. Measured against the engine: recovery error
zero on all fourteen.

The page now says what the field is for, which is the collection order, and the
example carries values on the step the bands themselves render on. Nothing a
partner builds against changes: the order is unchanged, display_label, required,
message and onboarding.url are unchanged.

Two confidence-score sentences said the score is derived from band width. That
is an implementation detail and it is not what production computes. Both now
state the observable property, which holds either way: a complete profile scores
1.0, unanswered fields lower it, missing_fields says which answers raise it.

One <Note> justified the required/recommended split by claiming the recommended
fields move the numbers less. That is a sensitivity ranking. It now states the
classification and the fact that exactness needs all of them.

check-engine-constants.py gains an impact-resolution rule. Its existing
rate-adjacent rule looks for a printed unit next to a number, so it cannot see a
JSON response body, where the value follows the key and the key spells its unit
in underscores. That blind spot covered every response example on the site,
which is where this got in. The new rule is deliberately narrow: only values
inside a band_impact object, and only when they are off the band's own step. A
sample prescription elsewhere in an example stays what this file already calls
it, a number the API hands the caller.

Verified:
  check-engine-constants.py, this tree                  exit 0, 19 allowed, no findings
  check-engine-constants.py, prose reverted, gate kept  exit 1, 3 findings, all onboarding.mdx:23
  check-engine-constants.py, on-grid 100 seeded to 86.1 exit 1, 1 finding, so the rule is not vacuous
  check-docs-drift.py --backend fuel-backend            exit 0, 116 spec operations, 16 webhook events

Ci-From: linux
Ci-Session: 87067284-6412-4360-a52c-38cf35d2bfbf
@DrAlexHarrison
DrAlexHarrison merged commit defdb97 into main Aug 13, 2026
3 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant