Skip to content

Close loop-1.0 emulation gaps: momentum gate and max active insulin limit - #41

Open
ps2 wants to merge 2 commits into
mainfrom
emulation/loop1-preset-gaps
Open

ps2 wants to merge 2 commits into
mainfrom
emulation/loop1-preset-gaps

Conversation

@ps2

@ps2 ps2 commented Sep 30, 2026

Copy link
Copy Markdown
Collaborator

Follow-up to #40. A review of the loop-1.0 preset against the Tidepool Loop 1.0 source (LoopWorkspace build-332, i.e. LoopKit bdad094 and Loop cf10ea3) found two behaviors it did not restore.

Momentum gradual-transitions gate

linearMomentumEffect called hasGradualTransitions() with its hard-coded 40 mg/dL default. So noGradualTransitionsGate only bypassed the retrospective-correction gate, even though its doc comment says it covers momentum too.

This PR:

  • adds a gradualTransitionThreshold: Double? = 40.0 parameter, where nil means no gate;
  • has both prediction paths pass nil when noGradualTransitionsGate is set.

1.0's linearMomentumEffect checked only continuity, calibration and provenance (LoopKit GlucoseMath.swift:97-99).

Max active insulin limit

1.0's temp-basal recommendation had no active-insulin limit (Loop DoseMath.swift:340-386). The port caps automatic dosing at maxBolus × maxActiveInsulinMultiplier. When IOB is above that limit, it caps the temp basal below scheduled even when a high is forecast.

This PR adds disableMaxActiveInsulinLimit, which is on in loop-1.0.

Documentation

The loop1 preset's doc comment now lists the 1.0 behaviors callers must set through inputs:

  • recommendationType = .tempBasal
  • useIntegralRetrospectiveCorrection = false
  • useMidAbsorptionISF = false
  • the insulin model

It also lists the dosing-side behaviors outside this package that callers must reproduce:

  • override application, including 1.0's override-expiry quirk
  • predictionStart at the CGM timestamp
  • rate rounding and temp-basal continuation
  • no recommendation while a bolus is in progress

Not addressed here

With IOB above the limit and a forecast high, the default path recommends a negative temp basal (−12.07 U/h in the new test's scenario before the flag is applied). The headroom cap pushes maxBasalRate below zero and nothing clamps it back to 0. That's worth a separate fix.

Testing

Defaults are unchanged: the 158 existing tests pass unmodified. Five new tests in AlgorithmEmulationTests cover:

  • the momentum gate on, off and without a jump;
  • the flag removing the temp-basal cap, matching a run with an unbounded limit;
  • the preset contents.

🤖 Generated with Claude Code

https://claude.ai/code/session_019XDFAzoY74eu61n3aTT54Z

ps2 and others added 2 commits September 30, 2026 12:50
…imit

Two Tidepool Loop 1.0 behaviors the loop-1.0 preset did not restore:

- Momentum gradual-transitions gate. linearMomentumEffect called
  hasGradualTransitions() with its hard-coded 40 mg/dL default, so
  noGradualTransitionsGate only bypassed the retrospective-correction gate
  despite documenting that it covers momentum too. Add a
  gradualTransitionThreshold parameter (default 40, nil = no gate) and pass
  nil from both prediction paths when noGradualTransitionsGate is set.
  Tidepool Loop 1.0's linearMomentumEffect guarded only continuity,
  calibration and provenance.

- Max active insulin limit. Tidepool Loop 1.0's temp basal recommendation
  had no active-insulin limit; the port caps automatic dosing at
  maxBolus x maxActiveInsulinMultiplier, which with IOB above the limit
  caps the temp basal below scheduled even when a high is forecast. Add
  disableMaxActiveInsulinLimit (on in loop-1.0) to lift the limit.

Defaults are unchanged; the existing 158 tests pass unmodified.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019XDFAzoY74eu61n3aTT54Z
…side the loop-1.0 preset

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019XDFAzoY74eu61n3aTT54Z
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