# How Ponytail Filters Instructions by Intensity Levels: A Deep Dive into the Three-Tier System

> Learn how Ponytail filters instructions by intensity levels. Explore the lite, full, and ultra tiers for efficient content extraction from markdown files.

- Repository: [DietrichGebert/ponytail](https://github.com/DietrichGebert/ponytail)
- Tags: deep-dive
- Published: 2026-09-06

---

**Ponytail filters instructions using a pure-JavaScript pipeline that extracts only content matching the requested intensity—lite, full, or ultra—from a master markdown skill file while preserving all mode-agnostic guidance.**

The DietrichGebert/ponytail repository implements an **intensity-aware instruction system** that serves developers precisely calibrated guidance based on their selected mode. This article breaks down how the filtering mechanism works, from initial mode resolution through final instruction delivery.

---

## Mode Resolution: From Request to Effective Intensity

Every instruction request begins with **mode resolution** in [`ponytail-mcp/instructions.js`](https://github.com/DietrichGebert/ponytail/blob/main/ponytail-mcp/instructions.js). The `resolveMode()` function normalizes user input, applies configured defaults, and ultimately falls back to `"full"` when no valid mode is detected.

```javascript
// Resolve a user-provided mode string to an actual intensity
import { resolveMode } from "./ponytail-mcp/instructions.js";

const intensity = resolveMode("ultra"); // → "ultra"
const intensity2 = resolveMode("");     // falls back to default (e.g. "full")

```

This resolution step ensures that downstream components always receive one of three validated values: `lite`, `full`, or `ultra`.

---

## Building Filtered Instructions: The Two-Stage Pipeline

Once resolved, the intensity flows through a **two-stage pipeline** that transforms raw skill content into mode-specific instructions.

### Stage 1: Instruction Retrieval

The `buildInstructions(requested)` function forwards the resolved mode to `getPonytailInstructions()` in [`hooks/ponytail-instructions.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-instructions.js). This function reads the master skill file at [`skills/ponytail/SKILL.md`](https://github.com/DietrichGebert/ponytail/blob/main/skills/ponytail/SKILL.md) and prepares it for filtering.

```javascript
// Retrieve the filtered instructions for a given intensity
import { buildInstructions } from "./ponytail-mcp/instructions.js";

const instructions = await buildInstructions("lite");
console.log(instructions); // Only lite-specific rows/examples remain

```

### Stage 2: Intensity-Aware Filtering

The core filtering logic resides in `filterSkillBodyForMode(body, mode)`. This function performs **three distinct operations**:

1. **Strips front-matter** — Removes YAML front-matter blocks (delimited by `---`) that contain metadata rather than instructional content
2. **Filters intensity table rows** — Keeps only table rows whose header matches the effective mode (pattern: `| **lite** | …`)
3. **Filters worked-example bullets** — Retains only example bullets labeled for the current mode (pattern: `- lite: "…"`)

All other content—general rule bullets, explanatory prose, mode-agnostic tables—passes through unchanged.

```javascript
// Core filtering routine (simplified)
function filterSkillBodyForMode(body, mode) {
  const effective = normalizeMode(mode) || DEFAULT_MODE;
  return body
    .replace(/^---[\s\S]*?---\s*/, "")               // strip front‑matter
    .split(/\r?\n/)
    .filter(line => {
      // Keep a table row only if its header matches the effective mode
      const tbl = line.match(/^\|\s*\*\*(.+?)\*\*\s*\|/);
      if (tbl && normalizeMode(tbl[1].trim())) return normalizeMode(tbl[1].trim()) === effective;

      // Keep a worked‑example bullet only if its label matches the mode
      const ex = line.match(/^-\s*([^:]+):\s*"/);
      if (ex && normalizeMode(ex[1].trim())) return normalizeMode(ex[1].trim()) === effective;

      // Otherwise the line is mode‑agnostic → keep it
      return true;
    })
    .join("\n");
}

```

---

## Fallback Handling When Skills Are Unavailable

If [`skills/ponytail/SKILL.md`](https://github.com/DietrichGebert/ponytail/blob/main/skills/ponytail/SKILL.md) cannot be read, `getFallbackInstructions()` generates a **minimal instruction set** that ensures the system remains functional. This fallback provides basic guidance without intensity-specific tailoring, allowing graceful degradation when file system access fails.

---

## Key Files in the Intensity Filtering System

| File | Role |
|------|------|
| [`ponytail-mcp/instructions.js`](https://github.com/DietrichGebert/ponytail/blob/main/ponytail-mcp/instructions.js) | Resolves the requested mode and builds the final instruction set via `resolveMode()` and `buildInstructions()` |
| [`hooks/ponytail-instructions.js`](https://github.com/DietrichGebert/ponytail/blob/main/hooks/ponytail-instructions.js) | Contains `filterSkillBodyForMode()`, `getPonytailInstructions()`, and `getFallbackInstructions()` |
| [`skills/ponytail/SKILL.md`](https://github.com/DietrichGebert/ponytail/blob/main/skills/ponytail/SKILL.md) | Master markdown source with intensity tables and worked examples |
| [`ponytail-mcp/test/instructions.test.js`](https://github.com/DietrichGebert/ponytail/blob/main/ponytail-mcp/test/instructions.test.js) | Unit tests verifying fallback behavior and resolution logic |
| [`pi-extension/test/helpers.test.js`](https://github.com/DietrichGebert/ponytail/blob/main/pi-extension/test/helpers.test.js) | Edge case tests for `filterSkillBodyForMode()` including mode-named rule bullets |

---

## How Intensity Levels Map to Developer Workflows

Understanding how Ponytail filters instructions by intensity levels helps developers choose the right mode for their context:

- **lite** — Minimal guidance, essential rules only; ideal for quick tasks or experienced users
- **full** — Balanced instruction set with standard examples; default for general development
- **ultra** — Comprehensive guidance with exhaustive examples; suited for complex or unfamiliar scenarios

The filtering system ensures that selecting `/ponytail lite` or `/ponytail ultra` delivers exactly the depth of instruction requested without manual configuration.

---

## Summary

- **Mode resolution** in [`ponytail-mcp/instructions.js`](https://github.com/DietrichGebert/ponytail/blob/main/ponytail-mcp/instructions.js) validates and normalizes intensity requests, defaulting to `"full"`
- **Two-stage pipeline** retrieves raw skill content then filters it based on the resolved intensity
- **`filterSkillBodyForMode()`** strips front-matter and selectively retains table rows and worked examples matching the target mode
- **Pass-through preservation** ensures all generic content remains available regardless of intensity selection
- **Fallback mechanism** provides minimal instructions when the primary skill file is inaccessible
- **Test coverage** in [`ponytail-mcp/test/instructions.test.js`](https://github.com/DietrichGebert/ponytail/blob/main/ponytail-mcp/test/instructions.test.js) and [`pi-extension/test/helpers.test.js`](https://github.com/DietrichGebert/ponytail/blob/main/pi-extension/test/helpers.test.js) validates both resolution and filtering behavior

---

## Frequently Asked Questions

### What happens if I request an invalid intensity level?

`resolveMode()` normalizes the input and falls back to the configured default; if no default exists, it returns `"full"`. Invalid values never propagate to the filtering stage.

### Does filtering remove any content permanently?

No. The `filterSkillBodyForMode()` function creates a filtered **view** of the skill file contents. The original [`skills/ponytail/SKILL.md`](https://github.com/DietrichGebert/ponytail/blob/main/skills/ponytail/SKILL.md) remains unchanged, and subsequent requests with different intensities generate fresh filtered outputs.

### Can intensity levels be extended beyond lite, full, and ultra?

The current normalization logic in `normalizeMode()` recognizes only these three values. Extending the system would require updating the normalization function, the skill file markup conventions, and associated test suites.

### How does Ponytail distinguish mode-specific table rows from regular tables?

Table rows are identified by the pattern `| **{mode}** |` where the mode name appears in bold within the first column. Regular table rows without this bold header pattern pass through unfiltered.