Skip to Content

Intervention Bundles

When a student has an active educational profile, the modules/bundle module takes a single step: it looks the profile up in a 21-row deterministic map and returns exactly one named intervention bundle. The teacher then decides whether to activate it. Nothing reaches a student until the teacher acts (V-12).

The catalog

The bundle catalog contains 20 defined bundle definitions. Bundles are closed catalog items identified by a string bundleId. They are not generated, not freeform, and not per-student. What changes per student is the scaffold tier assigned to each skill within that bundle.

The catalog is versioned and publish-then-freeze: once a catalog version is published it is never mutated. A V-6 dry-run replay endpoint lets you preview how a catalog change would affect existing recommendations before publishing.

From profile to bundle: the map

The 21-row profile_bundle_map is keyed on (primary_profile_code, access_driver | comprehension_subprofile | modifier_driver). The extra driver column narrows which bundle is selected for profiles that have multiple instructionally distinct sub-types.

Row MAP-000 / NO_BUNDLE_SYSTEM_GUARD is the halt case: when the student has no active profile, a DATA_INCOMPLETE guard state, or a do_not_decide_yet anchor skill, the map returns blocked_insufficient_evidence plus a nextRecommendedDataAction that names the specific data action needed. No bundle is recommended and there is no override path around this.

MAP-000 is a hard halt. It surfaces only the next data action, never a placeholder bundle. No override code bypasses it. The teacher’s action is to complete the named data collection step, not to activate an alternative plan.

The Threaded Path Model

Every recommended bundle has three parts:

PartWeight rangeRule
Anchor40–60% of instructional timeAddresses the primary skill group; must always be the largest share
Supporting threads (1–2)25–35% combinedAddress skills related to the anchor; maximum 2
Asset bridge10–15%Builds on a documented strength; not_enough_evidence when support data is absent

The anchor weight being strictly the largest is enforced in two places: the engine (threaded-path.ts) and a DB CHECK constraint on the assignment table. Trying to store a split where a supporting thread outweighs the anchor will be rejected.

The dosageSplit field on every ActivateBundleResponse and BundleCatalogRowDTO carries the actual percentages.

Scaffold tier

The scaffold tier is assigned per (student × skill × bundle × task_type), not per student and not per bundle. A student may have Level_1_Foundation on one skill within a bundle and Level_2_Targeted on another.

TierIdentifier
FoundationLevel_1_Foundation
TargetedLevel_2_Targeted
IndependenceLevel_3_Independence

The scaffold tier is never shown to the student. It drives which level of scaffolded task the task-delivery layer selects. Teacher and admin routes can see tier distribution (the cluster preview and the scaffold adjustment endpoint expose it), but no student-facing route does.

Scaffold tier adjustments use override rule OVR_SCAFFOLD with a reasonCode from the 9-code catalog. RTI tier is in every override’s forbidden_fields and is never written through any bundle endpoint.

Bundle assignment lifecycle

Once a teacher activates a bundle, the assignment follows a 17-value lifecycle reflecting the monitoring loop:

recommended → in_review → activated → monitoring ├─ paused ├─ reviewed → continued | adjusted | modified ├─ escalated → immediate_review ├─ data_completion_required ├─ met_criteria → exited ├─ teacher_modified ├─ regression_review └─ rescinded

The BundleAssignmentStatus enum is the authoritative list returned in ActivateBundleResponse and exposed on the class profile distribution endpoint.

Teacher adjustments (override codes)

Teachers adjust bundle parameters (delivery mode, schedule, context flags) through controlled override operations. Every adjustment picks a reasonCode from the 9-code OverrideCodeCatalog:

CodeApplicable scope
Override_Contextual_01All
Override_Procedural_02All
Override_Scheduled_03All
Override_DataGap_04All
Gam_Award_Invalid_05Gamification rescind only
Bundle_Met_Criteria_06Bundle exit
Bundle_Teacher_Modify_07Bundle exit
Bundle_Acute_Regression_08Bundle exit
Bundle_Data_Incomplete_09Bundle exit

No free-text reason fields exist anywhere in the bundle module. All adjustment endpoints accept only a reasonCode FK into this catalog. This is enforced at the CI lint level (pnpm lint:bundle).

Context flags (e.g. CTX_SESSION_INTERRUPTED) may optionally accompany an adjustment. The 7 allowed ContextFlagId values are the only representable flags; the 3 blocked ones are not constructible through the API.

Key endpoints

EndpointPurpose
POST /api/bundles/recommendCompute and write a bundle recommendation for a student
GET /api/bundles/catalogAll 20 bundle definitions
GET /api/bundles/:id/definitionOne bundle with delivery options and cluster rule
GET /api/bundles/profile-mapAll 21 map rows and integration rules
POST /api/students/:id/activate-bundleTeacher activates a recommendation
PATCH /api/students/:id/scaffold-assignmentOVR_SCAFFOLD adjustment
PATCH /api/assignments/:id/deliveryOVR_DELIVERY adjustment
PATCH /api/assignments/:id/scheduleOVR_SCHEDULE adjustment
POST /api/assignments/:id/context-flagOVR_CONTEXT_FLAG (7 allowed flag ids)
POST /api/admin/bundle-config-setsPublish new catalog version
POST /api/admin/bundle-replayV-6 dry-run; writes nothing

Smart Cluster + bulk-activation endpoints are in Smart Clustering.

Connections

  • Upstream: Student Profiles: the active profile is the input to the profile-to-bundle map.
  • Downstream: Smart Clustering: cluster logic groups students who share bundle, anchor, tier, and delivery mode.
  • Monitoring: Progress Monitoring: the 5 GSR safety rules and 19 per-bundle success criteria that govern when a bundle transitions.
  • Workflow: Teacher Activation Workflow: the 17-step UI workflow that drives teacher confirmation, adjustment, and review.
  • Task delivery: Task Delivery: once a bundle is active, task delivery selects and serves stored items using the scaffold tier.
Last updated on