Study guides / CCAR-F / Domain 5

Context Management & Reliability · Lesson 4 of 6

5.4 - Codebase Exploration & Context Degradation

Manage context effectively in large codebase exploration, including context degradation mitigation, scratchpad files, subagent delegation, and crash recovery via structured state manifests.

Large codebase exploration is one of the most context-intensive tasks a Claude-based agent performs. Whether an agent is exploring an unfamiliar repository, tracing dependency chains, or understanding legacy systems, extended sessions create a specific failure mode: context degradation. It has nothing to do with running out of tokens. The model simply loses its grip on earlier findings as the context fills with verbose discovery output.

Context Degradation

Context degradation manifests as a specific, observable behaviour: the model starts referencing "typical patterns" instead of the specific classes, methods, and dependency chains it discovered earlier in the session. After investigating several modules, the agent might say "this follows the typical repository pattern" instead of "the OrderRepository class at src/repos/order.ts implements the base Repository<T> interface with custom caching in the findById method."

This happens because:

  1. Each exploration step generates verbose output (file contents, search results, directory listings).
  2. This output accumulates in the conversation context.
  3. Earlier, precise discoveries are pushed further into the context while more recent verbose output dominates.
  4. The model's attention shifts to recent output and it loses specific references to earlier findings.

The critical insight: context degradation is not a token limit problem. Increasing the context window doesn't fix it. The model isn't running out of space. It's losing track of specific details as they get buried under newer, more verbose output.

Scratchpad Files

The primary mitigation for context degradation is scratchpad files. The agent writes key findings to a file and references it for subsequent questions. This persists knowledge outside the conversation context, making it immune to context degradation.

# Exploration Scratchpad - Order Service

## Key Classes
- `OrderRepository` (src/repos/order.ts) - implements Repository<T>, custom findById caching
- `OrderService` (src/services/order.ts) - orchestrates OrderRepository + PaymentGateway
- `RefundProcessor` (src/services/refund.ts) - depends on OrderService.getOrderWithItems()

## Dependency Chain
RefundProcessor → OrderService → OrderRepository → PostgreSQL
RefundProcessor → PaymentGateway → Stripe API

## Critical Findings
- RefundProcessor has no retry logic for Stripe API failures
- OrderRepository caches by orderId but cache invalidation on status change is missing
- Test coverage: OrderService has 87% coverage, RefundProcessor has 12%

When the agent needs to reference earlier discoveries, it reads the scratchpad file instead of relying on conversation context. Treat this as a deliberate strategy from the outset, not a rescue move once things degrade - agents should be instructed to maintain scratchpad files from the start of any extended exploration session.

Subagent Delegation

Spawning subagents for specific investigation tasks is the second major mitigation strategy. Instead of the main agent doing all exploration directly (filling its context with verbose output from every file read and search), delegate specific questions to subagents:

Each subagent operates with its own isolated context. It can explore verbosely without polluting the main agent's context. It returns a structured summary to the coordinator, which keeps only the key findings.

Parallelisation is the obvious read; the real value is context isolation. The main agent's context stays clean for high-level coordination while subagents handle the verbose exploration.

Summary Injection Between Phases

When exploration happens in phases (Phase 1: understand the architecture, Phase 2: investigate specific components), summarise key findings from Phase 1 before spawning Phase 2 subagents. Inject these summaries into the initial context of Phase 2 subagents.

This prevents the "cold start" problem where Phase 2 subagents duplicate Phase 1 exploration because they were not given the previous findings. It also ensures that Phase 2 agents have the architectural understanding needed to ask the right questions.

Phase 1 Summary (injected into Phase 2 subagent prompts):
- The system follows a layered architecture: Controllers → Services → Repositories → Database
- The refund flow passes through: RefundController → RefundProcessor → OrderService → PaymentGateway
- Key concern: RefundProcessor has no retry logic for external API failures
- Phase 2 objective: Investigate error handling in RefundProcessor and PaymentGateway

The /compact Command

Claude Code provides a /compact command specifically for reducing context usage during extended sessions. When context fills with verbose discovery output - file contents, search results, directory listings - /compact summarises the conversation to free up space while preserving key information.

Use /compact proactively during extended exploration sessions, not just when you hit context limits. It's there to protect context quality, not only quantity.

Crash Recovery via Structured State Manifests

Extended exploration sessions can fail due to session crashes, network interruptions, or context exhaustion. Without recovery mechanisms, all exploration progress is lost.

The fix is structured state persistence. Each agent exports its current state to a known file location (a manifest). This manifest includes:

{
  "sessionId": "explore-order-service-001",
  "phase": 2,
  "exploredPaths": [
    "src/repos/order.ts",
    "src/services/order.ts",
    "src/services/refund.ts"
  ],
  "keyFindings": {
    "architecture": "Layered: Controllers → Services → Repositories → DB",
    "criticalIssue": "RefundProcessor has no retry logic for Stripe API failures",
    "testCoverage": {"OrderService": "87%", "RefundProcessor": "12%"}
  },
  "nextSteps": [
    "Investigate PaymentGateway error handling",
    "Review RefundProcessor test files",
    "Check cache invalidation logic in OrderRepository"
  ]
}

On resume, the coordinator loads this manifest and injects it into agent prompts. The agent picks up where it left off without repeating earlier exploration.

Key Concept

Context degradation is not a token limit problem - it is the model losing grip on specific findings as verbose output accumulates. Scratchpad files persist key discoveries outside the context. Subagent delegation isolates verbose exploration. Crash recovery manifests prevent progress loss across sessions.

Exam traps

Practice question

A developer productivity agent is exploring an unfamiliar codebase. After investigating several modules, it starts referencing 'typical repository patterns' instead of the specific class names and dependency chains it discovered earlier. What is the most effective mitigation?

  • A Increase the model context window so that far more of the discovery output can be retained throughout the whole exploration

    Context degradation is not about running out of tokens - it is about the model losing grip on earlier findings as verbose output accumulates. A larger window does not fix this.

  • B Have the agent maintain scratchpad files recording key findings and reference them for subsequent questions Correct

    Scratchpad files persist knowledge outside the conversation context, directly counteracting context degradation by keeping critical discoveries accessible regardless of context state.

  • C Restart the session with a fresh context and ask the agent to explore the codebase more efficiently this time

    Restarting loses all accumulated knowledge without addressing the underlying context degradation problem. Without scratchpad files, the same degradation will recur.

  • D Pre-load the entire codebase structure into the initial context so exploration has less to rediscover

    This would consume context budget before exploration starts and does not address degradation during the session. The problem is accumulated verbose output, not missing initial context.

Build exercise: Build a Context-Resilient Codebase Explorer

Advanced · 60 minutes

You'll practice:

  1. Create a coordinator agent that delegates specific codebase exploration tasks to subagents (e.g., find test files, trace dependency chains, identify external integrations)

    Subagent delegation is primarily about context isolation, not parallelisation. The main agent context stays clean for high-level coordination while subagents handle verbose exploration. This directly prevents context degradation by keeping verbose file contents and search results out of the coordinator context.

    You should see: A coordinator function that spawns subagents with specific, focused investigation prompts. Each subagent returns a structured summary (key findings, file paths, class names) rather than raw verbose output. The coordinator context should remain clean.

    Hints
    1. Define 3-4 specific investigation tasks, each narrow enough for a single subagent to handle without filling its own context.
    2. Each subagent should return structured data (class names, file paths, findings), not the raw file contents it read during exploration.
    3. const investigationTasks = [
        { task: "Find all test files for the order service and report coverage status", subagent: "test-coverage" },
        { task: "Trace the refund flow from API endpoint to database, listing all intermediate services", subagent: "refund-flow" },
        { task: "Identify all external API integrations and their error handling patterns", subagent: "external-apis" }
      ];
      
      async function delegateToSubagent(task) {
        const result = await spawnSubagent({
          prompt: task.task,
          returnFormat: "structured_summary"
        });
        // Coordinator receives only the summary, not verbose exploration output
        return { task: task.subagent, findings: result.structuredFindings };
      }
  2. Implement scratchpad file management: agents write key findings (class names, file paths, dependency chains) to a known file and read it before subsequent exploration steps

    Scratchpad files are the primary mitigation for context degradation. They persist knowledge outside the conversation context, making it immune to the attention shift that causes the model to reference typical patterns instead of specific class names and file paths it discovered earlier.

    You should see: An agent that writes structured findings to a scratchpad file after each exploration step and reads the scratchpad at the start of each subsequent step. The scratchpad should contain specific class names, file paths, and dependency chains, not summaries.

    Hints
    1. The scratchpad should be a Markdown file with clear sections for key classes, dependency chains, and critical findings. Write to it after each major discovery.
    2. This is a deliberate strategy, not a fallback. Agents should be instructed to maintain scratchpad files from the start of any extended exploration session.
    3. const SCRATCHPAD_PATH = "/tmp/exploration-scratchpad.md";
      
      async function updateScratchpad(newFindings) {
        const existing = await readFile(SCRATCHPAD_PATH).catch(() => "");
        const updated = existing + "\n\n" + formatFindings(newFindings);
        await writeFile(SCRATCHPAD_PATH, updated);
      }
      
      function formatFindings(findings) {
        return `## ${findings.module}\n` +
          `- Class: \`${findings.className}\` (${findings.filePath})\n` +
          `- Implements: ${findings.interfaces.join(", ")}\n` +
          `- Dependencies: ${findings.dependencies.join(" -> ")}\n` +
          `- Critical: ${findings.criticalNote || "None"}`;
      }
      
      // Before each exploration step, read the scratchpad
      const context = await readFile(SCRATCHPAD_PATH);
  3. Build summary injection logic: after Phase 1 exploration, summarise findings and inject the summary into Phase 2 subagent prompts

    Summary injection prevents the cold start problem where Phase 2 subagents duplicate Phase 1 exploration because they were not given previous findings. It ensures Phase 2 agents have the architectural understanding needed to ask the right questions without rediscovering the system structure.

    You should see: A Phase 1 summary document that captures the high-level architecture, key concerns, and specific investigation targets for Phase 2. This summary is injected into the initial prompt of every Phase 2 subagent.

    Hints
    1. The summary should include the architectural overview, dependency chains discovered, and the specific Phase 2 objective for each subagent.
    2. Keep the summary concise and structured. Phase 2 subagents need context, not the full verbose output from Phase 1.
    3. function buildPhase2Prompt(phase1Summary, phase2Task) {
        return `## Context from Phase 1 Exploration\n` +
          `Architecture: ${phase1Summary.architecture}\n` +
          `Key dependency chain: ${phase1Summary.dependencyChain}\n` +
          `Critical concern: ${phase1Summary.criticalIssue}\n\n` +
          `## Your Phase 2 Task\n${phase2Task}\n\n` +
          `Use the Phase 1 context to guide your investigation. Do not re-explore already-discovered architecture.`;
      }
      
      const phase1Summary = {
        architecture: "Layered: Controllers -> Services -> Repositories -> DB",
        dependencyChain: "RefundController -> RefundProcessor -> OrderService -> PaymentGateway",
        criticalIssue: "RefundProcessor has no retry logic for Stripe API failures"
      };
  4. Implement crash recovery: each agent exports structured state (explored paths, key findings, next steps) to a manifest file that the coordinator loads on resume

    Extended exploration sessions can fail from crashes, network interruptions, or context exhaustion. Without recovery mechanisms, all progress is lost. Structured state manifests enable the coordinator to resume from the last checkpoint rather than restarting from scratch.

    You should see: A manifest file in JSON format containing the session ID, current phase, explored paths, key findings, and next steps. On resume, the coordinator loads this manifest and injects it into agent prompts so exploration continues from where it left off.

    Hints
    1. The manifest should be updated after every significant exploration step, not just at the end of a phase. Frequent checkpointing minimises lost work on crash.
    2. Include a nextSteps array so the resumed session knows exactly what to investigate next without re-analysing the findings.
    3. const MANIFEST_PATH = "/tmp/exploration-manifest.json";
      
      async function saveManifest(state) {
        await writeFile(MANIFEST_PATH, JSON.stringify({
          sessionId: state.sessionId,
          phase: state.phase,
          exploredPaths: state.exploredPaths,
          keyFindings: state.keyFindings,
          nextSteps: state.nextSteps,
          lastUpdated: new Date().toISOString()
        }, null, 2));
      }
      
      async function resumeFromManifest() {
        const manifest = JSON.parse(await readFile(MANIFEST_PATH));
        console.log(`Resuming session ${manifest.sessionId} from phase ${manifest.phase}`);
        console.log(`Already explored: ${manifest.exploredPaths.length} paths`);
        console.log(`Next steps: ${manifest.nextSteps.join(", ")}`);
        return manifest;
      }
  5. Test context degradation by running an extended exploration session across multiple modules and verify that scratchpad files preserve specific class names and file paths that would otherwise degrade to generic descriptions

    This validates that the scratchpad mitigation actually works against context degradation. The observable symptom is the model referencing typical patterns instead of specific classes and paths. You need to confirm that scratchpad files prevent this degradation.

    You should see: Two comparison runs: one without scratchpad files where the agent degrades to generic references after exploring 4-5 modules, and one with scratchpad files where the agent maintains specific class names and file paths throughout the entire session.

    Hints
    1. Look for the specific degradation symptom: the agent saying this follows the typical repository pattern instead of the OrderRepository class at src/repos/order.ts implements Repository<T>.
    2. After exploring 5+ modules, ask the agent to list all classes it discovered with their file paths. Without scratchpad files, it will miss or generalise. With scratchpad files, it will reference the file for accurate details.
    3. // Test without scratchpad
      const withoutScratchpad = await exploreModules(5, { useScratchpad: false });
      // Ask: "List all classes you discovered with their file paths"
      // Expected: generic references like "a repository class" and "the service layer"
      
      // Test with scratchpad
      const withScratchpad = await exploreModules(5, { useScratchpad: true });
      // Ask: "List all classes you discovered with their file paths"
      // Expected: specific references like "OrderRepository at src/repos/order.ts"
      
      // Measure specificity
      function measureSpecificity(response) {
        const specificRefs = (response.match(/\b\w+\.ts\b/g) || []).length;
        const genericRefs = (response.match(/typical|standard|common pattern/gi) || []).length;
        return { specificRefs, genericRefs, ratio: specificRefs / (genericRefs + 1) };
      }

Sources