feat(learning): validator execution engine and learning API#58
Merged
Conversation
Runs the declarative validators of a roadmap step against the real state of the project's containers. Dispatch by type through a single registry, per-validator error isolation (an unknown type, invalid params or an unreachable Docker daemon produce an 'error' result for that validator and the others still run), infrastructure errors classified through the existing dockerErrors taxonomy, and a lazy memoized container list (one Docker call per step run). Ships the first validator, container_running.
- GET /api/learning/roadmaps — catalogue of the valid roadmap files
found in roadmaps/ (invalid files are logged and never served)
- GET /api/learning/roadmaps/:id — full roadmap for the player
- POST /api/learning/validate — runs every validator of a step for a
project and returns one structured result per validator
({status, message, errorCode?, expected?, observed?} + stepPassed)
Roadmap files are re-read on each request (hot reload for authors) and
resolved from __dirname, never process.cwd(): the CLI spawns the server
without a cwd. Infrastructure failures answer 200 with per-validator
'error' results — 4xx/5xx are reserved for request problems.
The learning engine loads roadmap files from roadmaps/ at the repo root; without this entry the published CLI would start with an empty catalogue.
Contract of the three /api/learning endpoints for the player (P-1/P-2): pass/fail/error semantics and their intended UI mapping, errorCode table, the 'Docker down answers 200 with error results' policy, a curl walkthrough (pass and fail) against the example roadmap, and the recipe for adding a validator type.
Derssa
approved these changes
Jul 14, 2026
OthmaneZ05
added a commit
that referenced
this pull request
Jul 18, 2026
* feat(learning): add the validator execution engine
Runs the declarative validators of a roadmap step against the real state
of the project's containers. Dispatch by type through a single registry,
per-validator error isolation (an unknown type, invalid params or an
unreachable Docker daemon produce an 'error' result for that validator
and the others still run), infrastructure errors classified through the
existing dockerErrors taxonomy, and a lazy memoized container list (one
Docker call per step run). Ships the first validator, container_running.
* feat(learning): expose roadmap loading and step validation over REST
- GET /api/learning/roadmaps — catalogue of the valid roadmap files
found in roadmaps/ (invalid files are logged and never served)
- GET /api/learning/roadmaps/:id — full roadmap for the player
- POST /api/learning/validate — runs every validator of a step for a
project and returns one structured result per validator
({status, message, errorCode?, expected?, observed?} + stepPassed)
Roadmap files are re-read on each request (hot reload for authors) and
resolved from __dirname, never process.cwd(): the CLI spawns the server
without a cwd. Infrastructure failures answer 200 with per-validator
'error' results — 4xx/5xx are reserved for request problems.
* chore: ship the roadmaps directory in the published npm package
The learning engine loads roadmap files from roadmaps/ at the repo
root; without this entry the published CLI would start with an empty
catalogue.
* docs: document the learning validation API
Contract of the three /api/learning endpoints for the player (P-1/P-2):
pass/fail/error semantics and their intended UI mapping, errorCode
table, the 'Docker down answers 200 with error results' policy, a curl
walkthrough (pass and fail) against the example roadmap, and the recipe
for adding a validator type.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary of Changes
The execution side of the roadmap format introduced in #54: a stateless engine that runs a step's declarative validators against the real state of a project's containers, so a learner's work can be auto-checked. Until now, roadmap files declared validators but nothing executed them.
New endpoints:
GET /api/learning/roadmaps— catalogue of the valid roadmap files inroadmaps/(invalid files are logged server-side and never served)GET /api/learning/roadmaps/:id— full roadmapPOST /api/learning/validate—{projectId, roadmapId, stepId}→ one structured result per validator (pass/fail/error+ message + optionalexpected/observed) and an aggregatedstepPassedDesign notes:
failmeans the learner hasn't completed the step yet;errormeans the check itself couldn't run (Docker daemon down, unknown validator type, bad params in the roadmap file) and carries anerrorCodereusing the existingdockerErrorstaxonomy. Infrastructure failures answer200with per-validatorerrorresults —4xx/5xxare reserved for request problems.engine/validators/+ one line inengine/registry.ts(recipe indocs/learning-api.md). This PR ships the first one,container_running; the rest of the v1 palette comes next.paramsare inert JSON interpreted by code in this repo.__dirname(the CLI spawns the server without a cwd).roadmaps/is now shipped in the published npm package so the catalogue isn't empty in production.Full contract, semantics and a curl walkthrough:
docs/learning-api.md.Types of Changes
Verification & Testing
Automated Checks
npm run lintsuccessfully with no errorsnpm run buildsuccessfully with no compilation errorsnpm testsuccessfully (all tests pass)Manual Verification
Ran the full loop against real containers with the backend in dev mode and Docker running:
POST /api/learning/validateon the example roadmap's first step before creating anything →status: "fail"with an actionable message ("No container named "web" exists in this project yet…").webnode via the containers API, re-validated →status: "pass",stepPassed: true.failwithobserved: "exited".error/UNKNOWN_VALIDATORwhile the other validator still returns its verdict.404s, missing body field →400.GET /api/learning/roadmapslists the example roadmap withstepCount: 4.Checklist