Part II: Discovery Through Software Engineering and Vibe Coding
Chapter 8: Foundations of AI Assisted Software Engineering

8.1 Code Foundation Models

"I memorized every Stack Overflow answer ever posted. The hard part was learning which ones were wrong."

A Language Model Graduating from Pre-training

Prerequisites

This section opens Chapter 8. We assume you have read Chapter 7 on software as a discovery process and have a conceptual understanding of transformer architectures (attention, positional encoding, autoregressive generation). If the term "next-token prediction" is unfamiliar, review Chapter 4 on reasoning foundations before proceeding.

The Big Picture

Code foundation models are transformer-based language models trained on massive corpora of source code and natural language. They learn statistical patterns over token sequences that capture syntax, semantics, idioms, API usage, and even aspects of program behavior. Three training phases determine what a code model can do: pre-training builds broad competence over code and language, fine-tuning specializes the model for specific tasks (instruction following, code repair, test generation), and in-context learning adapts behavior at inference time through prompts and examples. Understanding these three phases is essential for knowing what coding AI tools can and cannot do, and for using them effectively in your own work. Figure 8.1 illustrates how these phases build on each other. Figure 8.1.1 illustrates the three-phase training pipeline of code foundation models.

Three-phase training pipeline of code foundation models
Figure 8.1.1: The three-phase training pipeline of code foundation models, from pre-training on raw code corpora through fine-tuning with human feedback to in-context learning at inference time.
Pre-training Causal LM + FIM on code corpora (900B+ tokens) Raw code + docs Fine-tuning SFT, RLHF, DPO on (instruction, response) pairs In-Context Learning Prompt examples at inference time Code assistant Broad code competence Instruction following Figure 8.1: Three-phase training pipeline
Figure 8.1: The three-phase training pipeline for code foundation models. Pre-training on large code corpora builds broad competence; fine-tuning with supervised (SFT), reward-based (RLHF), or preference-based (DPO) methods adds instruction-following ability; in-context learning adapts behavior at inference time through prompt examples, producing a usable code assistant. Each acronym is defined in Section 4 below.

1. Code as a Sequence Modeling Problem

In 2021, a neural network that had never executed a single program reportedly scored higher on introductory programming exams than most human students, generating correct solutions from nothing but natural-language problem descriptions. The trick was deceptively simple: treat source code the same way a language model treats English prose, as a sequence of tokens to predict. Given a prefix of tokens \(x_1, x_2, \ldots, x_{t-1}\), the model estimates a probability distribution over the next token:

$$P(x_t \mid x_1, x_2, \ldots, x_{t-1}; \theta)$$

where \(\theta\) denotes the model's parameters. Training maximizes the log-likelihood over a corpus \(\mathcal{D}\) of code files:

$$\mathcal{L}(\theta) = \sum_{x \in \mathcal{D}} \sum_{t=1}^{|x|} \log P(x_t \mid x_{<t}; \theta)$$

This objective, called causal language modeling (CLM), where the model predicts each token using only the tokens that precede it, is the same one used for GPT-style text models. What makes code models distinctive is not the objective but the training data, the tokenizer, and the additional training objectives layered on top.

Code differs from natural language in ways that matter for modeling. Parsers and compilers enforce strict syntax; a single misplaced bracket makes a program fail. Identifiers carry semantic weight (a variable named user_count conveys intent that x does not). Python treats indentation as syntactic structure, and all languages rely on it for readability. Files within a repository depend on each other through imports, inheritance, and API contracts. These structural properties force a code model to learn far more rigid constraints than a prose model, but they also supply richer training signal. In short: code is a language strict enough to compile yet expressive enough to narrate its own intent, and that dual nature is exactly what makes it ideal training data for a neural model.

Common Misconception

A frequent misconception is that code foundation models "understand" code the way a compiler or interpreter does, by parsing syntax trees and applying formal rules. In reality, these models learn statistical correlations over token sequences: they predict what token is likely to come next based on patterns seen during training, not by executing or formally verifying the code. This distinction matters because it explains why a model can produce code that looks plausible and follows common patterns yet contains subtle logical errors that a compiler or type checker would catch immediately.

2. Tokenization for Programming Languages

Tokenization, the process of splitting raw text into the discrete units the model processes, is the very first step in any language model pipeline; the model never sees raw characters, only token IDs. This step presents unique challenges for code. Natural-language tokenizers like byte-pair encoding (BPE, explained below) are trained primarily on prose and may fragment code tokens in unhelpful ways. Consider the Python identifier get_user_by_email: a prose-trained BPE tokenizer might split it into ["get", "_user", "_by", "_email"], while a code-aware tokenizer preserves it as fewer, more meaningful tokens.

The tokenizer converts raw characters into integer IDs from a fixed vocabulary; the transformer then maps these IDs to embedding vectors for processing. The tokenizer choice directly controls how much source code fits within the model's finite context window, how much each API call costs (providers charge per token), and whether the model treats meaningful code constructs as atomic units rather than arbitrary character fragments.

Byte-pair encoding (BPE), the most common tokenization algorithm, starts with individual bytes or characters and iteratively merges the most frequently co-occurring pair into a new vocabulary entry. It repeats this process until the vocabulary reaches a target size. Use a code-specialized tokenizer (such as those shipped with StarCoder or DeepSeek-Coder) whenever your workload is predominantly code; fall back to a general-purpose tokenizer (like GPT-4's cl100k_base) only when the input mixes prose and code roughly equally.

Whitespace and indentation are critical in Python but are often collapsed by prose tokenizers. Code-specialized tokenizers preserve indentation tokens explicitly, sometimes encoding indentation depth as a single token (e.g., <INDENT_4>). This reduces sequence length (important because transformer cost scales quadratically with context in standard attention) while preserving syntactic structure.

The effect becomes concrete with a simple Python function:

import tiktoken

# Compare tokenization of the same code snippet
code = """def fibonacci(n: int) -> list[int]:
    sequence = [0, 1]
    for i in range(2, n):
        sequence.append(sequence[-1] + sequence[-2])
    return sequence
"""

# GPT-4 tokenizer (cl100k_base)
enc_gpt4 = tiktoken.get_encoding("cl100k_base")
tokens_gpt4 = enc_gpt4.encode(code)
print(f"cl100k_base tokens: {len(tokens_gpt4)}")

# Inspect individual tokens to see split points
for tok in tokens_gpt4[:15]:
    print(f"  {tok:6d} -> {repr(enc_gpt4.decode([tok]))}")
Listing 8.1: Comparing tokenization of a Fibonacci function with the cl100k_base BPE tokenizer, showing how identifiers and operators are split into subword units.

The token count directly impacts both inference cost and the amount of code that fits within the model's context window. A tokenizer that uses 40 tokens for a function signature leaves less room in the context for surrounding code. This is why models designed for code (StarCoder, Code Llama, DeepSeek-Coder) train their tokenizers on code-heavy corpora, yielding vocabularies where common programming constructs (def, return, import, self.) are single tokens.

3. Pre-training: Learning the Language of Code

Pre-training is the phase where the model absorbs the statistical structure of code from a large corpus. The scale of these corpora is staggering: The Stack v2, used to train StarCoder2, contains over 900 billion tokens across 600+ programming languages. Codex (circa 2021) was trained on 159 GB of Python code from GitHub. These datasets include not just code but also comments, docstrings, README files, commit messages, and issue discussions, providing the model with natural-language context that bridges intent and implementation.

Key Insight: Code Models Learn More Than Syntax

Pre-training on code teaches models far more than syntax completion. By predicting the next token across millions of repositories, the model implicitly learns API usage patterns (which functions are called together), common bug patterns (what code typically follows a resource allocation), testing conventions (what assertions follow what operations), and even aspects of program semantics (variables named total tend to be sums of previously defined quantities). This emergent knowledge is what makes code LLMs useful for tasks far beyond autocomplete: code review, bug detection, refactoring, and documentation generation.

The standard causal language modeling objective trains the model to predict code left-to-right. But real programming rarely proceeds linearly. A developer might write a function signature, skip to the return statement, then fill in the body. The fill-in-the-middle (FIM) objective addresses this by training the model to predict a missing span given surrounding context:

$$\text{Input: } \texttt{1
Listing 8.2: Simulating the FIM data transformation on a quicksort function, extracting a random span and restructuring the code into prefix-suffix-middle format.

Pre-training and FIM give a model broad competence over code patterns, but that raw capability alone does not make the model useful as a programming assistant; it still needs to learn how to follow human instructions.

4. Fine-tuning: From Completion to Conversation

A pre-trained code model is a powerful completion engine, but it has no concept of following instructions. If you type "write a function that sorts a list," the model might complete your sentence with more English prose rather than producing code. Fine-tuning bridges this gap by training on curated datasets of (instruction, response) pairs.

Three fine-tuning approaches dominate code model development:

Supervised, Reward-Based, and Preference-Based Methods

Supervised fine-tuning (SFT) trains on human-written or human-verified instruction-response pairs. The dataset might contain entries like ("Write a Python function that computes the nth Fibonacci number using memoization", followed by a correct implementation). SFT teaches the model to map natural-language specifications to code.

Reinforcement learning from human feedback (RLHF) goes further by training a reward model on human preferences between pairs of outputs, then optimizing the code model to produce outputs that the reward model scores highly. For code, the reward signal can incorporate not just human preference but also execution results: does the code compile? Does it pass the test suite? This combination of human judgment and automated verification is particularly powerful for code because correctness is partially verifiable.

Direct preference optimization (DPO) simplifies RLHF by skipping the separate reward model. Instead, it directly optimizes the policy (the code model) using pairs of preferred and rejected outputs. DPO has gained traction for code models because it is simpler to implement while typically achieving comparable results.

Checkpoint

So far: three fine-tuning methods build on top of pre-training: SFT teaches the model to follow instructions using curated example pairs, RLHF refines outputs by training a separate reward model on human preferences, and DPO achieves a similar effect without the reward model by optimizing directly on preferred versus rejected output pairs.

The loss function for SFT is straightforward: given an instruction $I$ and a target response $R = (r_1, r_2, \ldots, r_m)$, we minimize:

$$\mathcal{L}_{\text{SFT}}(\theta) = -\sum_{t=1}^{m} \log P(r_t \mid I, r_1, \ldots, r_{t-1}; \theta)$$

Note that the loss is computed only over the response tokens $r_t$, not the instruction tokens. The instruction provides context but the model is not penalized for its representation of the instruction.

Practical Example: Fine-tuning Data for Code Repair

Consider building a fine-tuning dataset for automated bug fixing. Each example pairs a buggy function (instruction) with a corrected version (response):

2
Listing 8.5: Structuring a fine-tuning example for code repair, pairing a buggy binary search with its corrected version and explanatory reasoning.

Real fine-tuning datasets for code repair contain thousands of such pairs, often mined from version control history: the buggy version comes from one commit and the fix from the next. The model learns not just to produce correct code but to explain the reasoning behind the fix, which is crucial for developer trust.

5. In-Context Learning: Adaptation at Inference Time

In-context learning (ICL) is the remarkable ability of large language models to adapt their behavior based on examples provided in the prompt, without updating any model parameters. For code models, ICL means you can teach the model a new API, a coding convention, or a transformation pattern simply by including examples in the context window.

ICL operates through what researchers call task vectors (directions in the model's internal representation space that encode a particular input-output mapping), where the model's internal activation patterns shift to represent the function implied by the in-context examples. When the model sees a pattern of (input, output) pairs in its context, its internal representations shift to implement the implied function. The number of examples needed depends on the complexity of the pattern: a simple name-refactoring rule might need one example, while a complex data transformation might need five or more.

3
Listing 8.3: Building an in-context learning prompt that teaches a code model to add type hints via input-output examples, with no parameter updates required.

ICL drives most practical code AI workflows. Pasting existing code into a chat with Claude or Cursor and requesting modifications provides in-context examples; a coding agent reading your repository before generating new code uses ICL to match your project's style. Context quality directly determines output quality, as detailed in Chapter 11: Context Engineering.

Whether the model adapts through fine-tuning or in-context examples, the end goal is the same: producing correct code from a specification. This goal has a long history that predates neural networks entirely.

6. Program Synthesis: From Specification to Code

Program synthesis, the automatic generation of programs from specifications, predates LLMs by decades. Classical approaches used deductive synthesis (deriving programs from logical specifications), inductive synthesis (generalizing from input-output examples), or constraint-based synthesis (encoding the specification as a satisfiability problem). LLM-based code generation represents a new paradigm: neural program synthesis, where the "specification" is a natural-language description and the "search" is implicit in the model's learned distribution over programs.

The connection to Chapter 1 is direct: program synthesis is search over the space of programs. The search space $S$ is the set of all syntactically valid programs; the objective $f$ is correctness with respect to the specification; and the model's learned distribution serves as a heuristic that guides search toward promising regions of program space. Temperature sampling (controlling randomness by scaling the logit distribution, where logits are the raw unnormalized scores the model assigns to each vocabulary token before converting them to probabilities), beam search (maintaining the top-$k$ partial sequences at each step), and nucleus sampling (sampling from the smallest set of tokens whose cumulative probability exceeds a threshold $p$) are all strategies for navigating this space, each with different exploration-exploitation trade-offs (recall Section 1.2).

The pass@k metric quantifies how effectively a model searches program space. Given a problem, we sample $n$ candidate programs and check how many of the first $k$ pass all test cases. The unbiased estimator for pass@k, given $n$ total samples and $c$ correct ones, is:

$$\text{pass@k} = 1 - \frac{\binom{n-c}{k}}{\binom{n}{k}}$$

This metric reveals a key insight: generating multiple candidates and selecting among them is far more effective than generating a single "best" candidate. A model with 30% pass@1 can, under typical conditions, achieve 70% pass@10, because different samples explore different regions of program space. This motivates the generate-and-test approach that underlies most coding agents.

from math import comb

def pass_at_k(n: int, c: int, k: int) -> float:
    """Compute the unbiased pass@k estimator.

    Args:
        n: Total number of samples generated
        c: Number of correct samples (passing all tests)
        k: The k in pass@k (number of attempts allowed)

    Returns:
        Probability that at least one of k samples is correct
    """
    if n - c < k:
        return 1.0  # more correct than k, guaranteed pass
    return 1.0 - comb(n - c, k) / comb(n, k)


# Demonstrate the power of multiple samples
print("pass@k for a model with 30% base accuracy (n=100, c=30):")
for k in [1, 5, 10, 25, 50]:
    score = pass_at_k(n=100, c=30, k=k)
    print(f"  pass@{k:2d} = {score:.3f}")

# Output:
# pass@k for a model with 30% base accuracy (n=100, c=30):
#   pass@ 1 = 0.300
#   pass@ 5 = 0.836
#   pass@10 = 0.976
#   pass@25 = 1.000
#   pass@50 = 1.000
Listing 8.4: Computing the unbiased pass@k estimator, showing how sampling multiple candidate programs dramatically increases the probability of finding a correct solution.
Library Shortcut: HumanEval with the Evaluate Library

The manual pass@k computation above illustrates the mathematics, but in practice you would use Hugging Face's evaluate library, which bundles the HumanEval metric (where HumanEval is a benchmark of 164 hand-written Python programming problems introduced by OpenAI in 2021 to measure functional correctness of code generation) and handles sampling, execution sandboxing, and the unbiased estimator in two lines (as of 2024, HumanEval has been largely supplemented by more challenging benchmarks such as SWE-bench, HumanEval+, MBPP+, and LiveCodeBench, which test repository-scale reasoning and guard against data contamination; HumanEval remains useful as a lightweight sanity check):

Real-World Application: GitHub Copilot in IDE Autocomplete
Real-World Application: GitHub Copilot in IDE Autocomplete
import evaluate

code_eval = evaluate.load("code_eval")
results = code_eval.compute(
    references=["assert add(2,3)==5"],       # test cases
    predictions=[["def add(a,b): return a+b",  # candidate 1
                  "def add(a,b): return a*b"]], # candidate 2
    k=[1, 2]
)
# results["pass@1"], results["pass@2"]
Listing 8.6: Evaluating code candidates against test cases using Hugging Face's evaluate library with sandboxed execution and automatic pass@k computation.

This reduces roughly 30 lines of sampling, sandboxed execution, and metric computation to 5 lines, while handling edge cases like infinite loops via timeouts.

With the core training techniques and evaluation metrics in hand, the natural next question is which models put them into practice, and how their design choices differ.

7. The Landscape of Code Foundation Models

The field has produced a rich ecosystem of code models, each with different trade-offs in size, training data, licensing, and capabilities. Understanding this landscape helps you choose the right model for your task.

Closed-source frontier models like Claude (Anthropic), GPT-4 (OpenAI), and Gemini (Google) are trained on diverse mixtures of code and text. They excel at complex multi-step reasoning, long-context understanding, and instruction following. Their code capabilities emerge from general intelligence rather than code-specific training alone, which makes them strong at tasks requiring both code and natural-language understanding: explaining code, translating between languages, and reasoning about software architecture.

Open-weight code-specialized models like StarCoder2, DeepSeek-Coder, and Code Llama are trained on code-heavy corpora with code-specific tokenizers and objectives (as of 2025, newer entrants such as DeepSeek-Coder-V2, Qwen2.5-Coder, and CodeGemma have joined this tier, often surpassing their predecessors on standard benchmarks). They are often smaller (1B to 33B parameters compared to frontier models at 100B+) but can match or exceed larger general models on pure coding benchmarks, particularly for languages well-represented in their training data. Their open weights enable fine-tuning for specific codebases or tasks, a capability we leverage in Chapter 16 on repository-scale implementation.

As a practical starting point for choosing between these tiers: use a closed-source frontier model when the task requires complex reasoning across code and natural language (architecture design, multi-step debugging, code review with explanations), and reach for an open-weight code-specialized model when you need low-latency completion, local deployment, or the ability to fine-tune on a proprietary codebase. Many production workflows combine both, routing simple completions to a smaller model and escalating complex queries to a frontier model.

Research Frontier: Verified Code Generation with Execution Feedback

A major frontier in code foundation models is closing the loop between generation and verification. CodeChain (Le et al., 2023) introduced a technique where the model iteratively revises its own code by examining execution outputs from failed test cases, chaining together self-revision steps that progressively fix errors. Building on this direction, systems like SWE-agent (Yang et al., 2024) and OpenHands (Wang et al., 2024) embed code models inside agent loops that can browse repository files, run tests, and interpret stack traces before submitting a patch. These execution-grounded approaches represent a shift from single-shot generation toward iterative refinement with real-world feedback, achieving substantially higher solve rates on benchmarks like SWE-bench than purely prompt-based methods. Meanwhile, test-time compute scaling (extended "thinking" in models like Claude and OpenAI's o-series) applies complementary reasoning depth at inference, breaking complex problems into sub-problems and evaluating edge cases before generating code. We revisit this topic in Chapter 29: Reasoning Models for Discovery.

Try It: Compare Tokenizers on Your Own Code

This mini-project lets you measure how different tokenizers handle real code from your own projects, giving you intuition for context-window budgets and inference costs.

1. Install the tokenizer library: pip install tiktoken. This provides the tokenizers used by GPT-4 and GPT-4o.

2. Pick a Python file from one of your projects (ideally 50+ lines). Load it and tokenize with two encodings:

import tiktoken, pathlib

code = pathlib.Path("your_file.py").read_text()
enc_100k = tiktoken.get_encoding("cl100k_base")   # GPT-4
enc_200k = tiktoken.get_encoding("o200k_base")     # GPT-4o
print(f"cl100k: {len(enc_100k.encode(code))} tokens")
print(f"o200k:  {len(enc_200k.encode(code))} tokens")
Listing 8.7: Comparing cl100k_base and o200k_base token counts on a user-supplied Python file to measure tokenizer efficiency differences.

3. Compute the compression ratio (characters per token) for each encoding. A higher ratio means more code fits in the context window.

4. Inspect the first 20 tokens from each encoding by decoding them individually (enc.decode([tok])). Note where they split identifiers, operators, and whitespace differently.

5. Repeat with a file in a second language (JavaScript, Rust, or SQL) and compare. Code-aware tokenizers typically show larger efficiency gains on languages with verbose syntax (Java, TypeScript) than on terse ones (Python, Ruby).

Exercise 8.1.1

A code model generates 50 candidate solutions for a programming problem. You run each through the test suite and find that 8 pass all tests. Compute pass@1, pass@5, and pass@10 using the unbiased estimator from this section. Then answer: if you could double the number of correct samples to 16 (out of 50), by how much would pass@5 improve? Which is more cost-effective for raising pass@5: doubling sample quality (from 8/50 to 16/50 correct) or doubling sample quantity (from 50 to 100 samples with 16 correct)?

Hint

Use the formula \(\text{pass@k} = 1 - \binom{n-c}{k} / \binom{n}{k}\). For n=50, c=8, k=5: compute \(\binom{42}{5}/\binom{50}{5}\). Python's math.comb handles the arithmetic. For the comparison, note that doubling quality changes \(c/n\) while doubling quantity keeps \(c/n\) constant but increases \(n\). The nonlinear shape of the formula means one of these strategies wins decisively.

Step-Through: Fill-in-the-Middle Data Transformation

Trace through the FIM (prefix-suffix-middle) transformation on a concrete four-line function.

Original code (4 lines):
Line 0: def square(x):
Line 1: result = x * x
Line 2: print(result)
Line 3: return result

Step 1: Choose span boundaries. Suppose start=1, end=3 (lines 1 and 2 are the masked span).
Step 2: Extract prefix = Line 0 = "def square(x):"
Step 3: Extract middle (the target the model must predict) = Lines 1..2 = " result = x * x\n print(result)"
Step 4: Extract suffix = Line 3 = " return result"
Step 5: Assemble in PSM format: <PRE>def square(x):<SUF> return result<MID> result = x * x\n print(result)

The model sees the function signature and the return statement, then must reconstruct the two missing body lines. During training, thousands of such examples teach the model to generate code that is consistent with both what comes before and after the gap.

Real-World Application: GitHub Copilot in IDE Autocomplete

GitHub Copilot uses a FIM-trained code foundation model (originally based on OpenAI Codex, which OpenAI deprecated in March 2023, with Copilot subsequently migrating to newer GPT-4-class and multi-provider models) to power real-time autocomplete inside VS Code, JetBrains, and Neovim. When you place your cursor in the middle of a file, Copilot sends the code above the cursor as the prefix and the code below as the suffix, then streams the model's infilling prediction as a ghost-text suggestion. GitHub reported (circa 2022) that developers accept roughly 30% of Copilot's suggestions and that accepted code accounts for nearly 40% of newly written code in files where Copilot is active, demonstrating how FIM pre-training translates directly into a production developer tool used by millions.

The Billion-Token Typo Detector

During the creation of The Stack v2, researchers found that roughly 5% of files on public GitHub were exact or near-exact duplicates, and according to their ablation studies, deduplication alone improved downstream model quality more than adding 100 billion extra tokens of raw data. Even more surprising: code models trained on deduplicated corpora became significantly better at detecting copy-paste bugs, precisely because they were no longer memorizing duplicate snippets and could instead learn the subtle differences between nearly identical code blocks. In effect, teaching the model to see less data made it better at spotting when two pieces of code that look the same actually differ in a critical way.

Lab: Measuring Tokenizer Efficiency Across Languages

Goal: Quantify how tokenizer choice affects context-window utilization for different programming languages, and build intuition for why code-specific tokenizers matter.

Tools needed: Python 3.8+, pip install tiktoken, and 3 to 5 source files of roughly equal length (50 to 100 lines each) in different languages (e.g., Python, Java, Rust, SQL, and JavaScript). You can grab samples from any open-source repository.

Procedure (15 to 20 minutes): For each file, tokenize with both cl100k_base (GPT-4) and o200k_base (GPT-4o). Record the token count and compute the compression ratio (characters per token). Build a small table of language vs. tokenizer vs. compression ratio.

What to vary: Try files with heavy use of long identifiers (getUserAccountBalanceById) vs. short ones (x, i). Compare a minified JavaScript file against its unminified source.

What to observe: Which language gets the best compression? Which gets the worst? How large is the gap between the two tokenizers, and does the gap vary by language? Compute how many extra lines of Java (or your worst-compressed language) would fit in a 128k-token context window if you switched from the less efficient tokenizer to the more efficient one.

Exercises

  1. (Conceptual) A code model trained only on Python is asked to generate Rust code. Explain why it might still produce partially correct Rust, and identify two specific failure modes you would expect compared to a model trained on both languages.
  2. (Coding) Using the tiktoken library, compare the token count for the same 50-line Python function using the cl100k_base (GPT-4) and o200k_base (GPT-4o) tokenizers. Compute the percentage difference and explain which tokenizer is more efficient for code and why.
  3. (Analysis) A model achieves pass@1 = 0.15 on HumanEval. You have a budget of 20 API calls per problem. Compute pass@20 using the formula from this section. Then argue whether it is more cost-effective to spend 20 calls on one model with 15% pass@1, or 10 calls each on two different models with 10% and 20% pass@1 respectively (assume independence).

What's Next

Code foundation models process individual files as token sequences. But real software lives in repositories: interconnected webs of files, functions, classes, and dependencies. In Section 8.2: Repository-Level Reasoning, we build the graph structures that let AI reason about code at the scale of an entire codebase, enabling tasks like cross-file refactoring, issue-to-patch search, and test-guided program repair.