One zip, no surprises, and a conformance report on every download
EngagedLab builds SCORM 1.2 and SCORM 2004 4th Edition packages. Every claim below is rendered from the export registry in the codebase, and each one names the check that keeps it honest.
The standards we build
Two, because there are two manifest builders. A tile you can click for an edition nobody builds is worse than no tile.
SCORM 1.2
- Score model:
- cmi.core.score.raw (0-100) + lesson_status
- Suspend budget:
- 4,096 characters
- Recommended for:
- Maximum compatibility - every mainstream LMS since 2001.
SCORM 2004 4th Edition
- Score model:
- cmi.score.scaled + completion_status + success_status
- Suspend budget:
- 64,000 characters
- Recommended for:
- Richer tracking on modern LMSes - larger resume state, separate completion and success.
What this does not do
What holds for every package we build
These are guarantees rather than options: they are true of the bytes, and each names the executable check that asserts it.
Self-contained by default
One zip, zero external requests - no CDNs, no fonts, no calls home. Runs on locked-down LMS servers and in offline pilots. Switch evidence return on and the package contacts exactly one address, this deployment's own, which the dialog prints in full before you download; the export refuses to build if the package would reach anything else.
Asserted by: scorm-package.test.ts · "OFFLINE CLAIM: index.html contains zero http(s) URLs - no CDNs, fonts, or telemetry" · "no direct LRS sender survives in the built package" · export-switch.test.ts · "builds a package with no telemetry whatsoever - absence, not a flag" · "refuses to hand over a package that would contact anything undeclared" · ws-h1-export-parity.test.ts · "passes the conformance gate it advertises, including no-undeclared-sender" · "no-undeclared-sender FAILS when a second global appears in the shell"
Resume where they left off
Progress, XP and position persist in the LMS's own suspend data, within each standard's byte budget - learners pick up mid-lab.
Asserted by: scorm-package.test.ts · "runtime ships as a minified IIFE with the SCORM adapter and suspend budget" - both budget constants asserted present in the built bundle
Per-question reporting
Every answered interaction is journalled to cmi.interactions - instructors see per-question results and response times in their gradebook, not just one number.
Asserted by: export-switch.test.ts · "the built package journals to the LMS's own cmi records" · new-blocks-export.test.ts · "interaction type mapping" - every block type maps to a cmi interaction type
Outcome-shaped in the gradebook
The lab's stated objectives ship as cmi.objectives in both dialects, and every interaction declares the objectives it evidences - so the customer's own gradebook reports against outcomes, not just against questions. SCORM 2004 packages additionally declare them in the manifest's imsss sequencing block.
Asserted by: scorm-telemetry.test.ts · "both manifests declare the lab's objectives, by each dialect's own mechanism" · "the runtime spells an objective id exactly as the manifest declares it"
Works without an LMS too
No SCORM API found? The runtime falls back to browser storage - the same package doubles as a standalone web lab.
Asserted by: scorm-package.test.ts · "DUAL ADAPTER: index.html ships both SCORM API literals under both standards" · export-switch.test.ts · "the built package journals to the LMS's own cmi records" - the localStorage fallback is asserted present in the built bundle
The one thing you can switch on
Off until an educator deliberately turns it on, for that download, having read what it sends.
Evidence returns from the LMS
Attempts made inside your LMS batch back to EngagedLab, so the cohort report, the insights dashboard and the UK evidence artefact describe LMS deliveries as well as hosted ones. The LMS keeps its own cmi.interactions record unchanged; a failed send never costs a learner their completion.
Where: Export for your LMS → Evidence return → "Send attempts back to EngagedLab"
What it sends: Each attempt sends: the lab and chunk id, the block type, the objectives it evidences, the attempt number, whether it was correct, the normalised answer (never free text), how long it took, and the hint rung reached. Identity is your LMS's own learner id, hashed with a per-deployment key before it is stored - no name, no email, no cookie, no cross-site identifier.
What this does not do
Import steps, and what has actually been checked
The verified line under each platform says what was executed, never what we would like to imply.
Moodle (scorm12)
- In your course, turn editing on and add an activity → SCORM package.
- Drag the downloaded .zip into the package area.
- Set Grade → Grading method to "Highest attempt", then Save and display.
Verified: CI asserts the manifest's required elements, that every href it references exists in the zip, and that the page makes zero external requests. It is NOT schema-validated against the CAM XSD - we do not ship one and will not claim one. Not executed against a live Moodle by us.
Canvas (scorm12)
- Open your course → Settings → Navigation and enable SCORM.
- Go to SCORM → Upload, choose the .zip, and select "Import as graded assignment".
- Publish the created assignment.
Verified: CI asserts the manifest's required elements, that every href it references exists in the zip, and that the page makes zero external requests. It is NOT schema-validated against the CAM XSD - we do not ship one and will not claim one. Not executed against a live Canvas by us.
Blackboard (scorm12)
- In a content area choose Build Content → Content Package (SCORM).
- Browse to the .zip and submit.
- Enable "Track number of views" and grading if you want scores in the Grade Centre.
Verified: CI asserts the manifest's required elements, that every href it references exists in the zip, and that the page makes zero external requests. It is NOT schema-validated against the CAM XSD - we do not ship one and will not claim one. Not executed against a live Blackboard by us.
Brightspace (D2L) (scorm2004)
- Course Admin → Import/Export/Copy Components → Import Components.
- Upload the .zip and follow the wizard.
- Add the imported package to a module from Existing Activities.
Verified: CI asserts the 4th Edition manifest's required elements and namespaces, that every href it references exists in the zip, and that the page makes zero external requests. It is NOT schema-validated against the CAM XSD - we do not ship one and will not claim one. Not executed against a live Brightspace by us.
SCORM Cloud (scorm2004)
- Library → Add Content → Import a SCORM, AICC, xAPI or cmi5 package.
- Upload the .zip; SCORM Cloud runs its own validation on import.
- Use "Launch" to sandbox-test, or "Dispatch" to deliver into another LMS.
Verified: SCORM Cloud runs its own validation on import, so this is where to prove conformance independently of us.

