Skip to content

Developer Reference Guide

Philip Pavlik edited this page May 22, 2026 · 18 revisions

Developer Reference Guide

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

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/models/selection/selectionPolicy.ts
  • learning-components/models/probability/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, and instruction-only units when instruction fields exist without a session object. Do not treat learning and assessment sessions as the only unit types.

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 fallback 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 now executable TypeScript, but some public API packages remain migration targets rather than stable extension APIs
  • 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