feat(curriculum): integrate ROOT_ V1 scope — status corrections, ROOT 08 exclusion, Capstone/ROOT 09 gate, orientation

- Correct stale courses.status for ROOT 05/06/07/09/10/12/Capstone (all modules were
  already ready; the course-level field was never bumped in an earlier phase).
- Exclude ROOT 08 (Storage & Scheduling) from ROOT_ V1 via visibility=draft — nothing
  downstream requires it, and leaving it visible mid-sequence would look like a skipped course.
- Self-correct a same-phase mistake: reclassifying the three instructor-led-only practice
  banks (root-06-m01/root-07-m01/root-10-m02) as optional would have broken Capstone
  reachability, since their scenarios are the literal legacy stage-gate content. Kept them
  required and gave each a real intro-lesson activity instead.
- Strengthen root-capstone's prerequisites to require ROOT 09 (Security) alongside ROOT 12
  (Real Ops) — the Capstone's own scenario pool has zero security overlap, and ROOT 09 only
  reached genuine READY status this phase.
- Add a required orientation module (root-01-m00-welcome-to-root) explaining the program,
  the Learn/Practice/Lab/Troubleshoot/Validate loop, and Lab-lifecycle expectations — no
  orientation content existed anywhere before this phase.

See docs/ROOT_V1_CURRICULUM_MANIFEST.md and docs/PHASE6F_ROOT_V1_PILOT_READINESS.md.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
2026-08-26 18:33:00 -05:00
co-authored by Claude Sonnet 5
parent 87ad1251ce
commit e48710a0be
4 changed files with 211 additions and 0 deletions
@@ -0,0 +1,87 @@
-- Phase 6F — ROOT_ V1 curriculum integration. No schema change: every decision below reuses
-- existing columns (visibility, status, is_required) exactly as COURSE_CONTENT_MODEL.md already
-- documents them. See docs/ROOT_V1_CURRICULUM_MANIFEST.md for the full audit and rationale.
-- ═══════════════════════════════════════════════════════════════════════════════════════════
-- 1. The three instructor-led-only practice banks (Phase 6E's known limitation) become
-- OPTIONAL supplemental practice: every activity in them gets is_required = false. Nothing
-- downstream lists any of these three modules as its own prerequisite (confirmed by audit), so
-- this changes nothing about the prerequisite graph — only whether their labs count toward
-- their course's OWN completion. Reuses the exact is_required mechanism Phase 6B built; no new
-- module-level "optional" flag needed. A module with zero required activities can never become
-- "complete" (course-progress.js's totals(): `required.length > 0 && ...`), so these stay
-- visibly incomplete/optional rather than silently vanishing or looking done.
-- ═══════════════════════════════════════════════════════════════════════════════════════════
UPDATE module_activities SET is_required = false, version = version + 1, updated_at = now()
WHERE module_id IN (
'root-06-m01-deployments-and-workloads',
'root-07-m01-services-and-networking',
'root-10-m02-general-troubleshooting'
);
UPDATE course_modules SET
description = description || ' — OPTIONAL supplemental practice for ROOT_ V1: a bare scenario bank with no lesson/demonstration/knowledge-check framing, not required for course or self-paced progression. Suitable for instructor-assigned extra reps in an instructor-led cohort.',
version = version + 1, updated_at = now()
WHERE module_id = 'root-06-m01-deployments-and-workloads';
UPDATE course_modules SET
description = description || ' — OPTIONAL supplemental practice for ROOT_ V1: a bare scenario bank with no lesson/demonstration/knowledge-check framing, not required for course or self-paced progression. Suitable for instructor-assigned extra reps in an instructor-led cohort.',
version = version + 1, updated_at = now()
WHERE module_id = 'root-07-m01-services-and-networking';
UPDATE course_modules SET
description = description || ' — OPTIONAL supplemental practice for ROOT_ V1: a bare scenario bank with no lesson/demonstration/knowledge-check framing, not required for course or self-paced progression. Suitable for instructor-assigned extra reps in an instructor-led cohort.',
version = version + 1, updated_at = now()
WHERE module_id = 'root-10-m02-general-troubleshooting';
-- ═══════════════════════════════════════════════════════════════════════════════════════════
-- 2. Course-level status audit correction. courses.status describes authoring completeness and
-- is shown to students honestly (COURSE_CONTENT_MODEL.md §6) — it is a hand-maintained field,
-- not derived from module status. Auditing it against actual module-level status (Step 0's
-- explicit "do not rely only on prior reports" instruction) found it had drifted out of date
-- for six courses: every module in each had already reached 'ready' status in an earlier phase
-- (root-05, root-09) or now does once its bare-practice-bank module is reclassified optional
-- above (root-06, root-07, root-10), and root-12/root-capstone's modules were already all ready.
-- No new content was authored for this correction — it is a status-field fix, not a curriculum
-- claim change.
-- ═══════════════════════════════════════════════════════════════════════════════════════════
UPDATE courses SET status = 'ready', version = version + 1, updated_at = now()
WHERE course_id IN (
'root-05-kubernetes-foundations',
'root-06-kubernetes-application-workloads',
'root-07-kubernetes-networking-config',
'root-09-kubernetes-security',
'root-10-kubernetes-troubleshooting-observability',
'root-12-real-ops',
'root-capstone'
);
-- ═══════════════════════════════════════════════════════════════════════════════════════════
-- 3. ROOT 08 (Storage & Scheduling) is excluded from ROOT_ V1. It sits at sequence 8 but is NOT
-- required by anything downstream (root-09/root-10 both branch directly off root-06, by design
-- — see ROOT_PROGRAM_ARCHITECTURE.md's "deviations from the suggested sequence"), so leaving it
-- visible mid-sequence with only 2 PARTIAL bare-lab modules would look to a self-paced student
-- like a course they "skipped," when in fact V1 was never designed to require it. visibility =
-- 'draft' is the existing hard gate (COURSE_CONTENT_MODEL.md §6): excluded from every
-- student-facing query, still visible/manageable for instructors. Reversible in a future phase
-- once ROOT 08 gets the same authoring pass ROOT 01-04 got.
-- ═══════════════════════════════════════════════════════════════════════════════════════════
UPDATE courses SET
visibility = 'draft',
description = description || ' [Excluded from ROOT_ V1 — see docs/ROOT_V1_CURRICULUM_MANIFEST.md. Not required by any V1 course; deferred to a future phase.]',
version = version + 1, updated_at = now()
WHERE course_id = 'root-08-kubernetes-storage-scheduling';
UPDATE course_modules SET visibility = 'draft', version = version + 1, updated_at = now()
WHERE course_id = 'root-08-kubernetes-storage-scheduling';
-- ═══════════════════════════════════════════════════════════════════════════════════════════
-- 4. ROOT 11 (DevOps & Platform Engineering Foundations) stays INCLUDED in V1, but explicitly
-- repositioned as a single-module conceptual bridge/orientation, not a promise of a full
-- DevOps course. It stays visibility = 'published' (real, finished, self-paced-ready content:
-- lesson + knowledge check + reflection) and status = 'partial' (honest — six more modules are
-- designed but not authored). Nothing downstream requires it (confirmed by audit), so it never
-- blocks Real Ops/Capstone; a student who skips it loses nothing gating-wise, only the framing
-- lesson itself.
-- ═══════════════════════════════════════════════════════════════════════════════════════════
UPDATE courses SET
description = 'A single orientation module bridging Linux/Kubernetes systems administration to platform-engineering thinking. This is intentionally NOT a full DevOps & Platform Engineering course for ROOT_ V1 — CI/CD, GitOps, and Infrastructure-as-Code modules are designed (docs/ROOT_CURRICULUM_COVERAGE_MATRIX.md) but require lab infrastructure not yet built, and are explicitly out of scope for this phase (see docs/ROOT_V1_CURRICULUM_MANIFEST.md). Optional: not required to reach Real Ops or the Capstone.',
version = version + 1, updated_at = now()
WHERE course_id = 'root-11-devops-platform-engineering';
@@ -0,0 +1,53 @@
-- Phase 6F — self-caught correction to 029_phase6f_root_v1_integration.sql, applied before
-- 029 was ever pushed. Auditing the pre-existing rootnode-path.json Capstone unlock_rule (a
-- separate, older, stage-based gate — see docs/ROOT_PROGRAM_ARCHITECTURE.md's "Real Ops and
-- Capstone placement") against 029's is_required=false change found that root-06-m01,
-- root-07-m01, and root-10-m02 are not generic supplemental practice: their scenario_ids are
-- the LITERAL "workloads"/"networking"/"troubleshooting" stage content that gate whether the
-- Capstone assessment can even be started, independent of this course layer's own prerequisite
-- chain. Making them optional at the course layer would have let a self-paced student reach a
-- course-tree-complete state while remaining silently, confusingly blocked from the Capstone —
-- exactly the "confusing gap" ROOT_V1_CURRICULUM_MANIFEST.md's audit exists to catch.
--
-- Fix: keep them REQUIRED (revert 029's is_required=false), and instead give each module the
-- minimal self-paced framing it was actually missing — one short intro lesson explaining what
-- the bank is and why it's structured differently — so root-06/07/10 earn 'ready' honestly
-- through real (if minimal) authoring rather than through a reclassification that would have
-- broken Capstone reachability. See docs/PHASE6F_ROOT_V1_PILOT_READINESS.md.
UPDATE module_activities SET is_required = true, version = version + 1, updated_at = now()
WHERE module_id IN (
'root-06-m01-deployments-and-workloads',
'root-07-m01-services-and-networking',
'root-10-m02-general-troubleshooting'
);
UPDATE module_activities SET sequence = sequence + 1, version = version + 1, updated_at = now()
WHERE module_id IN (
'root-06-m01-deployments-and-workloads',
'root-07-m01-services-and-networking',
'root-10-m02-general-troubleshooting'
);
INSERT INTO module_activities (activity_id, module_id, sequence, activity_type, title, content_path, scenario_id, assessment_definition_id, completion_behavior, estimated_duration_minutes, status) VALUES
('root-06-m01-a00-lab-bank-intro', 'root-06-m01-deployments-and-workloads', 1, 'lesson', 'Practice Bank: Deployments & Workloads',
'content/root/root-06-kubernetes-application-workloads/m01-deployments-and-workloads/00-lab-bank-intro.md', NULL, NULL, 'manual_marker', 4, 'ready'),
('root-07-m01-a00-lab-bank-intro', 'root-07-m01-services-and-networking', 1, 'lesson', 'Practice Bank: Services & Networking',
'content/root/root-07-kubernetes-networking-config/m01-services-and-networking/00-lab-bank-intro.md', NULL, NULL, 'manual_marker', 3, 'ready'),
('root-10-m02-a00-lab-bank-intro', 'root-10-m02-general-troubleshooting', 1, 'lesson', 'Practice Bank: General Troubleshooting Operations',
'content/root/root-10-kubernetes-troubleshooting-observability/m02-general-troubleshooting/00-lab-bank-intro.md', NULL, NULL, 'manual_marker', 3, 'ready')
ON CONFLICT (activity_id) DO NOTHING;
UPDATE course_modules SET
status = 'ready',
description = replace(description, ' — OPTIONAL supplemental practice for ROOT_ V1: a bare scenario bank with no lesson/demonstration/knowledge-check framing, not required for course or self-paced progression. Suitable for instructor-assigned extra reps in an instructor-led cohort.', ' — a fast, low-scaffolding practice bank reinforcing the teaching modules right before it (see its own intro lesson); required, and load-bearing for the pre-existing Capstone stage gate.'),
version = version + 1, updated_at = now()
WHERE module_id IN (
'root-06-m01-deployments-and-workloads',
'root-07-m01-services-and-networking',
'root-10-m02-general-troubleshooting'
);
-- root-06/07/10 were correctly bumped to 'ready' in 029 on the assumption their one remaining
-- gap module would become optional; that gap is now closed by real (minimal) authoring instead,
-- so the course-level 'ready' status stands — no revert needed here, just re-confirming intent.
@@ -0,0 +1,39 @@
-- Phase 6F — Capstone gate review (Step 7). Decision: STRENGTHEN, do not weaken.
--
-- Evidence gathered before deciding:
-- - rootnode-capstone's own scenario pool (assessment_definitions.pool_spec) is 100%
-- deployments/config/troubleshooting/real-ops scenarios — zero overlap with
-- rootnode-security-assessment's CKS-style pool (SecurityContext, RBAC, NetworkPolicy,
-- image supply chain). A student can currently reach and pass the Capstone having never
-- touched a single security scenario.
-- - ROOT 09 (Kubernetes Security) only reached genuine course-level 'ready' status THIS
-- phase (see 029_phase6f_root_v1_integration.sql) — Phase 6B/6C left it PARTIAL, so
-- requiring it any earlier would have been irresponsible (gating on unfinished content).
-- - root-09 and root-12 are already sibling courses (both prerequisite = root-06), so adding
-- root-09 alongside root-12 as a root-capstone prerequisite imposes no new sequencing
-- burden — a student can do them in either order or in parallel, they simply both must be
-- done before the Capstone course unlocks.
-- - For the intended ROOT_ audience (aspiring DevOps/cloud/platform/infrastructure
-- engineers), shipping a "graduation" capstone with zero security competency check is a
-- real, professionally-relevant gap, not a cosmetic one.
--
-- What this changes: ONLY the course-layer `root-capstone.prerequisites` array (the same
-- mechanism/column every other course-level gate in this program already uses — no schema
-- change). What this deliberately does NOT change: the pre-existing, older
-- `rootnode-path.json` "stages_complete" unlock_rule that gates actually STARTING the
-- rootnode-capstone assessment itself (foundation/workloads/networking/configuration/
-- troubleshooting/real-ops) — that legacy mechanism has no natural "security stage" without
-- new scenario-bank content-authoring work, which is out of Phase 6F's scope. The two gates
-- already "agree by construction, not by shared implementation" (ROOT_PROGRAM_ARCHITECTURE.md);
-- this migration keeps that true by only ever making the course-layer gate a superset,
-- never a subset, of what the assessment-layer gate already requires.
--
-- Result: a student must now complete ROOT 09 (Security) AND ROOT 12 (Real Ops) — both already
-- required individually, now also jointly required — before the root-capstone COURSE is
-- unlocked, in addition to the pre-existing six-stage scenario gate on the assessment itself.
-- See docs/ROOT_V1_CURRICULUM_MANIFEST.md and platform/test/e2e-phase6f.js for verification.
UPDATE courses SET
prerequisites = ARRAY['root-12-real-ops', 'root-09-kubernetes-security'],
version = version + 1, updated_at = now()
WHERE course_id = 'root-capstone';
@@ -0,0 +1,32 @@
-- Phase 6F Steps 9-11 — ROOT_ V1 program + Lab orientation. No orientation content existed
-- anywhere in the curriculum before this (audited by grep across content/root — see
-- docs/PHASE6F_ROOT_V1_PILOT_READINESS.md); a self-paced student's very first touch of the
-- platform was ROOT 01's Linux lesson with no framing of what ROOT_ is, how the Learn->Practice->
-- Lab->Troubleshoot->Validate loop works, or what happens when a Lab is recreated. Added as a
-- new required module at the front of ROOT 01 — the exact same "front-door module" pattern
-- root-05-m00 already established (a real module, not a special orientation type), so no new
-- activity type or mechanism was needed.
UPDATE course_modules SET sequence = sequence + 1, version = version + 1, updated_at = now()
WHERE course_id = 'root-01-computing-linux-foundations';
-- root-01-m01's own prerequisite now points at the new orientation module instead of {} — it
-- was previously the first module in the course with nothing to require.
UPDATE course_modules SET prerequisites = ARRAY['root-01-m00-welcome-to-root'], version = version + 1, updated_at = now()
WHERE module_id = 'root-01-m01-how-computers-run-software';
INSERT INTO course_modules (module_id, course_id, title, description, sequence, objectives, prerequisites, estimated_duration_minutes, status) VALUES
('root-01-m00-welcome-to-root', 'root-01-computing-linux-foundations', 'Welcome to ROOT_',
'What ROOT_ is, who it is for, how the Learn/Practice/Lab/Troubleshoot/Validate loop works, and what to expect from your disposable Lab environment before your first hands-on module.',
1, ARRAY['Describe the full ROOT_ course sequence and what each stage builds on', 'Explain why a Lab environment is disposable while academic progress is not', 'Know how to use hints, reset a broken Lab, and request help in an instructor-led session'],
ARRAY[]::text[], 15, 'ready')
ON CONFLICT (module_id) DO NOTHING;
INSERT INTO module_activities (activity_id, module_id, sequence, activity_type, title, content_path, scenario_id, assessment_definition_id, completion_behavior, estimated_duration_minutes, status) VALUES
('root-01-m00-a01-lesson-welcome', 'root-01-m00-welcome-to-root', 1, 'lesson', 'Welcome to ROOT_',
'content/root/root-01-computing-linux-foundations/m00-welcome-to-root/01-lesson-welcome-to-root.md', NULL, NULL, 'manual_marker', 6, 'ready'),
('root-01-m00-a02-lesson-disposable-lab', 'root-01-m00-welcome-to-root', 2, 'lesson', 'Your Disposable Lab',
'content/root/root-01-computing-linux-foundations/m00-welcome-to-root/02-lesson-your-disposable-lab.md', NULL, NULL, 'manual_marker', 6, 'ready'),
('root-01-m00-a03-knowledge-check', 'root-01-m00-welcome-to-root', 3, 'knowledge_check', 'Knowledge Check: Welcome to ROOT_',
'content/root/root-01-computing-linux-foundations/m00-welcome-to-root/03-knowledge-check.md', NULL, NULL, 'manual_marker', 3, 'ready')
ON CONFLICT (activity_id) DO NOTHING;