# What Is the context-compat.ts Module and Why Is It Essential for i-have-adhd?

> Discover the context-compat.ts module and its crucial role in the i-have-adhd extension. Learn how it ensures consistent API access for inspecting conversation context and activating ADHD rulesets.

- Repository: [Ayoub Ghriss/i-have-adhd](https://github.com/ayghri/i-have-adhd)
- Tags: deep-dive
- Published: 2026-08-19

---

**The [`context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/context-compat.ts) module normalizes session-manager APIs across Pi and OMP runtimes so the i-have-adhd extension can safely inspect conversation context and determine whether its ADHD ruleset is currently active.**

The [`context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/context-compat.ts) module lives at [`extensions/context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/context-compat.ts) inside the `ayghri/i-have-adhd` repository. It acts as a runtime compatibility bridge that shields the extension from platform-specific differences, enabling a single codebase to operate reliably in both the Pi and OMP environments.

## The Pi and OMP Session-Manager API Problem

The i-have-adhd extension targets two distinct runtimes, but each exposes a different session-manager API for retrieving conversation context.

**Pi** provides `buildContextEntries()`, which returns a flat array of custom message objects. **OMP** provides `buildSessionContext()`, which returns an object whose `messages` property contains the same kind of array.

Hard-coding either method into the extension logic would create a rigid dependency on one platform. If the API shape changes or the other runtime is used, the extension would break. The extension must inspect the context to know whether the ADHD ruleset in [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md) is already present or has been disabled.

## How the context-compat.ts Module Normalizes the API

The module solves this by exposing two pure functions that abstract away the underlying differences.

### contextMessages(sessionManager)

The `contextMessages()` function accepts a session-manager instance and returns a plain array of `ContextMessageMarker` objects regardless of which runtime method the manager implements.

It first detects whether the manager exposes `buildSessionContext()` or `buildContextEntries()`, then normalizes the result into a consistent array shape. If the manager is `null`, not an object, or throws while building the context, the function **fails open** and returns an empty array. This prevents the extension from crashing during session startup.

### latestMarkerIsActive(messages, activeType, disabledType)

The `latestMarkerIsActive()` function evaluates the normalized array to determine the effective state of a custom marker. It walks through the messages and returns `true` only if the most recent marker of `activeType` has not been overridden by a later marker of `disabledType`.

This logic is critical for toggle-style behavior, where a user might activate the ADHD rules and later disable them within the same session.

## Integration with the Main Extension Logic

In [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts), the `rulesAreInContext()` helper relies entirely on the compatibility layer to decide whether the ADHD rules are currently "live" in the model's context.

```typescript
import { contextMessages, latestMarkerIsActive } from "./context-compat";

function rulesAreInContext(ctx: ExtensionContext): boolean {
  return latestMarkerIsActive(
    contextMessages(ctx.sessionManager),   // ← works for Pi & OMP
    "i-have-adhd-rules",                  // active marker type
    "i-have-adhd-disabled",               // disabled marker type
  );
}

```

By delegating to `contextMessages()`, the extension avoids platform-specific conditionals. By delegating to `latestMarkerIsActive()`, it accurately tracks the ruleset state without manually scanning arrays in multiple places.

## Verifying the Compatibility Layer

The repository includes [`scripts/check_context_compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/scripts/check_context_compat.ts), which contains unit-style sanity checks that exercise both runtime paths. These tests verify that `contextMessages()` correctly handles an OMP-style manager with `buildSessionContext()` and a Pi-style manager with `buildContextEntries()`.

```typescript
import {
  contextMessages,
  latestMarkerIsActive,
} from "../extensions/context-compat";

const ACTIVE = "i-have-adhd-rules";
const DISABLED = "i-have-adhd-disabled";

const ompMgr = {
  buildSessionContext: () => ({ messages: [{ role: "custom", customType: ACTIVE }] })
};
console.assert(contextMessages(ompMgr).length === 1);

const piMgr = {
  buildContextEntries: () => [{ type: "custom_message", customType: ACTIVE }]
};
console.assert(contextMessages(piMgr).length === 1);

const markers = [
  { role: "custom", customType: ACTIVE },
  { role: "custom", customType: DISABLED },
  { role: "custom", customType: ACTIVE },
];
console.assert(latestMarkerIsActive(markers, ACTIVE, DISABLED));

```

This stand-alone script demonstrates that the abstraction works for both platforms and that marker evaluation respects chronological order.

## Summary

- [`extensions/context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/context-compat.ts) bridges the Pi and OMP session-manager APIs by normalizing `buildContextEntries()` and `buildSessionContext()` into a single array of markers.
- `contextMessages()` provides **fail-open** error handling, returning an empty array when the manager is missing or throws.
- `latestMarkerIsActive()` determines whether the most recent state marker is active or has been superseded by a disable marker.
- The module keeps [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) platform-agnostic and protects against future changes in session-manager implementations.

## Frequently Asked Questions

### What runtimes does the context-compat.ts module support?

The module supports the **Pi** runtime, which uses `buildContextEntries()`, and the **OMP** runtime, which uses `buildSessionContext()`. Both return conversation context data, but the wrapper methods and object shapes differ.

### What happens if the session manager is null or throws an error?

The `contextMessages()` function returns an empty array. This **fail-open** design prevents the i-have-adhd extension from crashing during session startup when the manager is unavailable or the underlying API throws.

### How does i-have-adhd.ts know whether to inject its ruleset?

[`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) calls `rulesAreInContext()`, which uses `contextMessages()` to fetch normalized markers and `latestMarkerIsActive()` to check whether the latest `"i-have-adhd-rules"` marker is still active. If the rules are not present or have been disabled, the extension re-injects them.

### Where can I find the actual ADHD ruleset that gets injected?

The ruleset content lives in [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md). The compatibility layer itself does not contain the rules; it only ensures the extension can safely detect whether that content is already present in the model's conversation context.