The wrong assumption at the start of most training tools
Most developer learning tools start with a blank slate assumption. They assume the learner knows nothing and progress linearly from fundamentals to advanced topics. This makes sense when the audience is someone learning to code for the first time. It makes almost no sense for a developer who has been writing production code for six years and is adding a new language to their existing mental model.
The blank slate approach wastes time on things the developer already knows and, more importantly, creates frustration. An experienced developer who is asked to complete "lesson 1: variables and types" before they can get to "lesson 8: goroutines" will bounce. Not because the lesson is hard but because it is boring and irrelevant. They already understand variables. What they do not understand is how Go's type system differs from what they know, and specifically where their existing mental models will lead them wrong.
When we designed the learning path system in HackQuest, we made a deliberate choice to start from what the developer has already shown us, not from a prescribed curriculum.
What we mean by concept detection
An adaptive path for experienced developers requires a reliable way to detect which specific concepts are missing. This is harder than it sounds. You cannot ask someone to take a pre-assessment test and expect an accurate answer. Developers generally have a poor model of their own gaps. They know what they know. They often do not know what they do not know until they try to write code and it breaks.
This is why code is the right signal. When a developer submits a PR, the diff is a direct window into the concepts they applied and the concepts they misapplied. A Go error handling mistake in a PR is more informative than a score on a multiple-choice question about error handling. The multiple-choice question tests whether someone can recognize a correct answer from a list. The PR tests whether they can produce correct code under realistic constraints, when they are focused on something other than the quiz itself.
HackQuest grades PRs at the concept level: each piece of feedback maps to one or more concepts in a knowledge graph. When a developer makes an error, we flag the concept, not just the line. When a developer handles something correctly, we mark that concept as demonstrated. The concept map updates after every PR, and it informs what the next lesson should be.
Sequencing gaps, not topics
A standard curriculum sequences topics: week one covers syntax, week two covers data structures, week three covers concurrency. The sequencing is logical and works well enough for a general population of learners starting from zero. It fails for experienced developers because the gaps are not distributed evenly across topics.
A Python developer switching to Go typically arrives with solid understanding of data structures, decent intuition for type systems even if Go's is different, and significant gaps around error handling conventions and concurrency models. They do not need week one and two at all. They need a targeted path through the specific parts of Go that conflict with or extend what they already know from Python.
Adaptive sequencing for this population means starting from the gaps shown in their first few PRs and building a path that addresses those gaps in a dependency-aware order. Concurrency and error handling are good examples of a dependency constraint. A developer who does not yet understand error-as-value in Go should probably not be doing deep dives on channel-based error propagation, because the channel pattern requires the error handling mental model to already be solid. Getting the sequencing wrong means a lesson lands on unprepared ground and does not stick.
Building a dependency graph for Go concepts took us several iterations. Some dependencies are obvious: you cannot understand goroutine ownership without first understanding how channels work as a communication primitive. Others are subtle: the proper use of defer with error handling requires both an understanding of how defer executes and a solid model of named return values. We got the second dependency wrong the first time and had to revise when we saw developers struggling with defer in error contexts despite having completed the defer lesson.
The problem of false confidence
One design challenge specific to experienced developers is false confidence: the developer thinks they understand a concept because they have used it successfully, but their understanding is shallower than they realize. This is different from a gap, which is a concept they have never applied. False confidence produces a specific pattern in PRs: the developer uses the feature correctly in simple cases and incorrectly in the edge cases that require a deeper model.
Consider Go interfaces. A developer from a Java background will use interfaces correctly in most straightforward cases because the surface-level mental model (a type satisfies an interface by implementing its methods) transfers. Where it breaks is implicit satisfaction: in Go, you do not declare that a type implements an interface. If a developer is expecting an explicit relationship and it does not exist, they may write code that compiles and passes basic tests but fails to satisfy an interface that was not in their mental view of the type hierarchy.
Detecting false confidence requires looking at patterns across PRs rather than individual errors. A developer who correctly uses interfaces in five PRs and then makes an implicit satisfaction error in the sixth is probably not missing the concept entirely; they are missing a specific aspect of it. The lesson path for false confidence cases is different: less foundational explanation, more targeted coverage of the specific edge case that revealed the gap.
What the path looks like in practice
For a developer who has submitted three or four PRs through HackQuest, the adaptive path looks like a small queue of lessons ordered by priority. The highest-priority lesson is the one that addresses the concept that appeared most recently in a PR error, especially if it has appeared more than once. The next lessons in the queue address related concepts in dependency order: if the top lesson covers context cancellation, the next might cover goroutine lifecycle management, since the two are tightly related.
The queue is not fixed. Submitting another PR can change the ordering. If a developer completes a lesson on error wrapping and then their next PR shows correct error wrapping but introduces a new gap around interface satisfaction, the interface concept rises in priority and the error wrapping concept can be deprioritized or removed from the queue entirely.
We do not prescribe a learning schedule. The path adapts to the pace of the developer's own PRs. Some developers submit multiple PRs per week; for them the feedback loop is fast and the path moves quickly. Others submit one per week or less; the path is slower but the lessons tend to stick better because there is more time to apply each concept before the next one appears.
What this design cannot do
Adaptive paths built from PR signals are good at detecting gaps in applied knowledge: what a developer does wrong when writing code under normal conditions. They are not as good at detecting gaps in conceptual knowledge that has not yet been tested in code. A developer might have a significant misunderstanding about how the Go scheduler works that has not yet produced a visible error in their PRs. The misunderstanding might only surface when they need to reason about performance or debug a subtle scheduling issue.
We are not claiming that PR-based adaptive paths replace all other learning inputs. Reading the Go specification, working through edge-case documentation, and talking to experienced Go developers all surface different kinds of knowledge gaps. Our position is that PR grading is the most direct signal of what a developer actually needs, because it tests production code rather than exercises, and because it captures the gap at the moment it matters: when the developer was trying to write real code and got something wrong.
The design goal is not a perfect curriculum. It is a learning path that wastes as little of the developer's time as possible and concentrates attention on the exact concepts that are blocking their ability to write idiomatic code in the new stack.