diff --git a/docs/PHASE6D_ROOT_FOUNDATIONS.md b/docs/PHASE6D_ROOT_FOUNDATIONS.md new file mode 100644 index 0000000..a770c28 --- /dev/null +++ b/docs/PHASE6D_ROOT_FOUNDATIONS.md @@ -0,0 +1,141 @@ +# 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). diff --git a/docs/ROOT_CURRICULUM_COVERAGE_MATRIX.md b/docs/ROOT_CURRICULUM_COVERAGE_MATRIX.md index 4568eef..f67f0ba 100644 --- a/docs/ROOT_CURRICULUM_COVERAGE_MATRIX.md +++ b/docs/ROOT_CURRICULUM_COVERAGE_MATRIX.md @@ -7,6 +7,17 @@ for each placement (not coverage-percentage padding). Built from more of demonstration/guided-exercise/reflection), **PLANNED** (structure only, no content), **GAP** (no suitable scenario exists at all). +## Phase 6D addition + +Phase 6D authored ROOT 01 (Computing & Linux Foundations) in full — 6 modules, 35 activities, 6 +new hands-on Linux scenarios plus 2 MCQs, all READY. This is the program's first course outside +the Kubernetes/CKS content this matrix was originally scoped to, so it is documented separately +in `docs/ROOT_FOUNDATIONS_ARCHITECTURE.md` and `docs/PHASE6D_ROOT_FOUNDATIONS.md` rather than +folded into the tables below, which remain the ROOT 05+ (Kubernetes) scenario-coverage record. +Post-Phase-6D totals: **28 modules total across all courses with any content — 22 READY, 6 +PARTIAL** (Phase 6C's 22 modules — 16 READY, 6 PARTIAL — plus 6 new ROOT 01 modules, all READY). +**106 scenario files** (98 + 8 new). + ## Phase 6C verification (superseding Phase 6B's own self-reported counts) Baseline (start of Phase 6C), run directly against the database and filesystem diff --git a/docs/ROOT_FOUNDATIONS_PILOT_READINESS.md b/docs/ROOT_FOUNDATIONS_PILOT_READINESS.md new file mode 100644 index 0000000..a6d0022 --- /dev/null +++ b/docs/ROOT_FOUNDATIONS_PILOT_READINESS.md @@ -0,0 +1,65 @@ +# ROOT Foundations Pilot Readiness — ROOT 01-04 + +Phase 6D §24 — the honest READY/PARTIAL/DEFERRED classification for ROOT 01-04, using the same +bar `docs/ROOT_PILOT_READINESS_STANDARD.md` established in Phase 6C. The standard is not +lowered because these courses are new. + +## ROOT 01 — Computing & Linux Foundations: READY + +All 6 modules meet the 8-point standard: + +| Module | Status | Evidence | +|---|---|---| +| M1 How Computers Run Software | READY | Lesson, guided exercise, real hands-on lab (`linux-inspect-hardware`), reflection. Verified via `e2e-phase6d.js` and the real-Lab rehearsal (`infra/scripts/drills/test-phase6d-foundations-rehearsal.js`). | +| M2 Linux and the Shell | READY | Full gold pattern (lesson/demo/kc/guided/lab/reflection). Lab (`linux-shell-basics`) tested end-to-end via the real scenario-validation API, including a negative test (fails when unsolved). | +| M3 Navigating the Filesystem | READY | Full gold pattern. Lab (`linux-filesystem-navigation`) tested end-to-end. | +| M4 Files and Text | READY | Full gold pattern. Lab (`linux-files-and-text`) tested end-to-end. | +| M5 Processes | READY | Full gold pattern. Lab (`linux-process-management`) tested end-to-end, including a negative test (fails while the process is still running). | +| M6 Users & Permissions Foundations | READY | Full gold pattern. Lab (`linux-permissions-foundations`) tested end-to-end via the real-Lab rehearsal, including a REAL permission denial (a second Linux user genuinely denied read access) before the fix. | + +**Self-paced readiness:** confirmed programmatically — `infra/scripts/validate-course-content.js`'s +deferral-phrase check and `e2e-phase6d.js`'s equivalent live check both scan every ROOT 01 +activity's student-visible content for "ask your instructor" or equivalent and found none. + +**Instructor-led readiness:** every lesson/demonstration/guided_exercise/reflection activity has +a real Instructor Notes section (timing, misconceptions, discussion questions), verified hidden +from students both statically and via a live API check. + +**Assessment:** `rootnode-linux-foundations-assessment` wired and verified live (real draw: 2 +required hands-on tasks + 2 random hands-on tasks + 2 random MCQs, 6 scenarios total). + +## ROOT 02 — Linux Administration & Networking: DEFERRED + +Architecture fully designed in `docs/ROOT_FOUNDATIONS_ARCHITECTURE.md` (6 modules, including the +explicitly "critical" Networking Mental Model module). Zero modules authored this phase — course +remains `status = 'planned'`, honestly, with a real (not fabricated) `prerequisites` gate to +ROOT 01 already in place so the sequence is correct once it IS authored. + +## ROOT 03 — Git & Collaborative Development: DEFERRED + +Architecture designed (6 modules, local-repository-only strategy documented in +`docs/ROOT_FOUNDATIONS_LAB_STRATEGY.md` §4). Zero modules authored this phase. + +## ROOT 04 — Containers & Docker: DEFERRED (content) / PLATFORM EXTENSION DONE + +Architecture designed (8 modules). **The platform extension ROOT 04 needs — a nested Docker +Engine inside the Lab — was built and verified this phase** (`docs/ROOT_FOUNDATIONS_LAB_STRATEGY.md` +§3: real `docker run`, `docker build`, and `docker compose` all tested working inside the actual +`rootnode-academy:test` image under production resource constraints). No course content was +authored against it yet — that's a real, substantial content-authoring effort left for a future +phase, now unblocked by this phase's platform work. + +## Why ROOT 02-04 were not authored this phase + +Given realistic effort constraints in a single phase, authoring, testing, and verifying ROOT 01 +to the same rigor as every ROOT 05+ module (real scenarios, live end-to-end verification, a +real-Lab rehearsal, an assessment) was prioritized over shallow architecture-only coverage +across all four courses. This mirrors Phase 6C's own precedent: some content built to a genuine +READY bar, the rest explicitly and honestly DEFERRED with a real reason, rather than every +course padded to look further along than it is (`e2e-phase6d.js`'s own first test explicitly +asserts ROOT 02-04 have zero modules, catching any future accidental over-claim). + +## Honest totals + +**READY: 1 course (ROOT 01), 6 modules. DEFERRED: 3 courses (ROOT 02-04), 0 modules — by +design, not oversight.** diff --git a/docs/ROOT_PILOT_CURRICULUM.md b/docs/ROOT_PILOT_CURRICULUM.md index 184e59e..bfe9d12 100644 --- a/docs/ROOT_PILOT_CURRICULUM.md +++ b/docs/ROOT_PILOT_CURRICULUM.md @@ -21,10 +21,10 @@ future phase pending an authored teaching layer for each. See Section 16 discuss | Course | Pilot status | Notes | |---|---|---| -| ROOT 01 Computing & Linux Foundations | **NOT IN PILOT** | Never authored (status `planned`, zero modules). Out of Phase 6C's scope; students are assumed to arrive with basic Linux/CLI comfort for this pilot. | -| ROOT 02 Linux Administration & Networking | **NOT IN PILOT** | Same as above. | -| ROOT 03 Git & Collaborative Development | **NOT IN PILOT** | Same as above. | -| ROOT 04 Containers & Docker | **NOT IN PILOT** | Same as above. | +| ROOT 01 Computing & Linux Foundations | **IN PILOT** (added Phase 6D) | Fully authored, READY — 6 modules, real hands-on Linux Labs, a wired assessment. See `docs/PHASE6D_ROOT_FOUNDATIONS.md`. | +| ROOT 02 Linux Administration & Networking | **NOT IN PILOT** | Architecture designed (`docs/ROOT_FOUNDATIONS_ARCHITECTURE.md`), content not yet authored. | +| ROOT 03 Git & Collaborative Development | **NOT IN PILOT** | Architecture designed, content not yet authored. | +| ROOT 04 Containers & Docker | **NOT IN PILOT** | Architecture designed; its platform extension (nested Docker Engine) is built and tested, content not yet authored. | | ROOT 05 Kubernetes Foundations | **IN PILOT** | See modules below. | | ROOT 06 Kubernetes Application Workloads | **IN PILOT** | See modules below. | | ROOT 07 Kubernetes Networking & Configuration | **IN PILOT** | See modules below. | @@ -37,6 +37,16 @@ future phase pending an authored teaching layer for each. See Section 16 discuss ## Module-level detail (courses IN pilot only) +### ROOT 01 — Computing & Linux Foundations (added Phase 6D) +| Module | Status | Prerequisite | Outcome | Delivery | Required/Optional | Labs/Assessment | +|---|---|---|---|---|---|---| +| root-01-m01-how-computers-run-software | READY | none (program entry point) | Explain the hardware/kernel/application layering; inspect a real machine's resources | Self-paced or instructor-led | 4 required | 1 lab | +| root-01-m02-linux-and-the-shell | READY | m01 | Read exit codes; use tab completion/history/man pages | Self-paced or instructor-led | 6 required | 1 lab | +| root-01-m03-navigating-the-filesystem | READY | m02 | Navigate absolute/relative paths; explain top-level directories | Self-paced or instructor-led | 6 required | 1 lab | +| root-01-m04-files-and-text | READY | m03 | Manipulate files; filter text with grep/pipes/redirection | Self-paced or instructor-led | 6 required | 1 lab | +| root-01-m05-processes | READY | m04 | Inspect and correctly terminate a real process | Self-paced or instructor-led | 6 required | 1 lab | +| root-01-m06-users-and-permissions-foundations | READY | m05 | Apply rwx permissions and the least-privilege principle | Self-paced or instructor-led | 7 required | 1 lab + **ROOT 01 Linux Foundations Assessment** (6-scenario timed exam) | + ### ROOT 05 — Kubernetes Foundations | Module | Status | Prerequisite | Outcome | Delivery | Required/Optional | Labs/Assessment | |---|---|---|---|---|---|---| @@ -99,7 +109,8 @@ instructor-only prep material was created outside the per-activity Instructor No ## What is intentionally NOT in the first pilot -- ROOT 01-04 (never authored). +- ROOT 02-04 (architecture designed in Phase 6D, content not yet authored — ROOT 01 IS now in + the pilot, added Phase 6D). - ROOT 08 Kubernetes Storage & Scheduling (non-capstone-gating; both modules remain PARTIAL). - ROOT 11 modules 2-7 (GitOps, CI/CD, IaC, hands-on Observability, hands-on Reliability) — see scope doc. @@ -112,7 +123,8 @@ instructor-only prep material was created outside the per-activity Instructor No ## Bottom line -Every module the pilot's required completion path depends on (ROOT 05-07, 09-10, 12, Capstone) -meets the READY bar for instructor-led delivery. Three specific modules run instructor-led only -this pilot. ROOT 08 and most of ROOT 11 are explicitly out of the required path. Given that -scope, the pilot curriculum, delivered instructor-led, is ready. +Every module the pilot's required completion path depends on (ROOT 01, 05-07, 09-10, 12, +Capstone) meets the READY bar for instructor-led delivery, and ROOT 01's self-paced readiness +was verified explicitly (see `docs/PHASE6D_ROOT_FOUNDATIONS.md`). Three specific modules run +instructor-led only this pilot. ROOT 02-04, ROOT 08, and most of ROOT 11 are explicitly out of +the required path. Given that scope, the pilot curriculum, delivered instructor-led, is ready. diff --git a/docs/ROOT_PROGRAM_ARCHITECTURE.md b/docs/ROOT_PROGRAM_ARCHITECTURE.md index 6d41394..08d91f3 100644 --- a/docs/ROOT_PROGRAM_ARCHITECTURE.md +++ b/docs/ROOT_PROGRAM_ARCHITECTURE.md @@ -14,14 +14,21 @@ here is grounded in `docs/ROOT_CURRICULUM_INVENTORY.md`, not aspirational. 6 courses gained new teaching modules — the module-level detail and evidence for every new placement lives in `docs/ROOT_CURRICULUM_COVERAGE_MATRIX.md`, not duplicated here. +**Updated for Phase 6D** (`platform/api/migrations/025_phase6d_root_foundations_root01.sql`, +`docs/PHASE6D_ROOT_FOUNDATIONS.md`): ROOT 01 fully authored and moved to READY — see +`docs/ROOT_FOUNDATIONS_ARCHITECTURE.md` for its module-level design and +`docs/ROOT_FOUNDATIONS_LAB_STRATEGY.md` for why no new activity type was needed. ROOT 02-04 +remain PLANNED (architecture designed, content not yet authored) but now carry a real +prerequisite chain (01→02→03→04→05) enforced server-side. + ## Course sequence | # | Course | Status | Why | |---|---|---|---| -| 1 | Computing & Linux Foundations | **PLANNED** | No lab content exists in this repository — every scenario is Kubernetes/CKS. | -| 2 | Linux Administration & Networking | **PLANNED** | Same — no Linux-admin scenario content exists. | -| 3 | Git & Collaborative Development | **PLANNED** | No Git scenario content exists. | -| 4 | Containers & Docker | **PLANNED** | No Docker-specific scenario content exists (the Lab itself runs k3s, but no student-facing "learn Docker" scenarios exist). | +| 1 | Computing & Linux Foundations | **READY** | Phase 6D: 6 modules, real Linux/shell scenarios using the existing generic scenario engine, a wired assessment — see `docs/PHASE6D_ROOT_FOUNDATIONS.md`. | +| 2 | Linux Administration & Networking | **PLANNED** | Architecture designed (`docs/ROOT_FOUNDATIONS_ARCHITECTURE.md`); content not yet authored. Real prerequisite: ROOT 01 complete. | +| 3 | Git & Collaborative Development | **PLANNED** | Architecture designed; content not yet authored. Real prerequisite: ROOT 02 complete. | +| 4 | Containers & Docker | **PLANNED** | Architecture designed; the nested-Docker-Engine platform extension it needs was built and verified this phase (`docs/ROOT_FOUNDATIONS_LAB_STRATEGY.md` §3), course content not yet authored. Real prerequisite: ROOT 03 complete. | | 5 | Kubernetes Foundations | **PARTIAL** | Phase 6B added a READY front-door module (`root-05-m00-kubernetes-mental-model` — full lesson/demo/knowledge-check/guided-exercise/lab/reflection) sequenced before the existing 20-scenario bare-lab bank (`root-05-m01`), which now sits behind it. | | 6 | Kubernetes Application Workloads | **PARTIAL** | Phase 6B added a READY `root-06-m02-deployments-scaling-updates` and a PARTIAL `root-06-m03-jobs-cronjobs-daemonsets`, both in front of the existing bare-lab bank. | | 7 | Kubernetes Networking & Configuration | **PARTIAL** | Phase 6B added a READY `root-07-m03-services-and-service-discovery` and a PARTIAL `root-07-m04-ingress-networkpolicy-foundations`. The existing configuration bank (`root-07-m02`) still has no authored teaching content — an honest, documented gap. | @@ -60,10 +67,13 @@ one complete module (the gold standard) as the authoring template, not a finishe CAPSTONE — Operate & Recover ``` -01-04 have no prerequisite chain enforced against each other yet (all PLANNED, zero content — -locking a PLANNED course behind another PLANNED course would just be decorative). 05 is the -first course with a real prerequisite gate. See `docs/COURSE_CONTENT_MODEL.md`'s "prerequisite/ -locking rule" for why a PLANNED/content-free prerequisite never actually blocks anything. +**Updated for Phase 6D:** 01→02→03→04→05 is now a real, server-side prerequisite chain +(`courses.prerequisites`). Since ROOT 01 is now real content and 02-04 remain PLANNED, ROOT 02 +is the first course this chain actually locks (behind ROOT 01); 03/04/05 stay vacuously +satisfied until their own prerequisite course is authored — see +`docs/COURSE_CONTENT_MODEL.md`'s "prerequisite/locking rule" for why a PLANNED/content-free +prerequisite never actually blocks anything, and `docs/PHASE6D_ROOT_FOUNDATIONS.md` for the live +verification of this behavior on both a completed and a fresh student. ## Deviations from the spec's suggested sequence, and why diff --git a/docs/ROOT_PROGRAM_DURATION_MODEL.md b/docs/ROOT_PROGRAM_DURATION_MODEL.md new file mode 100644 index 0000000..8ac3500 --- /dev/null +++ b/docs/ROOT_PROGRAM_DURATION_MODEL.md @@ -0,0 +1,60 @@ +# ROOT_ Program Duration Model + +Phase 6D §25 — the actual instructional-hour estimate, computed by summing real +`module_activities.estimated_duration_minutes` values from the live database, not invented or +marketed backward from a target number. Run: `SELECT c.course_id, SUM(a.estimated_duration_minutes) ... +GROUP BY c.course_id` against the current schema. + +## Per-course totals (self-paced estimate) + +| Course | Activities | Minutes | Hours | +|---|---|---|---| +| ROOT 01 Computing & Linux Foundations | 35 | 338 | 5.6 | +| ROOT 02 Linux Administration & Networking | 0 | 0 | 0 (not yet authored) | +| ROOT 03 Git & Collaborative Development | 0 | 0 | 0 (not yet authored) | +| ROOT 04 Containers & Docker | 0 | 0 | 0 (not yet authored) | +| ROOT 05 Kubernetes Foundations | 28 | 403 | 6.7 | +| ROOT 06 Kubernetes Application Workloads | 22 | 295 | 4.9 | +| ROOT 07 Kubernetes Networking & Configuration | 27 | 353 | 5.9 | +| ROOT 08 Kubernetes Storage & Scheduling | 15 | 250 | 4.2 | +| ROOT 09 Kubernetes Security | 40 | 745 | 12.4 | +| ROOT 10 Kubernetes Troubleshooting & Observability | 20 | 277 | 4.6 | +| ROOT 11 DevOps & Platform Engineering | 3 | 35 | 0.6 | +| ROOT 12 Real Ops | 6 | 115 | 1.9 | +| ROOT Capstone | 5 | 120 | 2.0 | +| **Total (all authored content)** | **201** | **2,931** | **48.9** | + +## Self-paced vs. instructor-led + +The figures above are self-paced estimates — the sum of each activity's own +`estimated_duration_minutes`, which is how long a student working alone is expected to need for +that specific lesson/lab/reflection. This is the one number this phase can honestly derive +programmatically. + +**Instructor-led classroom time is NOT separately tracked as a distinct database field** — every +Instructor Notes section already documents approximate live-facilitation timing in prose (e.g. +"10 minutes live discussion; 8 minutes self-paced writing"), but these are per-activity +estimates embedded in Markdown, not a summable column. A future phase could add a distinct +`estimated_duration_minutes_instructor_led` column if precise classroom scheduling becomes a +real, measured need — this phase does not invent that precision now. As a conservative +approximation: instructor-led delivery of the currently-authored curriculum runs roughly the +same total or somewhat longer than the self-paced figure above, once live discussion and +demonstration time (documented per-activity) is added — do not treat 48.9 hours as a hard +classroom-scheduling number without reading the relevant Instructor Notes first. + +## What this is NOT + +Not a marketing duration, not a promise, not a certification-hours figure. `estimated_duration_minutes` +values were themselves authored as honest guesses (see `docs/COURSE_AUTHORING_STANDARD.md` §4) +— this total will get more accurate as real completion-time data accumulates from actual +students, not before. + +## Once ROOT 02-04 are authored + +The foundational half of ROOT_ (01-04) is planned at ~6 modules each (see +`docs/ROOT_FOUNDATIONS_ARCHITECTURE.md`) — ROOT 01's actual authored total (5.6 hours across 6 +modules) is the only real data point so far; ROOT 02-04 should be expected to land in a similar +5-7 hour range each once authored, giving a rough eventual ROOT 01-04 total near 20-25 hours, +and a full ROOT_ program total near 65-75 hours — stated here as a planning estimate, explicitly +not yet real data, and should be replaced with the real computed total once those three courses +are actually built.