Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions docs/openedx_learning/decisions/0006-pathway-item-fulfillment.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
.. _openedx-learning-adr-0006:

6. Pathways: Mapping Pathway Items to the Things That Fulfill Them
==================================================================

Status
------

Draft

Context
-------

:ref:`openedx-learning-adr-0005` establishes that a Pathway Item is a stable requirement whose fulfillment can change
over time. This ADR describes how we intend to map Items to the things that fulfill them, starting with the only
fulfillment type in the first release: passing a course.

The exact data model here will likely need adjustment; we expect to modify it in an actual code PR.
Development does not gate on this ADR - it captures intent and boundaries, not field-level models.

Decisions
---------

1. In the MVP, a Pathway Item is fulfilled by passing a course run:

- Each Item holds an **author-defined list of course runs** that fulfill it. Passing *any one* of them fulfills
the Item. The runs may belong to different catalog courses.
- The list is explicit rather than "any run of this catalog course", because we don't necessarily want every
possible older version of a course to count.
- "Passing" is determined by each course's own grading policy. The grade and passed/failed state are read directly
from the course; Pathways define no grading of their own.
- Each Item designates a **default course run** - the one a learner is enrolled in when they begin the Item - and,
if that course uses multiple enrollment tracks, the track to enroll them in. The default can change over time.

2. Fulfillment types attach at this layer only. Potential future types - section completion, competency attainment,
admin override - plug in as alternative ways to fulfill an Item, without touching Item identity, Pathway structure,
or Pathway completion criteria.

3. Edge cases are resolved at this layer and never leak upward. For example: multiple passed runs fulfilling the same
Item (the Item is simply fulfilled), or one passed run fulfilling several Items simultaneously (each Item is
fulfilled independently).

4. Prior work counts. If a learner passed a course before enrolling in a Pathway that contains it, that pass fulfills
the corresponding Item - fulfillment is evaluated against the learner's record, not against activity that happened
"inside" the Pathway.

5. Item fulfillment is evaluated at three moments:

- **A course passing-status signal.** The learner's fulfillment is re-evaluated for the Items whose run list
includes that run, in the Pathways they are enrolled in.
- **Pathway enrollment.** A one-time check goes through everything the learner has already passed, which is what
makes decision 4 work.
- **Publishing changes to a Pathway Item.** An async task goes through the learners currently enrolled in
the Pathway containing that Item and retroactively evaluates the fulfillment.

6. The third trigger exists because the first two do not cover this sequence:

a. A learner passes Course Run A, which at the time fulfills nothing in the Pathway.
b. The learner enrolls in the Pathway. The enrollment check finds nothing relevant.
c. An author edits a Pathway Item so that Course Run A now fulfills it, and publishes the change.

No passing signal fires at step (c), and the enrollment check has already run, so without the async task the
Item would never be fulfilled for that learner, even though their record now satisfies it.

7. The task fires on publishing, not on draft edits, so an author can revise an Item repeatedly and only the
published result reaches learners.

8. Retroactive evaluation only grants credentials. Narrowing an Item, by removing a course run that used to
fulfill it, does not revoke credential a learner has already been awarded.

.. Run `dot -Tsvg images/pathway-item-fulfillment.dot > images/pathway-item-fulfillment.svg` to regenerate the
diagram after making changes to `images/pathway-item-fulfillment.dot`.

.. image:: images/pathway-item-fulfillment.svg
:alt: Pathway Item fulfillment mapping
:width: 100%

.. Run `dot -Tsvg images/pathway-item-evaluation.dot > images/pathway-item-evaluation.svg` to regenerate the diagram
after making changes to `images/pathway-item-evaluation.dot`.

.. image:: images/pathway-item-evaluation.svg
:alt: When Pathway Item fulfillment is evaluated
:width: 100%

Consequences
------------

- Authors control exactly which runs count, at the cost of manually updating the list when new runs are created.
- Because passing state comes directly from course grading, there is no Pathway-side duplication of grades to keep in
sync.
- Only the third trigger needs an async task: the first two act on a single learner, while publishing an Item change
fans out across everyone enrolled in the Pathways that contain it.
- Publishing an Item change on a large Pathway is therefore not instantaneous. Retroactive credentials appear once the
task completes.
- The fulfillment mapping is the natural extension point for everything post-MVP, and the part of the model we
expect to iterate on in code.
36 changes: 36 additions & 0 deletions docs/openedx_learning/decisions/images/pathway-item-evaluation.dot
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
digraph pathway_item_evaluation {
rankdir=LR;
fontname="Helvetica";
node [shape=box, style=rounded, fontname="Helvetica", fontsize=11];
edge [fontname="Helvetica", fontsize=10];

subgraph cluster_per_learner {
label="acts on one learner";
fontsize=10;
fontcolor="#4d4d4d";
style=dashed;
color="#b3b3b3";
signal [label="course passing-status\nsignal", shape=ellipse];
enroll [label="Pathway enrollment\n(checks what the learner\nhas already passed)", shape=ellipse];
}

subgraph cluster_fan_out {
label="fans out over enrolled learners";
fontsize=10;
fontcolor="#4d4d4d";
style=dashed;
color="#b3b3b3";
publish [label="Pathway Item change\npublished\n(async task)", shape=ellipse];
}

evaluate [label="evaluate Pathway fulfillment\nagainst the learner's record"];
credential [label="grant credential\n(never revoked by\na later narrowing)"];
nochange [label="no change", shape=plaintext];

signal -> evaluate;
enroll -> evaluate;
publish -> evaluate;

evaluate -> credential [label="fulfilled"];
evaluate -> nochange [label="otherwise"];
}
98 changes: 98 additions & 0 deletions docs/openedx_learning/decisions/images/pathway-item-evaluation.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
digraph pathway_item_fulfillment {
rankdir=LR;
fontname="Helvetica";
node [shape=box, style=rounded, fontname="Helvetica", fontsize=11];
edge [fontname="Helvetica", fontsize=10];

item [label="Pathway Item"];
runA [label="Course Run A1\n(default: enroll here)"];
runB [label="Course Run A2\n(older run, still counts)"];
runC [label="Course Run B1\n(different catalog course)"];
future [label="future fulfillment types:\nsection completion,\ncompetency, admin override", style="rounded,dashed"];

item -> runA [label="pass any one"];
item -> runB;
item -> runC;
item -> future [style=dashed];

grading [label="passed/failed read directly\nfrom each course's\ngrading policy", shape=plaintext, fontsize=10, fontcolor=gray30];
runB -> grading [style=invis];
}
Loading