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:
- `c.nudge != nil`, runtime is Active, `len(c.recentTitles) >= 2`, and
`lastNudgedAt` is zero or `now.Sub(lastNudgedAt) >= nudgeDebounce`.
- If eligible: stamp `lastNudgedAt = now`, capture `gen := c.driftGen`, the
commitment string (same `NextAction — SuccessCondition` form as the drift
judge), and a **copy** of `recentTitles`; return the nudge closure.
- If eligible: stamp `lastNudgedAt = now`, capture `epoch := c.nudgeEpoch`,
the commitment string (same `NextAction — SuccessCondition` form as the
drift judge), and a **copy** of `recentTitles`; return the nudge closure.
- If not eligible: return `nil` (unchanged behavior).
3. **Nudge closure** (runs in the goroutine):
- Calls `nudge.Nudge(ctx, commitment, titles)` under a `nudgeTimeout`
context.
- Re-acquires the lock; if `gen != c.driftGen || c.runtimeState !=
- Re-acquires the lock; if `epoch != c.nudgeEpoch || c.runtimeState !=
RuntimeActive` → stale, return.
- On error → log, leave `nudgeMessage` unchanged (no fabrication), unlock,
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
drift" rule.
- A reasonless concern from the model degrades to silence (see parsing).
- Stale results (session ended or restarted mid-call) are discarded by the
`driftGen` guard.
- Stale results (the on-task stretch ended via a drift episode, or the session
ended/restarted mid-call) are discarded by the `nudgeEpoch` guard.
## Testing