Skip to content

Developer Reference Guide

Philip Pavlik edited this page May 28, 2026 · 9 revisions

Developer Reference Guide

Last Updated: 2026-05-27 | For: Developers working in C:\dev\MoFaCTS

Audience: Developers only. Students, teachers, and researchers should use the role guides from Home unless they are also contributing code.

This is the canonical developer doc for the wiki. It replaces the previous map, architecture, data model, API-contract, API-index, and card/state-machine reference pages.

Start Here

  1. Use Local Install for the default local setup.
  2. Read the code in mofacts/ before changing runtime behavior.
  3. Use this page as the stable reference for architecture, data model, runtime boundaries, and high-risk areas.

Source of Truth

  • The wiki is canonical for stable contributor guidance.
  • The code is canonical for exact runtime behavior.
  • Public release-facing docs live in the repository root docs/ folder; longer operational/user guidance lives in this wiki.

Codebase Map

MoFaCTS application source still lives primarily under mofacts/, while contributor-facing learning-system code is being extracted to root learning-components/.

MoFaCTS/
  mofacts/              Meteor app shell, UI, server, common collections, custom Meteor packages
  learning-components/  unit engines, adaptive model code, content interpretation, runtime contracts
  examples/             typed contributor examples
  deploy/               canonical Docker Compose, hotfix, and deployment workflow
  app/                  target app-shell architecture map during migration
  packages/             target public API packages during migration

Runtime Architecture

Browser UI (Blaze + some Svelte)
  -> Meteor DDP / HTTP
Meteor app server
  -> MongoDB
  -> Dynamic assets / file storage

Key patterns:

  • Meteor methods handle writes and business logic.
  • Publications handle reactive reads.
  • Shared collections are defined in mofacts/common/Collections.ts.
  • The experiment runtime is still centered on the Blaze-based card flow, with Svelte work alongside it rather than replacing it everywhere.

History-First Resume Architecture

The current experiment runtime uses a history-first persistence model:

  • Histories is the canonical committed interaction log for learning, assessment, hidden-item actions, and video checkpoint question progress.
  • Learning resume reconstructs model state from history, then recomputes the next best card at resume time instead of restoring a persisted per-card cache.
  • Assessment resume derives question position from completed history count plus the persisted schedule artifact.
  • Video resume derives checkpoint position from completed history count plus checkpoint metadata in the TDF.
  • GlobalExperimentStates is now sparse control-plane state only: unit bootstrap, mapping/signature setup, schedule artifact storage, and other non-trial resume metadata.
  • Ordinary per-trial or per-question experiment-state writes are intentionally avoided.

Main Runtime Files

Use these first when you need to understand behavior:

  • mofacts/server/methods/
  • mofacts/server/publications.ts
  • mofacts/common/Collections.ts
  • mofacts/client/views/experiment/svelte/components/CardScreen.svelte
  • mofacts/client/views/experiment/unitEngine.ts (Meteor-facing compatibility facade)
  • learning-components/units/createUnitEngine.ts
  • learning-components/units/UnitEngineRegistry.ts
  • learning-components/units/learning-session/model/selectionPolicy.ts
  • learning-components/units/learning-session/model/probabilityCalculation.ts
  • mofacts/client/views/experiment/modules/cardStore.ts
  • mofacts/client/views/experimentSetup/contentUpload.ts
  • mofacts/client/views/experimentSetup/apkgWizard.ts

Data Model

Primary collection groups:

  • learning and course data: Tdfs, Items, Histories, Assignments, Courses, Sections, SectionUserMap
  • experiment/session state: GlobalExperimentStates, UserTimesLog, UserMetrics, UserDashboardCache
  • content/assets/config: Stims, itemSourceSentences, DynamicAssets, DynamicSettings, DynamicConfig
  • security/audit/utility: PasswordResetTokens, AuditLog, ErrorReports, UserUploadQuota, ScheduledTurkMessages, ClozeEditHistory

Important relationships:

  • course -> section -> assignment
  • TDF -> items -> histories
  • user <-> section through SectionUserMap
  • per-user runtime control state lives separately from lesson definition data, but committed trial/question behavior should be recoverable from Histories

Notes:

  • Meteor 3 server code should prefer async collection APIs.
  • JS variable names and Mongo collection names do not always match.
  • DynamicSettings still uses the historical collection name dynaminc_settings.

API Surface

The raw method/publication inventory is large and not useful as a separate wiki page. The practical split is:

  • auth/user management
  • content upload and editing
  • assignments and class management
  • experiment/runtime state
  • reporting and data export
  • theme/help-page/admin utilities

High-value methods to know:

  • processPackageUpload
  • analyzeApkgFile
  • generateTdfsFromApkg
  • saveTdfStimuli
  • saveTdfContent
  • copyTdf
  • tdfUpdateConfirmed
  • downloadDataByTeacher
  • downloadDataByFile
  • downloadDataById
  • getTdfsAssignedToStudent
  • getAllCourseAssignmentsForInstructor
  • insertHistory

Server-internal reporting helper:

  • getHistoryByTDFID is exported for server-only reporting code and should not be treated as a public Meteor method.

Important publication groups:

  • content listing and editing: allTdfsListing, dashboardTdfsListing, tdfForEdit, ownedTdfs
  • runtime/session: userExperimentState, currentTdf
  • assets/settings/theme: assets, settings, theme, themeLibrary

When documenting or changing a method, capture:

  1. auth/roles required
  2. input shape
  3. return shape
  4. side effects
  5. failure cases

Card Runtime and State Machine

The experiment card flow is a high-risk area. Treat changes here as architectural work, not routine UI polish.

Runtime unit resolution recognizes assessmentsession as a schedule unit, learningsession as a model/adaptive unit, videosession as a video unit, autotutorsession as an AutoTutor unit, and instruction-only units when instruction fields exist without a session object. Do not treat learning and assessment sessions as the only unit types. H5P is not a unit type; it registers as the h5p trial-display adapter and appears under stimulus display.h5p.

Core flow:

  1. prepareCard() selects and prepares the next trial
  2. content preloads and display state is set up
  3. the question starts fading in; trial timers are anchored here, before input may open
  4. input is processed through handleUserInput()
  5. feedback/study/transition logic runs
  6. cardEnd() returns to the next-trial path

Important trial states:

  • IDLE
  • PRESENTING_LOADING
  • PRESENTING_FADING_IN
  • PRESENTING_DISPLAYING
  • PRESENTING_AWAITING
  • STUDY_SHOWING
  • FEEDBACK_SHOWING
  • TRANSITION_START
  • TRANSITION_FADING_OUT
  • TRANSITION_CLEARING

Use these rules when editing trial behavior:

  • input should only be accepted in input-accepting states
  • speech recognition should not restart during feedback or transition phases
  • fade-out/fade-in boundaries are part of runtime correctness, not just animation
  • response timeout resets are explicit user-activity events, such as text input activity, voice start, and speech-recognition retry/error activity
  • TTS may extend an expired timer until active playback completes, but it must not restart a full configured timer
  • duplicated cleanup and recovery guards in card.js should be verified against real execution flow before keeping them

Card State Ownership

CardStore is the intended facade for card-scoped state. Avoid adding fresh direct state mutations in unrelated modules.

State buckets you should think in:

  • card UI state
  • speech-recognition state
  • trial-state-machine state
  • timeout/timer state
  • shared Session-backed lesson/runtime state

If you need a new state value, prefer:

  1. an existing store or facade
  2. a narrowly scoped new accessor
  3. direct raw Session usage only if there is a clear reason

Current Structural Risks

  • server methods are split under mofacts/server/methods/, but runtime-facing method changes are still high-risk
  • card.js remains one of the highest-risk files in the codebase
  • Blaze and Svelte coexist, which makes contribution targeting non-obvious
  • root learning-components/ is executable TypeScript; unit engines and the H5P trial-display adapter register through explicit learning-component manifests
  • canonical history rows carry historySchemaVersion: 1; standard cards and H5P rows use the shared history service, AutoTutor writes through its history runtime capability, and app-owned history persistence validates the canonical envelope before storage
  • some older planning docs in the repo describe future intent, not current truth

Dependency and Change Policy

  • use npm ci, not npm install, for reproducible installs
  • keep dependency updates focused
  • prefer explicit image/version tags over floating latest
  • run npm run lint and npm run typecheck before merging TypeScript-bearing app changes
  • root learning-components/**/*.ts and examples/**/*.ts are included in the repository checks
  • treat auth, upload, export, and runtime-trial changes as high-verification areas

Contribution Targeting

  • default new UI work to the active Svelte direction only when the feature area already lives there
  • if behavior still runs through Blaze/card runtime, document and test against the Blaze path instead of pretending the migration is complete
  • for content/import/export changes, update the user-facing wiki pages in the same change when behavior changes

Related Pages

Clone this wiki locally