# How context-compat.ts Enables OMP Compatibility: A Deep Dive into the Open-Code Marketplace Plugin Adapter

> Discover how context-compat.ts bridges OMP versions by normalizing session-context APIs. Ensure your i-have-adhd plugin functions seamlessly with stable context for broad compatibility.

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

---

**TLDR: [`context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/context-compat.ts) is a compatibility bridge that normalizes the Open-Code Marketplace Plugin (OMP) runtime's session-context APIs into a single, stable `ContextMessageMarker` shape, gracefully degrades on failure, and evaluates marker state — ensuring the i-have-adhd plugin works across all OMP versions.**

The `ayghri/i-have-adhd` repository contains a plugin that injects ADHD-focused productivity rules and UI tweaks into an AI coding assistant. Its core challenge is that the Open-Code Marketplace Plugin (OMP) runtime exposes session context through two different, version-dependent APIs. The file [`extensions/context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/context-compat.ts) solves this by abstracting those differences. In this article, I explain exactly how this adapter works, the functions it exports, and where it plugs into the larger architecture — based directly on the source code in the repository.

## What context-compat.ts Does: The OMP Compatibility Bridge

The OMP runtime provides a `sessionManager` object to plugins at initialization time. That object may implement one of two methods depending on the OMP release:

- **`buildSessionContext()`** — the newer API signature.
- **`buildContextEntries()`** — the older, legacy API.

If the plugin code tried to call one method directly, it would break on the other version. [`context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/context-compat.ts) eliminates this fragility by defining the `CompatibleSessionManager` type, which captures **both** signatures:

```ts
type CompatibleSessionManager = {
  buildSessionContext?: () => ContextMessageMarker[];
  buildContextEntries?: () => ContextMessageMarker[];
  // ... additional optional fields
};

```

Because both methods return the same underlying `ContextMessageMarker` shape, the type acts as a structural union. The rest of the plugin can then treat every supported OMP version identically, regardless of which API the runtime actually provides.

### How contextMessages() Normalizes OMP Context Data

The exported `contextMessages()` function performs the actual dispatch. It checks which method exists on the session manager, invokes it, and returns a normalized `ContextMessageMarker[]` array:

```ts
export function contextMessages(sessionManager: unknown): ContextMessageMarker[] {
  if (!sessionManager) return [];

  const sm = sessionManager as CompatibleSessionManager;

  try {
    if (typeof sm.buildSessionContext === "function") {
      return sm.buildSessionContext() ?? [];
    }
    if (typeof sm.buildContextEntries === "function") {
      return sm.buildContextEntries() ?? [];
    }
  } catch {
    // OMP API changed or transient failure — fail open, not closed.
  }

  return [];
}

```

Notice three defensive details in this implementation:

1. **Null safety** — If `sessionManager` is `undefined`, the function short-circuits to an empty array.
2. **Double validation** — Each method is checked with `typeof` before invocation, so a missing method never throws a `TypeError`.
3. **Exception swallowing** — Any runtime error inside the method call is caught, and the function returns `[]` instead of crashing the plugin startup.

This fails-open behavior is essential for OMP compatibility: the plugin must start safely even when the runtime's API is temporarily broken or mid-migration.

## Graceful Degradation and the OMP Fallback Policy

According to the `i-have-adhd` source, OMP enforces a policy where its custom rules are applied **only as a fallback** when an alternative provider (called "Pi") is unavailable. [`context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/context-compat.ts) supports this policy through its fail-open default.

When the plugin initializes, it never knows ahead of time whether the OMP session manager will be present, functional, or using the expected API. If `contextMessages()` returned `null` or threw, the plugin would crash — and no rules would load, breaking the fallback entirely. By silently returning an empty array, the adapter enables the plugin to:

- Start up cleanly every time.
- Wait for the session manager to become available later.
- Re-inject OMP rules when a later call succeeds.

This separation of "retrieve what you can, fail without side effects" is critical for long-running editor sessions where OMP updates may hot-reload the API mid-session.

## Marker State Evaluation with latestMarkerIsActive()

A **marker** in the OMP context is a typed message object: `{ type: string, ... }`. OMP uses custom types such as `"omp_active"` and `"omp_disabled"` to signal whether the OMP-specific ruleset should be applied.

The helper `latestMarkerIsActive()` walks through the normalized markers in order and determines if the most recent marker of a given active type `activeType` is still in effect — accounting for a later disabling marker:

```ts
export function latestMarkerIsActive(
  markers: ContextMessageMarker[],
  activeType: string,
  disabledType: string
): boolean {
  let active = false;
  for (const m of markers) {
    if (m.type === activeType) active = true;
    else if (m.type === disabledType) active = false;
  }
  return active;
}

```

The function is **order-aware**: it scans the chronological list, so a later `"omp_disabled"` overrides an earlier `"omp_active"`. This gives the plugin a single, deterministic Boolean that drives feature toggles without the caller needing to understand OMP's internal message ordering.

## Integration Points: Where the Adapter Plugs Into the Plugin

### The OMP Extension Entry Point

The main integration lives in [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts), which is invoked by OMP at plugin load. It calls `contextMessages(sessionManager)` and then `latestMarkerIsActive()` to decide whether to apply OMP-specific rules:

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

// The OMP runtime passes its session manager to the plugin entry point.
function onPluginInit(sessionManager: unknown) {
  // Retrieve a normalized list of context markers.
  const markers = contextMessages(sessionManager);

  // Determine whether the "omp_active" marker is still in effect.
  const isOmpActive = latestMarkerIsActive(
    markers,
    "omp_active",     // active marker type
    "omp_disabled"    // disabling marker type
  );

  if (isOmpActive) {
    // Enable OMP-specific behavior (e.g., custom rules, UI tweaks)
    enableOmpFeatures();
  } else {
    // Fallback to default behavior or Pi compatibility path
    disableOmpFeatures();
  }
}

```

This is the only place in the plugin that touches OMP internals. Everything downstream operates on the simple Boolean `isOmpActive`.

### The Verification Script

The repository also contains [`scripts/check_context_compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/scripts/check_context_compat.ts), a test script that validates OMP compatibility. It checks two essential properties:

- **Message presence** — that `contextMessages()` returns the expected markers for a given mock session manager.
- **Marker ordering** — that chronological order is preserved, ensuring `latestMarkerIsActive()` behaves deterministically.

This test is crucial because OMP regularly evolves its API. If a future OMP release changes the session manager shape, the test fails immediately, alerting the maintainers that the adapter needs an update — rather than silently breaking plugin behavior in production.

## Key Files and Their Roles

| File | Purpose |
|------|---------|
| [`extensions/context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/context-compat.ts) | Normalizes OMP session-context messages and evaluates marker state. |
| [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) | OMP entry point that uses the helpers above to apply runtime-specific rules. |
| [`scripts/check_context_compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/scripts/check_context_compat.ts) | Test script that verifies OMP compatibility (message presence, ordering). |

## Why This Design Matters for Plugin Maintainability

By encapsulating the differences between OMP's session-manager APIs, [`context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/context-compat.ts) delivers three concrete benefits to the `i‑have‑adhd` plugin:

- **Version independence** — The rest of the codebase is completely decoupled from OMP's API changes.
- **Fail-safe startup** — The plugin can never crash due to a missing or broken session manager.
- **Deterministic behavior** — Marker logic is centralized, auditable, and unit-tested.

Any new OMP feature that introduces additional context types only requires extending the adapter functions — never the consumer code in [`i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/i-have-adhd.ts).

## Summary

- [`context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/context-compat.ts) defines the `CompatibleSessionManager` type that unifies OMP's two APIs: `buildSessionContext()` and `buildContextEntries()`.
- The `contextMessages()` function normalizes output to `ContextMessageMarker[]` and returns an empty array on any error, satisfying OMP's fallback policy.
- `latestMarkerIsActive()` evaluates marker sequencing deterministically, returning a Boolean used by OMP feature toggles.
- The adapter is integrated through [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) and guarded by the [`scripts/check_context_compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/scripts/check_context_compat.ts) test script.
- This design ensures the plugin remains fully compatible across OMP releases with zero change to its core logic.

## Frequently Asked Questions

### What problem does context-compat.ts solve?

[`context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/context-compat.ts) solves the problem of OMP runtime API divergence. The OMP may provide a session manager implementing either `buildSessionContext()` or `buildContextEntries()`, and this file normalizes both into a single `ContextMessageMarker[]` array that the rest of the plugin consumes without knowing which API version is in use.

### How does context-compat.ts handle missing or broken session managers?

It fails open. If the session manager is missing, the `contextMessages()` function returns an empty array. If the manager exists but throws an error during mark the call, the error is swallowed and the function still returns `[]`. This prevents plugin startup crashes and allows OMP's fallback-only policy to work safely.

### What lesson does latestMarkerActive() teach about OMP marker evaluation?

It scans markers chronologically, so the last marker always wins: if a `"omp_disabled"` marker appears after an `"omp_active"` marker, the function returns `false`. Order preservation is checked by the test script in [`check_context_compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/check_context_compat.ts).

### Where in the repository is the OMP compatibility adapter used?

The adapter is used in [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts), the OMP entry point. That file calls `contextMessages(sessionManager)` at full initialization and `latestMarkerIsActive()` to decide whether to enable OMP-specific features. The adapter and its integration are governed by the test in [`scripts/check_context_compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/scripts/check_context_compat.ts).