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

142 lines
8.3 KiB
Markdown

# 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).
## Recommended Phase 6E scope
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).