# From Shackles to Anchors: Pattern-Matching-Native Harness Design

## 1. A Question That Kept Me Up at Night

2025–2026. The model layer has leveled off. Claude, GPT, Gemini — each has its strengths, but none is an order of magnitude ahead of the others.

Yet people using the same model produce outputs an order of magnitude apart.

Why?

If the problem isn't the model itself, where is it?

I spent a year doing one thing: repeatedly dissecting moments where "the model is clearly smart enough, but what it generates just isn't right." Every crash trajectory pointed to the same root cause — **it's not that the model isn't smart enough. It's that the harness design fights against the model's natural way of working.**

## 2. What Traditional Harness Does: Restrict vs. Guide

The default strategy of most agent frameworks is "add rules."

Model output isn't valid JSON? Add a JSON schema validator. Model hardcoded an API key? Add "don't hardcode secrets." Model generated insecure code? Add a security checklist.

None of this is wrong. But it's a design philosophy that **works against the model** — you're constantly telling it what NOT to do, not what TO do.

Let's understand what we're dealing with: **An LLM's core capability isn't logical reasoning — it's pattern matching.**

Given a context, it doesn't "think" about what to say next. It predicts the most likely next token. Its knowledge, reasoning, and creativity all build on layer after layer of pattern recognition.

This means:

- **Give it ten "don't do X" rules, and you've given it ten natural patterns it must actively suppress.** Each rule is additional cognitive load.
- **Give it three correct examples, and you've activated patterns it already knows to the front of its attention.** It isn't "generating by rules" — it's "continuing a familiar path."

The former is a shackle. The latter is an anchor.

## 3. Zhuangzi's Butcher: Working With the Grain

2300 years ago, Zhuangzi wrote a story about killing an ox.

Lord Wenhui stood at the kitchen door, watching a butcher named Cook Ding cut up an ox. Every other butcher he'd seen used a heavy cleaver to smash through bones, replacing their knife ten times a year. But Ding's blade moved through the ox's body like music. After thousands of oxen, his blade was still as sharp as if it had just come off the whetstone.

"Remarkable," said Lord Wenhui. "How did your skill reach this height?"

Cook Ding set down his knife and replied:

> **What I care about is the Way, which goes beyond skill.**

Then he explained his three stages:

1. **At first, I saw nothing but the whole ox.** An enormous, undifferentiated mass. I didn't know where to start.

2. **After three years, I no longer saw the whole ox.** The ox disappeared. In its place: joints, sinews, connective tissue, gaps.

3. **Now, I meet it with spirit rather than look at it with eyes.** My senses stop. My *shen* (spirit) guides the knife.

When I read this, I realized: **this is exactly what's missing from LLM harness design.**

Every harness today is stuck at stage two.

You can see where the structural gaps are — you know which scenarios LLMs mess up, you know where to add rules, gates, and validators. But you're still *forcing* it. You're using an external framework to constrain a system that should work through its own perception.

Stage three isn't about using more force. It's about using less.

> **A very thin blade enters a gap between joints — there's plenty of room, the blade roams freely.**

The ox's structure wasn't created by Cook Ding. He perceived it. **The LLM's inherent patterns aren't something we create. We need to learn to perceive them.**

## 4. Where Is the "Grain"? The LLM's "Gaps"

Back to practice. What IS the LLM's inherent grain? Where are its "gaps"?

I've observed three structurally confirmed features:

### 4.1 Pattern Consistency

Show the model three examples of the same pattern, and it will naturally produce a fourth. No rules needed — it infers the distribution and continues it.

This is determined by the Transformer's attention mechanism: repeated patterns in context increase attention weights, making subsequent generation naturally follow the same pattern.

**Application:** Replace ten "don't" rules with three perfect examples.

### 4.2 Continuation Beats Reasoning

Asking the model to "continue this existing code" produces more stable results than "write code from scratch following these N rules."

The former relies on pattern matching (what transformers do best). The latter relies on combining multiple constraints logically (what transformers are relatively weaker at).

**Application:** Before each Task, generate a 10-15 line structural anchor, then let the model continue it.

### 4.3 Uneven Attention Distribution

Transformer attention has well-documented recency bias + primacy bias. Information at the beginning and end of context gets far more weight than information in the middle.

This means: cramming instructions into a 128K context window doesn't work unless you put them where the model naturally looks.

**Application:** Put current-task-critical information in the last ~2000 tokens, permanent rules at the beginning, less important stuff in the middle.

### 4.4 The Catalyst Effect

Hydrogen peroxide decomposes into water and oxygen naturally, but slowly. Add a small amount of manganese dioxide, and the reaction rate increases by orders of magnitude. The manganese dioxide doesn't participate in the reaction — it just provides a lower-energy path.

LLM generation is the same. A bare model can write code, but it has to reason from zero each time — read the request, recall APIs, plan structure, suppress error tendencies, generate. Each layer is activation energy.

But if you give the model a 10-15 line **structural anchor** (a complete code fragment that embodies the project's style) before generation, its behavior changes: from "reason and generate" to "continue the anchor." Attention consumption drops significantly, output consistency increases significantly.

The anchor doesn't get consumed (write once, reuse infinitely), doesn't change the generated content (it's just a starting context), and most importantly — it lets the model reach the correct result without passing through its error-prone tendencies.

**Key difference:**
- Traditional prompt engineering: tell the model the destination ("write a Y that conforms to X")
- Catalyst method: place the model near the destination ("continue this Z that's already 80% done")

The model is a pattern-matching system. Where you put it determines where it starts.

## 5. Practice: The 2.5-Layer Design in ReqForge

The following five changes form what we call the "2.5-layer" — not quite stage three, but already attempting to work *with* the model's grain rather than against it.

### 5.1 Difficulty Markers

Added a `## Known Difficult Spots` table to Product-Spec.md, with each module tagged 🔴/🟡/🟢.

When the model reads a 🔴 high-difficulty Task, it automatically slows down, adds self-review. When it reads a 🟢 low-difficulty Task, it passes quickly.

This isn't a constraint — it's **a more granular attention allocation scheme for the model.**

### 5.2 Anti-AI-Slop Reform

Replaced 9 "don't" rules with 3 perfect code anchors (error handling pattern, API endpoint pattern, test pattern). The old checklist was demoted to a pre-delivery safety net.

**The old way** — the model received a checklist:

```
| Check | Criterion |
|-------|-----------|
| Over-abstraction | No Factory/Strategy/interface for "future needs" |
| Hallucinated API | Does the API actually exist in deps? |
| Magic values | No hardcoded strings/numbers in business logic |
| Empty catch | Catch blocks have error handling, not just console.error |
| Copy-paste template | Not copy-pasting code and renaming variables |
| Fake tests | Not expect(true).toBe(true) |
| Comment debris | No // TODO: fix later |
| Type escapes | No as any / @ts-ignore |
| Style scattering | Consistent project styling |
```

The model has to recite nine commandments while generating, while simultaneously suppressing its natural impulses. Every act of suppression can fail.

**The new way** — the model reads three complete code snippets before generating:

```typescript
// Anchor 1: Error handling pattern
async function createUser(email: string, password: string): Promise<User> {
  const existing = await db.user.findUnique({ where: { email } });
  if (existing) {
    throw new AppError(ErrorCode.CONFLICT, "Email already registered");
  }
  const hashed = await bcrypt.hash(password, 12);
  const user = await db.user.create({ data: { email, passwordHash: hashed } });
  logger.info("User created", { userId: user.id });  // logs ID, not email
  return user;
}
```

(Plus API endpoint pattern and test pattern, structurally similar.)

After reading three perfect examples, the model's pattern-matching is anchored to the right path. It doesn't need to "remember not to do X" — it's already on the right track. The nine-item checklist remains as a pre-delivery safety net, demoted from generation guide to fallback.

### Benchmark: Rules vs. Anchors

We ran a controlled test on the todo-cli project. Same task (adding a search command), generated once with the old approach (9 rules as context) and once with the new approach (3 anchors as context). Both passed full `pnpm test` validation.

| Dimension | Old (9 rules) | New (3 anchors) |
|-----------|---------------|-----------------|
| Tests passed | 26/26 | 26/26 |
| Code size | 53 lines | 45 lines (−15%) |
| Filter logic | 2-step filter + pre-built Map | 1-step filter + runtime filter |
| Naming | `.toLowerCase()` called each iteration | `lowerKeyword` extracted once |
| Type safety | plain `string` | `TodoCategory[]` typed |

Both versions are functionally identical. The new approach produces cleaner code with the same behavior. The gap isn't "one works, one doesn't" — it's "one is done, the other is cleaner." The 15% savings per file accumulates to a visible difference at 100-file scale.

### 5.3 Laying Down the Skeleton (Phase 1's Special Role)

Phase 1 is the perfect moment to generate the catalyst.

A 0-to-1 project has no existing code to reference — but that means Phase 1's output *is* the catalyst.

Phase 1 doesn't write features — it lays down the skeleton. Domain models, core type definitions, data flow interfaces, error handling conventions — these are the project's unique "heavenly structure." Phase 1's output is the style reference for every subsequent Phase.

Before each subsequent Phase starts, there's a "sense the heavenly structure" step — glance at the skeleton files laid down in Phase 1, activate the model's memory of the project's code style, then begin generation. This is how the catalyst works: **no need for a global template library — every project's Phase 1 code is its own catalyst.**

(In brownfield projects, the catalyst comes from existing domain models and core types. Before each new Task, glance at these files to put the model in "this is what this project's code looks like" state.)

### 5.4 Sheathing the Knife

After each Phase completes, a five-step closing ritual is mandatory:

1. Review completed deliverables
2. Explicitly celebrate completion (stand with the knife, look around, savor)
3. Append newly discovered difficulties to Product-Spec.md's Known Difficult Spots
4. Record decisions in the decision log
5. Clear context — the next Phase starts from a clean attention window

**Core idea: A knife must be sheathed after use, or the next one won't be sharp.**

### 5.5 Auto-Rollback

When change verification fails, automatically restore files from a pre-change snapshot. No manual `git checkout` needed.

This isn't a constraint — it's **a trust mechanism that lets the model take risks safely.**

### The Big Picture: A Complete Cycle

These five changes aren't isolated. They form a **complete breathing cycle**:

```
Spec (with difficulty markers 🔴🟡🟢)
  │
  ├── dev-planner reads difficulties → annotates each Phase
  │
  ▼
Phase 1: Lay down skeleton (domain models, types, interfaces, conventions)
  │
  ▼
Phase 2+: Sense the heavenly structure (read existing code style → activate pattern matching)
  │
  ▼
Coding (anchor continuation → slow down for 🔴 → light touch → self-review)
  │
  ▼
Sheathe the knife (review → append difficulties → log decisions → clear context)
  │
  └──→ Spec's Known Difficult Spots updated
          Next Phase starts on an updated map → back to the top ▼
```

Each Phase is a Cook Ding cycle: **perceive → execute precisely → enjoy completion → sheathe the knife → clear the field → next round.**

The key isn't any single change — it's the cycle itself. Each iteration makes the Spec map more precise (appending hidden difficulties), the next Phase's attention cleaner (clearing context), and the project skeleton richer (Phase 1's skeleton compounds over time).

### 5.6 Extension: Model-to-Model Anchors

The discussion above focuses on "person → model" anchors: a developer writes a spec with difficulty markers, a framework provides anti-ai-slop code examples, a skill adds an action summary to its first-principles file. In all these cases, a human provides the anchor, the model reads it, and pattern-matching produces better output.

But a natural extension appears when **multiple models work sequentially on the same task.** The most common example in Forge:

```
design-maker (generates visual mockups) → dev-builder (writes code from them)
```

Without a structured intermediate representation, dev-builder must guess the page's component hierarchy, states, and responsive rules from pixels alone — the classic image-to-code failure pattern. The model is smart enough, but it's guessing structure instead of reading it.

The fix isn't another document for humans to maintain. It's an auto-generated, ephemeral intermediate representation — **UI-Spec.md** — that design-maker produces during verification and dev-builder reads at startup.

```
design-maker ──→ UI-Spec.md (auto-generated YAML, not committed) ──→ dev-builder
    │                    │                                              │
    │  page mockups      │  component hierarchy, states, responsive     │  reads structure
    │  visual tokens     │  reusable components, acceptance criteria    │  writes code
```

This isn't a new layer. It's the same 2.5-layer principle applied to model-to-model handoff:

| Aspect | Person→Model (Section 5.1–5.5) | Model→Model (Section 5.6) |
|--------|-------------------------------|---------------------------|
| Anchor source | Human writes | Upstream model generates |
| Anchor form | Code examples / summaries | Structured YAML (UI-Spec) |
| Lifespan | Permanent (checked in) | Ephemeral (regenerated each cycle) |
| Maintenance | Near-zero | Zero (auto-generated, auto-consumed) |
| Purpose | Activate correct mode | Pass structure, skip guessing |

The insight isn't "YAML is good." It's that **model-to-model handoff suffers from the same structural guessing problem as model-to-person instructions.** An intermediate representation — even a simple YAML template — eliminates the guessing and lets the downstream model work from known structure.

Like all 2.5-layer artifacts, UI-Spec.md isn't a rule ("you must follow this component hierarchy") and isn't final output (it's not the shipped code). It's a structural reference that puts the downstream model in the right starting position. The person-to-model 2.5 layer activates the right mode; the model-to-model 2.5 layer passes the right structure.

## 6. Anchor Selection Guide & Troubleshooting

### 6.1 How to Pick Good Anchors

Not any three code snippets qualify as anchors. Good anchors have three properties:

**Property 1: Coverage > 80%**

Three anchors should cover most of your coding scenarios. In dev-builder:

| Anchor | Covers | % of daily work |
|--------|--------|-----------------|
| Error handling | DB, API, file operations | ~40% |
| API endpoint | Request/response tasks | ~30% |
| Tests | New/modified feature validation | ~20% |
| Remaining (config, deploy, scripts) | Safety net handles | ~10% |

Three anchors cover ~90% of dev-builder's daily work. When selecting anchors, first list the three most common coding scenarios in your project, then write a perfect example for each.

**Property 2: Anchors must be 100% correct**

A single bug in an anchor will propagate to all subsequent generations. Anchors are seed code, not "close enough." Run `pnpm test` on your anchors before using them.

**Property 3: 10-15 lines, not 50**

Anchors are the starting line, not the finish line. Too long, and the model treats them as the complete implementation, making output bloated. 10-15 lines shows the project's style without constraining too much.

### 6.2 When Anchors Fail

**Scenario 1: Different tech stack, anchor APIs don't apply.**

> Replace the anchor. Anchors have no cache — replacement cost is near zero. Save old anchors to `references/archive/` for reference.

**Scenario 2: Model ignores the anchor style entirely.**

> The anchor isn't specific enough. Make it from "a generic error handling pattern" to "this project's specific error handling pattern" — add project-specific type references or framework calls. The more specific, the harder it is to deviate.

**Scenario 3: Anchor conflicts with other prompt instructions.**

> Find the conflict source. Most commonly, the system prompt has "keep it simple" while the anchor shows a more structured approach. The model oscillates between two signals and takes the path of least resistance. Solution: remove the conflicting instruction, or make the anchor match its style.

**Scenario 4: Model is strong enough to complete the file without the anchor.**

> This isn't a problem. The anchor exists as guidance when the model is uncertain, not as a mandatory path. If the model can write correct output independently, it means its pattern matching for this domain is already strong enough — nothing lost.

## 7. Results & Limitations

Honestly: these changes have theoretical support, have usage experience, but lack rigorous controlled experiments.

What we know works:
- Developer feedback: "feels noticeably better" — generated code is more consistent with project style, requires fewer revisions
- Known Difficult Spots make the model slow down before complex Tasks, reducing sudden failures
- Context clearing in "sheathe the knife" significantly reduces cross-Phase attention noise

Known limitations:
- These methods depend on the model's pattern-matching capability — if training data is sparse in a domain, anchor effectiveness drops
- Anchors require manual maintenance (infrequently, though) — not as "write once and forget" as rules files
- Currently validated only in Node.js / TypeScript projects — other languages and frameworks need separate testing

## 8. This Shouldn't Be an Academic Paper

As I write this, I realize this article makes no academic contribution.

No new mathematical structure. No benchmark tables. No controlled experiments. No statistical significance tests.

It has only one thing: **a philosophy of harness design that runs against the mainstream, and a working open-source implementation that supports it.**

Throwing this on arXiv would be ignored. But putting it in front of independent developers and AI engineers — they'll feel it.

Because everyone who actually uses AI for coding knows: **the shift from "ten don'ts" to "three examples" isn't a technique-level optimization. It's a fundamental change in how you see the model.**

The model isn't a machine that needs constant rule enforcement. It's a pattern-matching system. You just need to give it the right track.

The rest, it will find on its own.

---

---

### External References

- **[How Anthropic enables self-service data analytics with Claude]** (2026) — Anthropic's internal analytics agent: Skills lifted accuracy from 21% to 95%; historical SQL queries improved it by <1%. Direct validation that "anchors beat examples." https://claude.com/blog/how-anthropic-enables-self-service-data-analytics-with-claude
- **[OpenAI Harness Engineering]** (2026) — 3-engineer, 5-month, 1M+ line zero-human-code experiment. Introduced AGENTS.md as directory, Ghost Libraries, Agent-Legible Architecture. https://openai.com/index/harness-engineering/

*ReqForge: https://github.com/zxpmail/ReqForge*
*Feedback & discussion: Issues / Discussions*
