Not all kernel API changes are equal. A simple deprecation — replacing ida_simple_get() with ida_alloc() — is a mechanical transformation. The function signature changed, the new name is known, and every call site needs the same update. A competent find-and-replace with type awareness could handle it.
Contrast that with a lifecycle reordering change, where the kernel modifies the order in which device resources are initialized and released. This affects multiple functions across multiple files in a driver, requires understanding the driver's resource management flow, and may demand restructuring error paths that were designed around the old initialization order.
These are fundamentally different tasks. Using the same approach for both is either wasteful (spending expensive compute on trivial changes) or insufficient (applying a shallow transformation to a deep problem). KDRIFT uses two agents optimized for different complexity levels, with an escalation policy that routes each case to the appropriate tier.
The LPA is the fast path. It is template-conditioned, single-file scope, sub-second latency. It handles change classes 1 through 4 in the KDRIFT taxonomy: signature changes, return type changes, deprecation replacements, and struct field reshaping. These are the syntactic changes — the ones where the transformation can be determined from the API delta alone, without broader context.
The LPA's input is minimal: the change classification (one of 9 types), the AST delta between old and new API, and the driver source file to be patched. It does not have access to tools — no grep, no AST query, no documentation lookup. It works entirely from the information provided in its prompt, conditioned on transformation templates learned from thousands of kernel migration examples.
This constraint is deliberate. By limiting the LPA's scope and capabilities, we achieve two things: speed (no tool-use latency, no iterative refinement) and predictability (the output is a function of the input, with minimal variance across runs).
Here is a typical LPA case. The kernel deprecates ida_simple_get() in favor of ida_alloc(), changing the argument order:
This is a clean, mechanical transformation. The LPA identifies both ida_simple_get() and ida_simple_remove() call sites, maps them to their replacements (ida_alloc() and ida_free()), adjusts the arguments to match the new signatures, and generates the patch. Total time: 0.3 seconds. The patch compiles, passes Sparse, boots in QEMU, and matches the golden reference.
The LPA resolves approximately 75% of all DRIFTBENCH cases. This is not surprising — the majority of kernel API changes are syntactic in nature. Renaming, argument reordering, deprecation of convenience wrappers, and struct field movement account for the bulk of API evolution. These changes are frequent, predictable, and well-suited to template-conditioned generation.
The GMA is the deep path. It handles change classes 5 through 9: lifecycle ordering, concurrency and locking, error handling semantics, security and permissions, and cross-subsystem changes. These are the semantic changes — the ones where understanding the behavioral shift is as important as understanding the syntactic delta.
Unlike the LPA, the GMA has full tool access:
The GMA's workflow is iterative. It starts by analyzing the API change in depth — reading the commit message, comparing the old and new implementation, examining how other in-tree drivers adapted. It then generates an initial patch, compiles it, analyzes any errors, and refines. This loop runs for up to 5 iterations before the agent returns its best result.
The iterative approach is necessary because semantic changes often have non-obvious consequences. A locking change might require moving a function call outside a critical section, which requires restructuring the error handling, which requires changes to how resources are released. The GMA discovers these cascading requirements through the compile-refine loop — each compilation attempt reveals the next layer of adaptation needed.
Every migration case starts with the LPA. The LPA is cheap and fast, and it handles the majority of cases correctly. The escalation policy is simple:
This two-tier design means 75% of cases never need the expensive agent. The GMA is only invoked for the 25% of cases where the LPA's limited context is insufficient. And when the GMA does run, it has the benefit of the LPA's failed attempt as additional signal.
There is a subtlety here: the escalation trigger is currently compilation failure only. Cases where the LPA patch compiles but fails at later validation stages (Sparse, QEMU, runtime) are not currently escalated — they are reported as partial successes with diagnostic information. This is a deliberate design choice. The GMA's strength is in understanding complex API changes, not in debugging runtime behavior. We find that patches which compile but fail later stages are often close to correct and benefit more from human review than from additional agent iterations.
The cost differential is significant. The LPA runs in ~0.3 seconds at ~$0.002 per run. It uses a single model call with a compact prompt — the classification, the AST delta, and the driver source. No tool use, no iteration, no multi-turn conversation.
The GMA runs in ~45 seconds on average at ~$0.15 per run. It makes multiple model calls (initial analysis, patch generation, up to 5 compile-refine iterations), uses tools (grep, AST query), and processes significantly more context (kernel documentation, commit history, related driver adaptations).
The two-tier design reduces average cost by approximately 4x compared to always using GMA. For a team maintaining 20 drivers across a kernel upgrade with 50 API changes, the difference is meaningful: ~$2 for the two-tier approach versus ~$150 for GMA-only. More importantly, the LPA's sub-second latency means the 75% of cases it handles are resolved faster than a developer can context-switch to review them.
The GMA's 45-second average includes considerable variance. Simple escalation cases (where the LPA was close but missed a secondary change) resolve in 10-15 seconds. Complex cross-subsystem changes can take the full 5-iteration budget, running up to 2 minutes. The 45-second average reflects the mix of case complexity within the escalation pool.
For practical migration workflows, the throughput numbers that matter are:
In practice, a typical kernel upgrade (v6.8 to v6.9) with 30-50 affected API changes for a given driver set completes in under 5 minutes end-to-end using the two-tier approach. This includes classification, LPA attempts, GMA escalation for failures, and full four-stage validation for all generated patches. The output is a set of reviewed, validated patches ready for human review — not raw model outputs that need manual verification.