Files
rootnode-academy/docs/PHASE6D_ROOT_FOUNDATIONS.md
T
ced4568andClaude Sonnet 5 b6516a74db docs(phase6d): document the ROOT Foundations milestone
Adds PHASE6D_ROOT_FOUNDATIONS.md (the phase's own record: the generic-scenario-engine finding,
the tested container-runtime decision, what was authored, the bugs found and fixed, and honest
test/regression/rehearsal results) and ROOT_FOUNDATIONS_PILOT_READINESS.md (module-by-module
READY/DEFERRED classification for ROOT 01-04 against the unchanged Phase 6C readiness standard —
ROOT 01 READY, ROOT 02-04 DEFERRED by design).

Adds ROOT_PROGRAM_DURATION_MODEL.md — real per-course instructional-hour totals computed from
actual estimated_duration_minutes values (2,931 minutes / 48.9 hours across all authored
content), not invented, with an explicit note on why instructor-led timing isn't a separate
summable field yet.

Updates ROOT_PROGRAM_ARCHITECTURE.md (ROOT 01's new READY status and the real 01-04 prerequisite
chain), ROOT_PILOT_CURRICULUM.md (ROOT 01 added to the pilot, module-level detail), and
ROOT_CURRICULUM_COVERAGE_MATRIX.md (updated module/scenario totals) to reflect what Phase 6D
actually built, without restating Phase 6C's own Kubernetes-scenario tables.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 13:00:41 -05:00

8.3 KiB

Phase 6D — ROOT_ Systems Foundations

Phase 6D's mission: build the foundational half of ROOT_ (ROOT 01-04) so a student reaches ROOT 05 already fluent in Linux/networking/Git and understanding why Kubernetes exists, using the existing course/module/activity model throughout.

Baseline verification

Confirmed at start: branch main, clean tree, HEAD = origin/main = bd0a10fbfb31b05a6264d083f27d85a6f7d5d50c (the Phase 6C milestone).

The central architectural finding (Section 6/7)

backend/server.js's scenario engine (runCommand()) executes an arbitrary shell command string from a scenario's setup_commands/validation.commands and checks its output — nothing about it is Kubernetes-specific. This means the existing lab activity type and scenarios/data/*.json format already fully support Linux and Git exercises with real, deterministic validation. No shell_lab/git_lab/container_lab activity type was built — the speculative multi-type model the authorization raised as a possibility was unnecessary. See docs/ROOT_FOUNDATIONS_LAB_STRATEGY.md.

Container runtime decision, tested not assumed (Section 10)

Installed Docker Engine (docker.io + a static docker-compose v2 binary) inside the same already-Privileged: true Lab container, alongside k3s. This does not weaken the security boundary — the Lab Host's own Docker socket is never touched; the nested daemon has its own socket inside the guest. Verified empirically against the real production resource caps (2 vCPU, 4096MB, 512 PIDs): k3s + dockerd + a running nginx:alpine container + a real image build together used 884MB/4096MB and 160/512 PIDs, comfortable headroom in all dimensions. Dockerfile and scripts/entrypoint.sh updated accordingly (dockerd starts non-blockingly alongside k3s; a Docker daemon failure never breaks Kubernetes-only Labs).

ROOT 01 — Computing & Linux Foundations: fully authored, READY

6 modules, 35 activities, 29 new content files, 6 new hands-on scenario files (linux-inspect-hardware, linux-shell-basics, linux-filesystem-navigation, linux-files-and-text, linux-process-management, linux-permissions-foundations) plus 2 MCQ scenarios, all using the existing generic scenario/validation engine — no new mechanism. Every lab was tested end-to-end via the real scenario API (setup → solve → validate), including negative tests confirming they correctly FAIL when not actually solved. A new rootnode-linux-foundations-assessment (2 required + 4 random-draw scenarios) uses the existing Phase 3B engine.

ROOT 02-04: architecture designed, content deferred

docs/ROOT_FOUNDATIONS_ARCHITECTURE.md designs all remaining 20 modules (6+6+8) in full — outcomes, activities, and Real Ops connections for each. Given realistic effort constraints, authoring, testing, and verifying ROOT 01 to genuine READY depth was prioritized over shallow architecture-only coverage across all four courses (see docs/ROOT_FOUNDATIONS_PILOT_READINESS.md for the full reasoning). ROOT 02-04 remain honestly status = 'planned' with zero modules — not padded to look further along than they are.

Course prerequisite chain (Section 19)

courses.prerequisites now encodes ROOT 01→02→03→04→05 server-side, verified live: a fresh student sees ROOT 02 correctly LOCKED (ROOT 01 is real, non-empty content) while ROOT 03/04/05 stay unlocked (vacuously satisfied — their own prerequisite courses are still empty). Completing ROOT 01 unlocks ROOT 02 for that student. ROOT 06+ and the Capstone are completely unaffected (re-confirmed via regression). No UI-only hiding — this is a real courses table constraint the existing prerequisitesSatisfied() engine already enforced correctly before this phase; Phase 6D only populated real data into it.

Extension point for placement/override (Section 20)

Documented, not built: courses.prerequisites is a plain array a future placement assessment or instructor override could satisfy without a schema change. No bypass button implemented.

Frontend (Sections 21-23)

No frontend change was needed or made. CourseView.jsx and CurriculumView.jsx already generalized correctly to ROOT 01's activity/status shapes (lesson/demonstration/knowledge_check/ guided_exercise/lab/reflection/assessment, ready/planned status, is_required, instructor_notes) — the same generic rendering already proven for ROOT 05-12 in Phase 6C. Verified by inspection and by the real API responses e2e-phase6d.js and the rehearsal exercise.

New application/platform code and why necessary

  • Dockerfile + scripts/entrypoint.sh: the nested Docker Engine described above — a genuine platform gap (ROOT 04's course design needs it) that the existing content model couldn't satisfy on its own, tested and justified in docs/ROOT_FOUNDATIONS_LAB_STRATEGY.md.
  • No other application code. Every ROOT 01 requirement was satisfiable with the existing course_modules/module_activities/assessment_definitions/scenario-engine model.

Bugs found and fixed

  • An early draft of the real-Lab rehearsal's hardware-report step used a triple-nested JS-template/shell/heredoc string that silently produced a malformed file. Caught by actually running the rehearsal against a real Lab (not assumed to work); fixed by writing the script to a file and docker cp-ing it in rather than an inline heredoc.
  • Phase 6D's own content changes made two hardcoded assumptions in e2e-phase6a.js/ e2e-phase6b.js stale: both suites asserted resume pointed at ROOT 05's gold module as "the first real content," which was true before this phase and is now ROOT 01. Both suites fixed and re-verified green against a fresh stack.

Testing (Section 26)

platform/test/e2e-phase6d.js — 20/20 passing (fresh stack): ROOT 01 hierarchy, ROOT 02-04 honestly empty, activity ordering, lab-cannot-be-manually-completed, full course completion via lesson/lab/assessment, prerequisite chain (both the locked and unlocked directions, on two separate students), existing ROOT 05+ and Capstone state unaffected, is_required rule unaffected, self-paced no-instructor-deferral check, instructor-notes exclusion, RBAC, logout/ login persistence, cross-student isolation, version-bump stability, and content validation.

Real-Lab rehearsal (Section 27)

infra/scripts/drills/test-phase6d-foundations-rehearsal.js — 11/11 passing against a real disposable Lab container (no mocking): login → enroll → resume → lesson/guided-exercise → real Lab launch → real bash hardware inspection (nproc/free/df, written to a real file) → real validation → real permission-denial-then-fix (su - labuser, genuinely denied, then genuinely allowed after chmod 644) → remaining modules → assessment → course completion → ROOT 02 unlock → logout/login persistence → instructor visibility of the resulting state.

Regression (Section 30)

Re-ran 6A (21/21), 6B (24/24), 6C (17/17) fresh, each against its own freshly-reset stack per the established isolation convention — all green after the two resume-point staleness fixes above. 2A/2B/3A/3B/5A/5B/5C were not re-run: git diff for this phase shows no changes to platform/api/src/, gateway, or provisioner code (only the Lab image/entrypoint, migrations, content, scenarios, tests, and docs), so their surface area was untouched. Frontend build: clean (vite build, unchanged this phase). Lab image: rebuilt and standalone-smoke-tested directly (see the container runtime section above) in addition to the full-stack rehearsal.

Content validation

infra/scripts/validate-course-content.js — 0 errors against 17 courses/modules with real content, 201 activities, 106 scenario files (98 + 8 new this phase).

Known limitations / intentionally deferred

  • ROOT 02, 03, 04 course content — architecture designed, not authored.
  • ROOT 04's Docker/Compose hands-on labs specifically — platform extension done and verified, course content not yet written against it.
  • Instructor-led vs. self-paced timing is not a separate database field (see docs/ROOT_PROGRAM_DURATION_MODEL.md).
  • No placement testing or instructor-override UI (explicitly out of scope this phase).

Author ROOT 02 (prioritize the "critical" Networking Mental Model module), then ROOT 03 (Git, using the already-verified local-repo strategy), then ROOT 04 (content only — the runtime is already built and tested).