# How the `context‑compat.ts` Layer Ensures Cross‑Platform Compatibility in i‑have‑ADHD

> Discover how i‑have‑ADHD uses the context‑compat.ts layer to unify session managers, ensuring seamless cross-platform compatibility with Claude, Codex, Pi, and more.

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

---

**The `context‑compat.ts` module acts as an abstraction shim that normalizes platform‑specific session managers into a unified message format, enabling the i‑have‑ADHD runtime to work identically across Claude, Codex, Pi, OMP, and other adapters.**

The i‑have‑ADHD open‑source project provides ADHD‑friendly response rules for AI assistants, but different platforms expose incompatible session APIs. The `extensions/context‑compat.ts` file solves this by isolating platform quirks behind a stable compatibility layer. This article breaks down exactly how `context‑compat.ts` achieves cross‑platform compatibility, with reference to the actual implementation in the [ayghri/i‑have‑adhd](https://github.com/ayghri/i-have-adhd) repository.

## Unified Message Shape via `ContextMessageMarker`

The foundation of compatibility is a **minimal, platform‑agnostic type** that captures only essential fields.

In [`extensions/context‑compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/context-compat.ts), lines 1–5 define `ContextMessageMarker` containing `type`, `role`, and `customType`. Platform‑specific session managers may expose richer message objects, but the shim reduces every message to this common structure. This prevents type mismatches when the same code runs under different adapters.

## Graceful Session‑Manager Detection

The exported `contextMessages` function accepts an `unknown` session manager and validates it before use.

Lines 18–20 verify that the input is an object. This protects the runtime from crashes when a platform omits the session manager or changes its API signature. Without this guard, an undefined or malformed manager would throw at runtime.

## Dual‑API Support for Platform Variations

Different platforms expose context building through incompatible method names. The compatibility layer handles both conventions:

- **`buildSessionContext`** — returns `{ messages: … }` (object wrapper)
- **`buildContextEntries`** — returns an array directly

Lines 24–33 check for both methods, invoking whichever is present. The result is normalized to an array of `ContextMessageMarker` regardless of which API was used. This dual‑path logic means the same code works whether the underlying platform follows Claude's conventions or Codex's.

## Error‑Resilient Fallback Behavior

All platform detection and method invocation is wrapped in `try … catch` (lines 34–36). Any thrown error results in an empty array rather than a crash. This **defensive design** allows the rule engine to continue operating; markers can be re‑injected later if the session manager recovers or the platform environment stabilizes.

## Active‑Marker Detection with `latestMarkerIsActive`

The `latestMarkerIsActive` helper (lines 41–60) scans normalized messages to determine if a custom marker is currently active. Because it operates exclusively on the standardized `ContextMessageMarker` fields, this logic stays identical across all platforms.

The function accepts an active `customType` and a disabled `customType`, returning true only if the most recent relevant marker indicates activation. This powers features like the "ADHD‑mode" toggle without platform‑specific branches.

## Practical Usage Examples

Import and use the compatibility layer in any extension:

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

// Assume `sessionMgr` is supplied by the current platform runtime.
const markers = contextMessages(sessionMgr);

// Determine if the "adhd_mode" marker is active, ignoring any "adhd_off" marker.
const adhdActive = latestMarkerIsActive(
  markers,
  "adhd_mode",   // active customType
  "adhd_off"     // disabled customType
);

if (adhdActive) {
  // Enable ADHD-friendly response rules
}

```

For generic marker detection, wrap the compatibility layer:

```typescript
// Direct use of the compatibility layer in a generic utility
export function hasCustomMarker(
  sessionMgr: unknown,
  type: string
): boolean {
  const msgs = contextMessages(sessionMgr);
  return msgs.some(m => m.customType === type);
}

```

The [`context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/context-compat.ts) layer ensures these patterns execute identically whether the host is Claude, Codex, Pi, OMP, or any future adapter.

## Key Files in the Compatibility System

| File | Purpose |
|------|---------|
| [[`extensions/context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/context-compat.ts)](https://github.com/ayghri/i-have-adhd/blob/main/extensions/context-compat.ts) | Core compatibility shim that normalises session‑manager messages and provides marker‑checking helpers. |
| [[`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts)](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) | Platform‑specific entry point that consumes normalized messages from [`context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/context-compat.ts). |
| [[`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md)](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md) | Defines the ADHD‑friendly response rules that rely on markers supplied by [`context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/context-compat.ts). |
| [[`hooks/hooks.json`](https://github.com/ayghri/i-have-adhd/blob/main/hooks/hooks.json)](https://github.com/ayghri/i-have-adhd/blob/main/hooks/hooks.json) | Declares the hook that wires the compatibility layer into the runtime's execution flow. |

## Summary

- **`ContextMessageMarker`** provides a minimal, stable message format that all platforms can map to.
- **Unknown input handling** with object validation prevents runtime crashes from missing or malformed session managers.
- **Dual‑API detection** (`buildSessionContext` vs. `buildContextEntries`) accommodates platform variations without conditional compilation.
- **Try‑catch wrapping** returns empty arrays on failure, preserving system stability.
- **`latestMarkerIsActive`** operates on normalized data, ensuring consistent behavior across adapters.

## Frequently Asked Questions

### What platforms does `context‑compat.ts` support?

The layer supports Claude, Codex, Pi, OMP, and any platform exposing either `buildSessionContext` or `buildContextEntries`. The unknown‑input design allows graceful degradation on unsupported platforms.

### Why does `contextMessages` return an empty array on error?

Empty arrays prevent the rule engine from crashing when session managers fail or platforms change APIs. The system can re‑inject markers later. This is implemented in lines 34–36 of [`context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/context-compat.ts).

### How does `latestMarkerIsActive` handle conflicting markers?

It scans messages chronologically and respects the most recent marker matching either the active or disabled `customType`. Only the latest state determines the return value, preventing stale activation.

### Can I extend `context‑compat.ts` for new platforms?

Yes. Add detection logic in the dual‑API block (lines 24–33) to handle additional method signatures, ensuring the result normalizes to `ContextMessageMarker[]`. The rest of the system remains unchanged.