What Is the `session_compact` Process in the i-have-adhd Extension and Why It Prevents Lost Context
The session_compact event is a Pi runtime hook that triggers whenever conversation history is compressed, and the i-have-adhd extension uses it to re-inject ADHD response rules if they get removed during compaction.
The session_compact mechanism is critical for any Pi extension that injects custom messages into the model's context. In the ayghri/i-have-adhd repository, this hook ensures that the 10 ADHD-friendly response rules survive session compression cycles. Without this safeguard, the extension's core functionality would silently break mid-session as the runtime drops older messages to manage context size.
How session_compact Works in the Pi Runtime
The Pi runtime periodically compacts session history to keep memory usage bounded. During compaction, the runtime may summarize or drop older messages—including custom markers injected by extensions. The session_compact event fires after this process completes, giving extensions a chance to restore any lost state.
According to the source code in extensions/i-have-adhd.ts, the extension registers for this event at line 221:
pi.on("session_compact", async (_event, ctx) => syncContext(ctx));
This one-line handler delegates to syncContext, which implements the full re-synchronization logic.
Why Compaction Threatens Extension State
The i-have-adhd extension operates by prepending a ruleset to the model's context. The rules are defined in skills/i-have-adhd/SKILL.md and injected as a hidden message with customType: RULES_MESSAGE_TYPE. The compaction process poses two specific risks:
- Ruleset removal – Older messages, including the injected rules, may be dropped entirely
- Stale markers – A disabled notice or ruleset from a previous state may persist incorrectly
The extension cannot rely on a one-time injection because the runtime's compaction is opaque and can occur at any point during a long conversation.
The syncContext Re-Synchronization Strategy
The syncContext function in extensions/i-have-adhd.ts implements idempotent context repair. It follows a precise algorithm to ensure correct state without duplicate injections.
Step 1: Retrieve Current Context Messages
The function calls contextMessages(ctx.sessionManager) to get the actual message list after compaction. This helper is defined in extensions/context-compat.ts.
Step 2: Check Latest Marker Status
The latestMarkerIsActive function (lines 41-61 in context-compat.ts) scans messages to determine if the most recent custom marker is:
- The
RULES_MESSAGE_TYPEmarker (rules active) - The
DISABLED_NOTICE_TYPEmarker (rules explicitly disabled) - No marker (clean state)
Step 3: Inject or Correct as Needed
Based on the enabled state and marker presence, syncContext takes one of three actions:
- Enabled + missing rules: Re-inject the full ruleset
- Disabled + stale rules present: Inject
DISABLED_NOTICEto cancel prior rules - Already correct: No-op to avoid duplicates
The re-injection code at lines 121-129 shows the exact message structure:
pi.sendMessage(
{
customType: RULES_MESSAGE_TYPE,
content: `${RULES_HEADER}\n\n${rules}`,
display: false,
},
{ triggerTurn: false },
);
The display: false ensures the message remains hidden from the user interface, while triggerTurn: false prevents the re-injection from causing an unwanted model response.
Real-World Scenario: Rules Persistence Across Compaction
Consider a user who enables ADHD mode early in a conversation:
// User executes the slash command
/i-have-adhd
// Extension sets state and injects initial rules
enabled = true;
// ruleset injected as hidden message
After many turns, the Pi runtime compacts the session:
// Runtime internal: drops messages beyond context window
// → ADHD ruleset message is removed
// → session_compact event fires
// → syncContext detects missing RULES_MESSAGE_TYPE
// → ruleset re-injected automatically
The user experiences uninterrupted ADHD-friendly responses despite the compaction.
Handling Mode Cancellation
The same mechanism handles graceful shutdown. When a user says "stop adhd mode":
if (enabled && STOP_PHRASES.has(input)) {
setEnabled(false, ctx);
}
On next compaction:
// syncContext sees: enabled=false, but RULES_MESSAGE_TYPE still present
// → injects DISABLED_NOTICE which supersedes prior rules
// → future compactions see DISABLED_NOTICE as latest marker, no further action
This ensures the conversation reverts to standard behavior without ghost rules affecting model outputs.
Debugging Context State
Developers can inspect the current marker status using exported helpers from context-compat.ts:
import { contextMessages, latestMarkerIsActive } from "./context-compat";
const msgs = contextMessages(ctx.sessionManager);
const status = latestMarkerIsActive(
msgs,
"i-have-adhd-rules", // RULES_MESSAGE_TYPE
"i-have-adhd-disabled", // DISABLED_NOTICE_TYPE
);
console.log(`Marker active: ${status}`);
This returns true if either marker is present and is the most recent custom type, false otherwise.
Summary
session_compactis a Pi runtime event fired after conversation history compression- The handler
syncContextre-synchronizes injected ADHD rules if compaction removed them latestMarkerIsActiveprovides idempotency by checking the most recent marker before injection- The extension maintains continuity across unlimited compaction cycles without duplicate messages
- Graceful disabling works by injecting a cancellation notice that overrides prior rules
Frequently Asked Questions
What triggers the session_compact event in Pi?
The Pi runtime triggers session_compact automatically when the conversation context exceeds internal size thresholds. This occurs transparently during long chat sessions and may involve summarizing or dropping older messages. The event has no fixed interval—it fires as needed based on runtime memory management heuristics.
How does the extension avoid injecting duplicate rules?
The latestMarkerIsActive function in extensions/context-compat.ts scans the current message list and returns true only if the most recent custom marker matches the expected type. Before any injection, syncContext verifies whether the correct marker is already present. If present, no action is taken; if absent or stale, the appropriate correction is applied.
Can users disable ADHD mode permanently without compaction occurring?
Yes. The setEnabled(false, ctx) function immediately injects the DISABLED_NOTICE marker through syncContext, so the disabled state takes effect before any compaction. Subsequent compactions simply confirm the DISABLED_NOTICE marker remains the latest, requiring no additional changes. The mechanism works correctly regardless of when compaction occurs.
Where are the actual ADHD rules stored in the repository?
The 10 response rules live in skills/i-have-adhd/SKILL.md. The extension loads this file at initialization and stores the content in the rules variable. When injection is required, the rules are wrapped with RULES_HEADER and sent as the content field of a hidden message with customType: "i-have-adhd-rules".
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →