---
name: context-doctor
description: Identify and repair degradation in sf's context — the persistent knowledge base under `.sf/`, the system prompt, the loaded skills, and the memory store. Use when the agent feels confused, instructions seem ignored, or `.sf/` files have grown bloated, redundant, or contradictory. Complements sf's runtime doctor (`doctor-history.jsonl`).
---

# Context Doctor

Over time, sf's persistent context degrades. `.sf/CODEBASE.md` accumulates stale references; `.sf/KNOWLEDGE.md` and the `memories` table fill with redundant or contradictory entries; skills overlap. This skill diagnoses and repairs.

This is the persistent-knowledge counterpart to sf's existing **runtime doctor** (`doctor-history.jsonl`, `bootstrap/doctor`). Runtime-doctor checks live process health (DB, native engine, providers); context-doctor checks the *knowledge* sf carries between sessions.

## When to Run

- The agent repeatedly contradicts itself across sessions.
- `.sf/` files have grown beyond useful or contain obvious duplicates.
- The system prompt feels bloated (too many always-loaded files).
- A specific skill seems to confuse rather than help.
- After a major refactor, when paths and structures in `.sf/` no longer match the code.

## Operating Procedure

### Step 1 — Identify Issues

Read each persistent context file and judge:

| File | Question to ask |
|---|---|
| `.sf/PROJECT.md` | Does it still match what the project actually is? |
| `.sf/CODEBASE.md` | Are file paths and module references still valid? |
| `.sf/KNOWLEDGE.md` | Any duplicates, stale conclusions, or contradictions? |
| `.sf/preferences.yaml` | Still reflective of how the user wants to work? |
| `.sf/DECISIONS.md` | Any superseded decisions still present? |
| `.sf/REQUIREMENTS.md` | Active requirements still active? Anything done not marked done? |
| `.sf/PM-STRATEGY.md` | Still aligned with current direction? |
| `MEMORY.md` (root) | Index lines still pointing at extant files? |

For the memory store, use SF's DB-backed memory/query tools rather than direct `sqlite3` access:

```bash
/memory status
/memory search "pattern"
```

Inside an agent session, prefer the registered `memory_search` tool for targeted lookups.

Look for:

- Low-confidence rows (`< 0.5`) that haven't been hit in N days — candidates for archival.
- Multiple memories saying the same thing in different words — dedupe.
- Memories whose `content` references a path that no longer exists.

### Step 2 — Categorise the Decay

| Decay type | Symptoms | Fix |
|---|---|---|
| **Bloat** | `.sf/CODEBASE.md` is 5x its useful size; same fact stated 4 times. | Compress: keep one canonical statement, delete the rest. |
| **Stale** | A file references `extensions/old-extension/` (renamed to `extensions/sf/`). | Update; or, if the fact is now self-evident from the code, delete. |
| **Contradiction** | `.sf/DECISIONS.md` says "use bun" but `AGENTS.md` says "npm canonical". | Find the canonical source (usually `AGENTS.md` for sf), fix the other. |
| **Orphaned** | A reference points to a file that was deleted. | Delete the reference, or restore the file if it should still exist. |
| **Skill overlap** | Two skills try to do the same job. | Either merge them or scope each to its distinct sub-case. |
| **Always-loaded bloat** | Files imported into the system prompt blow the budget. | Move stable facts out of always-loaded; rely on memory recall. |

### Step 3 — Plan the Fixes

Before editing, list:

- What you're keeping.
- What you're consolidating (which two/three things become one).
- What you're deleting outright.
- What you're moving (e.g. from always-loaded to recall-on-demand).

For non-trivial cleanups, present this plan to the user before executing — sf's persistent context is sensitive and silent edits to `DECISIONS.md` or `REQUIREMENTS.md` can erase intent.

### Step 4 — Execute Repairs

Apply edits with `Edit`. For memory cleanup, use the current `/memory` commands or registered memory tools over direct `sqlite3` writes — direct DB mutation bypasses tool-level invariants.

**Scope rules:**

- **You may** refine, tighten, restructure to improve signal — but do not change the *intended semantics*.
- **You may not** alter user-identity facts (the human's name, stated goals) without explicit ask.
- **You may not** rewrite locked decisions in `.sf/DECISIONS.md` without their `superseded-by` link.
- Protected files (`SPEC.md`, `BUILD_PLAN.md`, `AGENTS.md`, `CLAUDE.md`, `docs/SPEC_FIRST_TDD.md`, ADRs) require human approval before context-doctor edits them. List proposed edits, don't apply.

### Step 5 — Verify

After repair:

- [ ] Read each touched file end-to-end. Does it now read cleanly?
- [ ] Cross-references still resolve.
- [ ] No two files claim authority over the same fact.
- [ ] The system prompt token budget is healthy (target ~10% of context).
- [ ] No semantic changes to persona, user identity, or behavioural instructions slipped in.

### Step 6 — Commit

```bash
cd <project-root>
git status --short
git diff
git add .sf/<files-changed>                   # only what you actually changed
git commit -m "doctor(context): <summary of repair>"
```

Do not push automatically — let the user review the diff first.

## Common Issues and Fixes

### System-prompt bloat

If the always-loaded files (system prompt + always-loaded skills) push past 10% of the context window:

- Move stable, low-frequency facts into the memory store.
- Move long examples into `references/` of the relevant skill.
- Demote low-value always-loaded skills to on-demand only.

### Skill overlap

If two skills' descriptions overlap so much the agent can't decide which to use:

- Compare their workflows. If 80% identical, merge. Keep the better name.
- If they target different *phases* (e.g. one is pre-execution, one post-), make the descriptions explicit about phase.

### Memory-store overgrowth

If the `memories` table has thousands of rows:

- Archive low-confidence, never-hit rows older than 30 days.
- Dedupe by content similarity (cheap heuristic: identical first 80 chars).
- Reset `hit_count` on rows that haven't been recalled in 90 days — let them earn their slot.

### Decision drift

If `.sf/DECISIONS.md` and `docs/dev/ADR-*.md` diverge:

- ADRs are the human-readable trail; DECISIONS.md is sf's tool-managed copy.
- Use `save_decision` to update DECISIONS.md (it regenerates the file). Update the matching ADR by hand.
- If they're already drifted, write a synthesis ADR pointing at both and supersede the older entries.

## Rules

- **Ask the user about goals, not implementation.** sf's context is for sf — don't ask the user about structural preferences for `.sf/` files. Ask how they want sf to *behave*.
- **Don't blind-apply edits to protected files.** List, propose, wait.
- **Verify before committing.** Read each touched file end-to-end after edits.
- **Don't auto-push.** The user reviews context-doctor diffs before they go to remote.
- **Repair, don't rewrite.** A 50-line edit to a 500-line file beats a full rewrite — the diff is the audit trail.
