Git is the state machine.
labtrail is a methodology for building and running lab courses, plus the tooling that makes the methodology checkable.
A course is a git repository. A trail is a tree of labs rooted at a base commit, and each lab is exactly two consecutive commits, named by refs:
base ── 01-greet/start ── 01-greet/complete ── 02-shout/start ── 02-shout/complete
(the exercise) (the solution)
A learner's position is which branch they are on. Their work is their
commits. Going back is git switch; getting a correction is git pull --rebase. There is no progress file and no command that advances anybody.
Everything labtrail checks reduces to one property:
At
<lab>/startthe check must fail. At<lab>/completeit must pass.
A lab that already passes at its start ref asks the learner for nothing. A lab that fails at its complete ref cannot be finished. A lab whose check cannot run at the start ref looks broken rather than unsolved. All three are invisible to the author who wrote the lab; all three are found by running the same check at both ends.
git clone <course-url> && cd <course>
ivpm update -d dev # or whatever the course README says
labtrail doctor # is this environment going to work?
labtrail status # where am I, and what is next?
labtrail open 01-greet # a worktree on my/01-greet, ready to work
labtrail check # 0 correct, 1 not yet, 2 the lab is broken
labtrail validate # start fails, complete passes, for every lab
labtrail propagate 01-greet # replay a revision through the descendants
labtrail collect -o out.json # lab metadata for a docs build
labtrail propagate is the part worth knowing about. When a lab is revised,
every descendant must both rebase cleanly and still pass its check —
and those are unrelated properties. A revision that renames a token can
leave a descendant rebasing with no conflict at all and no longer testing
anything. Git reports success. Only re-running the invariant at each hop
finds it, which is what propagate does, on scratch refs, publishing
nothing until you ask.
labtrail ships four agent skills — labtrail, labtrail-learner,
labtrail-authoring, labtrail-checks — generated from the documentation
and registered in the agent.skills entry-point group. A course that
depends on labtrail gets them linked into .agents/skills/ by ivpm update,
with nothing to vendor and nothing to keep in sync. See
the agent skills.
The first line of all four is that the check script is the authority: never tell someone their work is correct because it looks correct.
pip install labtrail
Python 3.10+. One runtime dependency (PyYAML), because labtrail installs into every learner's environment and each dependency is an installation that can fail on someone else's machine for a reason unrelated to the course.
docs/ builds with Sphinx. Start with
the methodology; the
check contract is the part authors
most need.
docs/requirements.md is the specification and docs/plan.md is the
implementation plan and running log.
Apache-2.0.