Align M3.5 design doc with the nudgeEpoch guard

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-05-31 18:52:01 -04:00
parent 622a1cd401
commit 19654c2b57
@@ -145,14 +145,14 @@ both.
nudge eligibility: nudge eligibility:
- `c.nudge != nil`, runtime is Active, `len(c.recentTitles) >= 2`, and - `c.nudge != nil`, runtime is Active, `len(c.recentTitles) >= 2`, and
`lastNudgedAt` is zero or `now.Sub(lastNudgedAt) >= nudgeDebounce`. `lastNudgedAt` is zero or `now.Sub(lastNudgedAt) >= nudgeDebounce`.
- If eligible: stamp `lastNudgedAt = now`, capture `gen := c.driftGen`, the - If eligible: stamp `lastNudgedAt = now`, capture `epoch := c.nudgeEpoch`,
commitment string (same `NextAction — SuccessCondition` form as the drift the commitment string (same `NextAction — SuccessCondition` form as the
judge), and a **copy** of `recentTitles`; return the nudge closure. drift judge), and a **copy** of `recentTitles`; return the nudge closure.
- If not eligible: return `nil` (unchanged behavior). - If not eligible: return `nil` (unchanged behavior).
3. **Nudge closure** (runs in the goroutine): 3. **Nudge closure** (runs in the goroutine):
- Calls `nudge.Nudge(ctx, commitment, titles)` under a `nudgeTimeout` - Calls `nudge.Nudge(ctx, commitment, titles)` under a `nudgeTimeout`
context. context.
- Re-acquires the lock; if `gen != c.driftGen || c.runtimeState != - Re-acquires the lock; if `epoch != c.nudgeEpoch || c.runtimeState !=
RuntimeActive` → stale, return. RuntimeActive` → stale, return.
- On error → log, leave `nudgeMessage` unchanged (no fabrication), unlock, - On error → log, leave `nudgeMessage` unchanged (no fabrication), unlock,
return. (`lastNudgedAt` stays set, so a failed call does not immediately return. (`lastNudgedAt` stays set, so a failed call does not immediately
@@ -209,8 +209,8 @@ avoid stale interrupts after a restart).
nudge never fabricates a concern, mirroring the drift judge's "never fabricate nudge never fabricates a concern, mirroring the drift judge's "never fabricate
drift" rule. drift" rule.
- A reasonless concern from the model degrades to silence (see parsing). - A reasonless concern from the model degrades to silence (see parsing).
- Stale results (session ended or restarted mid-call) are discarded by the - Stale results (the on-task stretch ended via a drift episode, or the session
`driftGen` guard. ended/restarted mid-call) are discarded by the `nudgeEpoch` guard.
## Testing ## Testing