# Why Compaction Drops the ADHD Ruleset and How the Extension Re‑Injects It

> Discover why automatic compaction drops the i-have-adhd ruleset and how the ayghri extension re-injects it using rulesAreInContext and syncContext to maintain functionality.

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

---

**Automatic compaction removes the custom ruleset to save tokens, so the ayghri/i‑have‑adhd extension continuously monitors the context with `rulesAreInContext()` and re‑injects the guidelines via `syncContext()` whenever they disappear.**

The **i‑have‑adhd** extension injects a specialized ruleset into AI conversations to enforce ADHD‑friendly interaction patterns. When the runtime performs **automatic compaction** to summarize older messages and stay within token limits, it strips out non‑essential custom messages—including the injected ruleset. To prevent the model from ever operating without these constraints, the extension implements a defensive guard‑and‑re‑inject pattern in [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts).

## How Context Compaction Removes the Ruleset

When a conversation grows too long, the runtime executes **automatic compaction**, a summarization process that condenses earlier exchanges into a compressed representation. During this cleanup, the engine discards **custom messages** that are not part of the model’s core conversation history. Because the ADHD ruleset is injected as a custom message type (distinct from standard user or assistant turns), compaction treats it as ephemeral metadata and removes it. Consequently, the model loses the guidelines even though the extension remains technically enabled.

## The Guard‑and‑Re‑Inject Pattern

To guarantee the ruleset is always present when needed, the extension employs a three‑phase detection and recovery system defined in [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts).

### Detecting Missing Rules with `rulesAreInContext()`

Before deciding whether to re‑inject, the extension checks the current context state. The `rulesAreInContext()` function leverages `latestMarkerIsActive` from [`extensions/context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/context-compat.ts) to inspect the most recent marker messages. It compares the latest active custom message against the constants `RULES_MESSAGE_TYPE` and `DISABLED_MESSAGE_TYPE`.

```ts
// extensions/i-have-adhd.ts
function rulesAreInContext(ctx: ExtensionContext): boolean {
  return latestMarkerIsActive(
    contextMessages(ctx.sessionManager),
    RULES_MESSAGE_TYPE,
    DISABLED_MESSAGE_TYPE,
  );
}

```

If the latest marker is the disabled notice, or if no marker exists at all, the function returns `false`, signaling that compaction has dropped the ruleset (see lines 99‑104).

### Re‑Injecting the Ruleset via `syncContext()`

The `syncContext()` function runs on every turn to synchronize the context state. When ADHD mode is enabled and `rulesAreInContext()` returns `false`, the extension sends a new custom message containing the full ruleset loaded from [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md). If the mode is disabled but a stale ruleset persists, it transmits a disabled notice to nullify the previous instructions.

```ts
// extensions/i-have-adhd.ts
const syncContext = (ctx: ExtensionContext): void => {
  const injected = rulesAreInContext(ctx);

  if (enabled && !injected) {
    pi.sendMessage(
      { customType: RULES_MESSAGE_TYPE, content: `${RULES_HEADER}\n\n${rules}`, display: false },
      { triggerTurn: false },
    );
    return;
  }

  if (!enabled && injected) {
    pi.sendMessage(
      { customType: DISABLED_MESSAGE_TYPE, content: DISABLED_NOTICE, display: false },
      { triggerTurn: false },
    );
  }
};

```

This logic resides at lines 135‑159 and ensures the model always receives the correct behavioral constraints before processing the next user query.

### Automatic Trigger Points

The `syncContext()` routine executes automatically whenever the extension restores its state, toggles ADHD mode on or off, or finishes processing a user turn. This aggressive triggering strategy guarantees immediate recovery after any compaction event, preventing the model from ever handling a request without the ADHD guidelines in scope.

## Practical Re‑Injection Scenarios

The following examples illustrate how the extension behaves during common lifecycle events.

**Enabling ADHD Mode (First Turn)**

When a user activates the feature, the extension updates its internal state and immediately invokes the synchronization routine:

```ts
// User runs: /i-have-adhd on
setEnabled(true, ctx);  // Updates state, UI, and calls syncContext()

```

**Recovering After Compaction**

After many turns trigger automatic compaction, the next user message prompts the extension to detect the missing ruleset and restore it silently:

```ts
// Context was compacted, ruleset discarded
syncContext(ctx);  // Detects rulesAreInContext() === false
// → sendMessage re‑injects the full ruleset

```

**Disabling ADHD Mode**

When the feature is turned off, the extension removes stale guidelines to prevent conflicting instructions:

```ts
setEnabled(false, ctx);  // Updates state and calls syncContext()

```

## Summary

- **Automatic compaction** discards non‑essential custom messages, including the ADHD ruleset, to keep token counts within operational limits.
- The extension uses `rulesAreInContext()` in [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) to verify whether the ruleset or a disabled marker is the most recent custom message in the context.
- `syncContext()` re‑injects the ruleset from [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md) whenever detection fails, ensuring continuous enforcement of ADHD‑friendly guidelines.
- The guard‑and‑re‑inject pattern triggers on every state change and user turn, providing seamless, invisible recovery from compaction events.

## Frequently Asked Questions

### Why does automatic compaction specifically target custom messages?

Compaction algorithms prioritize retaining the semantic core of the conversation. Custom metadata messages—such as the ADHD ruleset—are classified as ephemeral instructions rather than essential conversational content, so the summarization engine discards them to maximize token efficiency for the actual dialogue.

### How does the extension distinguish between an active ruleset and a disabled state?

The extension compares message markers using `latestMarkerIsActive` from [`extensions/context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/context-compat.ts). It checks whether the most recent custom message is of type `RULES_MESSAGE_TYPE` (active) or `DISABLED_MESSAGE_TYPE` (inactive), allowing precise state detection even after partial context loss.

### Will the ruleset be injected multiple times if compaction occurs frequently?

Yes, but intentionally so. Each time `syncContext()` detects the ruleset is missing, it sends a fresh injection. Because the messages use `display: false`, these re‑injections remain invisible to the user while ensuring the model always receives the current guidelines.

### Does the re‑injection process trigger a new model turn?

No. The `sendMessage` calls in `syncContext()` explicitly pass `{ triggerTurn: false }`, ensuring that re‑injecting the ruleset does not cause the model to generate an unsolicited response. The context is updated silently before the user’s next query is processed.