How one freeze bug became a build pipeline

Stack: SCORM 1.2, Storyline 360, Moodle, Node, FFmpeg, whisper.cpp

Where it started

The freeze bug was in 04_freeze_bug.md. Twenty minutes of diagnosis once we had an LMSSetValue trace; weeks before anyone thought to add the trace. The fix shipped. Two weeks later the same shape of bug showed up in a different module — different root cause, same "the LMS is being weird" first read, same disproportionate effort to find it.

That second incident was the one that changed how I work. The fix was easy. The disproportion was the problem. We had a CMS team that could read a stack trace in production and a SCORM team that couldn't, because the SCORM toolchain ended at "publish from Storyline and upload to Moodle."

The rest of this is what I built to close that gap.

What was actually missing

I listed the recurring sources of "we're flying blind" pain over six months of postmortems. The list was longer than I expected and shorter than I feared.

  1. No static checks before upload. A SCORM zip with a broken manifest namespace, a duplicate cmi.interactions.N.id, or an asset reference pointing at a file that didn't make it into the package would pass Storyline's publish step and fail silently on Moodle. The first signal would be a learner ticket two weeks later.
  2. No accessibility gate. Every course was supposed to be "WCAG-AA-aligned." In practice that meant "the producer remembered to set alt text most of the time." No static gate, no compile-time enforcement.
  3. No diff between versions. A storyboard revision shipped as a re-published zip. To review what changed, somebody had to unpack both zips and diff -r them. Manifest changes were buried in XML noise. Nobody did this. We shipped regressions.
  4. No local runtime. To test a SCORM change you uploaded to Moodle. Every cycle. Even for one-line CSS tweaks. The dev loop was minutes long.
  5. One package per language. We shipped Hindi, Tamil, Kannada as separate uploads. The gradebook saw them as separate courses. Completion didn't aggregate. Reporting was a mess.
  6. No runtime visibility. Once a course was live, the LMS told you completion and score. Nothing else. Was the slide janky? Did a video 404? Did a script throw? Unknown until somebody complained.

Six gaps. Each one had a workaround. None of the workarounds composed.

The pipeline I built

Each gap became a small CLI. The constraint was deliberate: small, composable, no shared state, pipeable. SCORM as a Unix-style build target.

That was the original six. Two more followed once the pipeline was in production: scorm-kit privacy (sixteen-rule PII / data-leak static audit, after a procurement reviewer flagged a font CDN that set cookies in one of our compliance modules), and scorm-kit cmi5 (validator + SCORM→cmi5 wrapper, after the first enterprise RFP that required cmi5 made it clear the dual-stream pattern was the safe migration path). Eight commands now. Each one was the size that was needed to fix one specific class of pain.

What it taught me

The original instinct — "treat the SCORM zip as something to compile, validate, and review like any other build artifact" — turned out to be the whole insight. The individual tools are not novel. Linting isn't novel. Static a11y isn't novel. Diffs aren't novel. What was missing was applying these widely-understood software-engineering disciplines to the SCORM workflow, which had inherited the conventions of authoring tools (visual, monolithic, opaque) instead of the conventions of code (textual, composable, gateable).

The job title most teams reach for is Instructional Designer. The work, increasingly, is Learning Engineering — taking SCORM, cmi5, and xAPI seriously as build targets and instrumenting the pipeline that delivers them. That gap is where most of the deployed-content quality problems live, and it's where most of the value of a senior IC role lives too.

Why this is in the portfolio

The freeze-bug story is the thirty-minute version. This is the eighteen-month version. The first answers "can you debug this." The second answers "can you build something so this class of bug doesn't happen again." For the roles I'm interested in, the second is the question that matters.

scorm-kit is open source. The toolchain that runs in the Kidvento pipeline is a superset of the open-source build and includes the org-specific glue. The open-source commands are the parts that generalise.