# How i-have-ADHD Restates State on Every Turn to Minimize Cognitive Load

> Discover how the i-have-ADHD extension restates state on every turn, preventing cognitive load and ensuring ADHD-friendly rules stay active without user input.

- Repository: [Ayoub Ghriss/i-have-adhd](https://github.com/ayghri/i-have-adhd)
- Tags: internals
- Published: 2026-09-02

---

**The i-have-ADHD extension uses a persistent session entry to track mode status and automatically re-injects ADHD-friendly rules whenever they drop from context, eliminating the need for users to remember or repeat their preference.**

The `ayghri/i-have-adhd` repository implements a state-restating mechanism designed specifically for users with ADHD who may struggle to track whether assistive features are active. Rather than burdening the user with monitoring mode status, the system handles state persistence and rule reinjection automatically through Pi's session manager architecture.

## State Storage: The Persistent Flag

When a user enables ADHD-friendly mode, the extension creates a durable session entry that survives across turns and compaction operations.

In [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) at line 75, the `setEnabled` function calls:

```typescript
pi.appendEntry("i-have-adhd-state", { enabled: true });

```

This creates a custom entry of type `i-have-adhd-state` with a boolean `enabled` flag. Unlike transient context, session entries persist even when the conversation tree is compacted, ensuring the preference survives long-running sessions.

## State Retrieval on Every Turn

The extension checks the stored flag at critical session lifecycle points—specifically `session_start` and `session_tree` events—via the `restoreState` function.

From lines 81-95 in [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts), the code walks the session branch:

```typescript
const branch = ctx.sessionManager.getBranch();
for (const entry of branch) {
  if (entry.type === "i-have-adhd-state") {
    state.enabled = entry.data.enabled;
  }
}

```

This loop finds the most recent state entry and extracts the current `enabled` value, giving the extension authoritative knowledge of user preference regardless of intervening conversation turns.

## Detecting Missing Rules with Rule Presence Check

Knowing the preference is only half the solution. The extension must also determine whether the rule set remains in the active context or was evicted during compaction.

The `rulesAreInContext` function (lines 105-110) leverages `latestMarkerIsActive` from [`extensions/context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/context-compat.ts):

```typescript
function rulesAreInContext(ctx: Context): boolean {
  return latestMarkerIsActive(ctx, "i-have-adhd-rules");
}

```

This utility checks if the most recent `i-have-adhd-rules` marker is still active and hasn't been superseded by a disabled marker. The marker-based approach handles edge cases where rules might be partially present but invalidated by later context changes.

## Automatic Restatement via syncContext

The core restatement logic lives in `syncContext`, triggered on `session_compact` events after every turn. Lines 134-148 implement the conditional reinjection:

```typescript
async function syncContext(ctx: Context, state: State) {
  if (state.enabled && !rulesAreInContext(ctx)) {
    // Rules were dropped by compaction—re-inject invisibly
    await pi.sendMessage({
      customType: "i-have-adhd-rules",
      content: RULES,
      display: false,  // Hidden from user view
      triggerTurn: false  // Doesn't advance conversation turn
    });
  }
}

```

Key characteristics of this restatement:

- **Invisible execution**: `display: false` ensures the user never sees duplicate rule injections
- **Non-intrusive**: `triggerTurn: false` prevents the hidden message from advancing the conversation state
- **Idempotent**: Repeated calls with rules already present safely no-op via the `rulesAreInContext` guard

## Clean Disabling with State Transition

When the user signals deactivation through any phrase in `STOP_PHRASES` (such as "stop adhd mode"), the extension performs a coordinated shutdown at lines 221-232:

```typescript
if (state.enabled && STOP_PHRASES.has(input)) {
  await setEnabled(false, ctx);  // Flips flag, appends disabled entry
  await pi.sendMessage({
    customType: "i-have-adhd-disabled",
    content: "ADHD-friendly mode disabled.",
    display: true
  });
}

```

The disabled state entry prevents future rule reinjection, while the visible confirmation gives the user clear feedback. Subsequent `syncContext` calls see `enabled: false` and skip all rule handling.

## Complete State Lifecycle Flow

The restatement mechanism follows this deterministic sequence on every user turn:

1. **Restore**: `restoreState` reads the latest `i-have-adhd-state` entry from the session branch
2. **Validate**: `rulesAreInContext` checks if rule markers remain active
3. **Reinstate**: `syncContext` injects hidden rules if enabled but missing
4. **Process**: User input handled with guaranteed rule presence
5. **Persist**: Any state changes appended as new session entries

This design ensures **causal consistency**—the model always operates with the correct rule context without requiring user intervention.

## State vs. Context: Architectural Distinction

The extension exploits Pi's dual storage model:

| Storage Type | Persistence | Use Case in i-have-ADHD |
|-------------|-------------|------------------------|
| **Session entries** | Survive compaction | Boolean `enabled` flag |
| **Context/markers** | Evicted during compaction | Full rule content |

Separating the lightweight state (one boolean) from heavyweight content (full rule set) minimizes storage pressure while enabling reliable recovery. The state entry acts as a **checkpoint**, while markers track ephemeral context presence.

## Summary

- **Persistent boolean flag**: Stored in `i-have-adhd-state` session entries, surviving compaction and cross-turn navigation
- **Automatic rule reinjection**: `syncContext` detects missing rules via `latestMarkerIsActive` and re-injects via hidden messages
- **Invisible operation**: Restatement uses `display: false` and `triggerTurn: false` to avoid user distraction
- **Explicit disable**: `STOP_PHRASES` trigger clean shutdown with state entry and user confirmation
- **Zero user burden**: No requirement to remember mode status or repeat preferences

## Frequently Asked Questions

### What triggers the state restatement in i-have-ADHD?

The `syncContext` function runs on every `session_compact` event, which fires after each turn. It checks whether `enabled` is true and whether rules remain in context via `rulesAreInContext`. If enabled but rules are missing, it re-injects them automatically.

### Does the user see when rules are restated?

No. The restatement uses `display: false` in the `pi.sendMessage` call, making the injection completely invisible. The user experiences seamless rule adherence without visual clutter or repetition.

### How does the extension handle session compaction?

Session compaction can evict context entries including rule markers, but it preserves session entries. The `i-have-adhd-state` entry survives, allowing `restoreState` to recover the preference. `syncContext` then detects missing rules and restates them before the model processes new input.

### Where is the actual rule content defined?

The human-readable rule set lives in [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md). This file's content is loaded into the `RULES` constant and injected whenever `syncContext` determines restatement is necessary.