test(phase6f): add V1 pilot acceptance suite; fix regression from real curriculum changes

- New platform/test/e2e-phase6f.js (17 tests): V1 manifest/exclusion correctness, the full
  V1 prerequisite graph, ROOT 01-04 re-verification, the orientation module's unlock
  behavior, optional-activity handling, the strengthened Capstone gate in both directions,
  instructor-notes RBAC on locked (not just draft) content, isolation, and an explicit
  age-independence check.
- foundations-helper.js: completeThroughRoot06/completeThroughRoot10 updated for the new
  practice-bank intro-lesson activities; new completeThroughCapstoneEligible() helper
  (ROOT 07-m03/m04 + full ROOT 09 + ROOT 12) shared by e2e-phase6f.js and both new drills.
- e2e-phase6a/6b/6d/6e.js: resume-pointer assertions updated for the new orientation
  module; e2e-phase6a.js's and e2e-phase6b.js's own inline ROOT 06/07/09/10/12 completion
  sequences updated for the new intro-lesson activities and the new root-09 Capstone
  dependency; e2e-phase6b.js's stale ROOT 09 status assertion and its draft-activity test
  (previously targeting the now fully-excluded ROOT 08) corrected.
- test-phase6d/6e-foundations-rehearsal.js: same orientation-module fix applied to the
  real-Lab dress rehearsals.

All of 6A (23/23) / 6B (26/26) / 6C (17/17) / 6D (21/21) / 6E (23/23) / 6F (17/17) verified
green on independent fresh stacks. See 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:21 -05:00
co-authored by Claude Sonnet 5
parent f695b7c95d
commit 2864fe03dc
8 changed files with 397 additions and 22 deletions
@@ -59,9 +59,18 @@ async function main() {
});
await step('resume points at ROOT 01\'s very first activity', async () => {
// Phase 6F added a required orientation module in front of root-01-m01 — see
// docs/PHASE6F_ROOT_V1_PILOT_READINESS.md.
const { body } = await session.request('GET', `/api/student/programs/${enrollmentId}/courses`);
assert.equal(body.resume.course_id, 'root-01-computing-linux-foundations');
assert.equal(body.resume.activity_id, 'root-01-m01-a01-lesson');
assert.equal(body.resume.activity_id, 'root-01-m00-a01-lesson-welcome');
});
await step('student completes the ROOT_ V1 orientation module', async () => {
for (const id of ['root-01-m00-a01-lesson-welcome', 'root-01-m00-a02-lesson-disposable-lab', 'root-01-m00-a03-knowledge-check']) {
const { status } = await session.request('POST', `/api/student/activities/${id}/complete`);
assert.equal(status, 200);
}
});
await step('student reads ROOT 01 module 1\'s lesson and guided exercise', async () => {
@@ -78,6 +78,9 @@ async function main() {
// ── ROOT 01 (already READY since Phase 6D) — complete quickly via real scenario endpoint ──
await step('ROOT 01 completes via the real Lab scenario-validation API', async () => {
// Phase 6F added a required orientation module gating root-01-m01 — see
// docs/PHASE6F_ROOT_V1_PILOT_READINESS.md.
for (const id of ['root-01-m00-a01-lesson-welcome', 'root-01-m00-a02-lesson-disposable-lab', 'root-01-m00-a03-knowledge-check']) await completeActivity(session, id);
for (const suffix of ['a01-lesson', 'a02-guided-exercise']) await completeActivity(session, `root-01-m01-${suffix}`);
await completeScenario(session, 'linux-inspect-hardware', envId);
await completeActivity(session, 'root-01-m01-a04-reflection');