Adds platform/test/e2e-phase6e.js (23 checks): full ROOT 02/03/04 hierarchy/content/assessment-
pool verification, the complete ROOT 01->02->03->04->05 chain proven on one student (each
course's completion unlocking exactly the next), the direct-API lock bypass proven blocked on
both a Phase 6E course pair and a pre-existing unrelated pair, existing ROOT 06+/Capstone/
is_required behavior confirmed unaffected, self-paced no-instructor-deferral scan,
instructor-notes exclusion, RBAC, persistence, isolation, version stability, content validation.
23/23 pass against both a warm and a freshly-reset stack.
Adds platform/test/foundations-helper.js — a shared completeRootFoundations01Through04/
completeThroughRoot06/completeThroughRoot10 helper, extracted once multiple suites needed the
identical real-completion sequence as test setup, rather than duplicating it four times.
Adds infra/scripts/drills/{run,test}-phase6e-foundations-rehearsal — the real Platform API/
Gateway/Provisioner/disposable-Lab/nested-Docker/Git/k3s dress rehearsal: one real Lab task per
new course (nginx inspection, a real merge conflict, a real container-networking fix) plus the
full chain to a genuine ROOT 05 unlock, with k3s reconfirmed healthy and untouched at the end.
13/13 pass against a real, freshly-built stack.
Fixes the regression fallout from the (correct) course-routes.js lock fix: several earlier
suites' own historical shortcuts had accumulated small ordering/scenario gaps the missing
enforcement had been silently covering for — none were platform bugs. e2e-phase6a/6b/6c/6d.js
now inject the real ROOT 01-04 (and where needed ROOT 05/06/10) completion sequence via
foundations-helper.js before touching ROOT 05+ content; e2e-phase6b.js's bypass-student flow now
completes deployment-rollback/job-task/cronjob-task/container-logging-mcq explicitly (real
scenarios added in later phases that its original ALL_STAGES list never included); e2e-phase6a/
6d.js's own ROOT 01/05 completion tests now complete each module fully (through its lab and
reflection) before moving to the next, since those courses' own modules carry real intra-course
prerequisites. Two now-obsolete Phase-6D-era assertions in e2e-phase6d.js (ROOT 02-04 stay
PLANNED / stay vacuously unlocked) are updated to assert the opposite, with a comment explaining
Phase 6E intentionally changed that fact. All four suites re-verified green fresh.
Also fixes a real, reproducible dash-vs-bash bug caught while testing the new ROOT 01
rehearsal's ordering fix: `&>file` misparses under this image's actual /bin/sh (dash), breaking
a later `$!`-based kill — the rehearsal script now writes multi-line completion loops with
explicit status assertions, matching the discipline the other suites already use.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Adds platform/test/e2e-phase6d.js (20 checks): ROOT 01 hierarchy, ROOT 02-04 honestly empty
(not padded), activity ordering, lab-cannot-be-manually-completed, full course completion via
lesson/lab/assessment, the prerequisite chain proven on two students (one who completed ROOT 01,
one fresh), existing ROOT 05+/Capstone state unaffected, is_required unaffected, self-paced
no-instructor-deferral check, instructor-notes exclusion, RBAC, logout/login persistence,
cross-student isolation, version-bump stability, and content validation. 20/20 pass against both
a warm and a freshly-reset dev stack.
Adds infra/scripts/drills/{run,test}-phase6d-foundations-rehearsal — the real disposable-Lab
dress rehearsal: login -> enroll -> lesson/guided-exercise -> real Lab launch -> real bash
hardware inspection (nproc/free/df, written to a real file) -> real validation -> a genuine
permission denial (a second Linux user actually denied via `su -`) then a real chmod fix ->
remaining modules -> assessment -> course completion -> ROOT 02 unlock -> logout/login
persistence -> instructor visibility of the resulting learning state. 11/11 pass against a real
Lab container, no mocking. (First run caught a real triple-escaping bug in the hardware-report
step's inline heredoc — fixed by writing the script to a file and docker-cp-ing it in instead.)
Fixes two stale hardcoded assumptions in e2e-phase6a.js and e2e-phase6b.js that this phase's own
ROOT 01 addition broke: both suites asserted `resume` landed on ROOT 05's gold module as "the
first real content," which was true before this phase and is now ROOT 01. Both suites' original
intent (resume must never land on a bare-lab bank) is preserved, just against the current front
door. Both suites re-verified green (21/21 and 24/24) against a fresh stack.
Co-Authored-By: Claude Sonnet 5 <[email protected]>