Repository navigation
feat: exclude archived criteria and groups from the status rollup - #3
Open
alezconsultant wants to merge 1 commit into
Conversation
Filter archived rows out of the two queries that fetch a group's children, so an archived criterion or criteria group does not count when a learner's group and competency statuses are combined. A group whose children are all archived has no status to report, so the rollup writes nothing for it. An archived group that the walk reaches is passed through, so its parent is still recomputed from its live children, but it gets no status row and, if it is a root, no competency row. The investigation warning for a sub-competency with no criteria beneath it ignores archived root groups, so a fully archived branch warns like one that was never authored. ADR-0002 Decision 6 records the evaluation rule. Statuses a learner already holds are never lowered or removed, so mastery earned through a requirement that was archived later stays earned. A parent competency's own archived root group counts through its stored status. Archiving does not trigger a rollup; a recomputation happens on the next grade for any criterion in that group or beneath it. Leaf evaluation skips archived criteria when a grade is recorded. The rollup's entry query does not, so a rollup call naming an archived criterion's content still recomputes that group from its live children. Related to openedx#815 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
An archived
CompetencyCriterionorCompetencyCriteriaGroupstops counting toward a learner'sstatus the next time the rollup runs. Every status a learner already holds is kept. The rollup
combines only live children, so an archived requirement the learner never met cannot keep a group
short of "demonstrated".
The rollup reads a group's children through two queries,
_child_groupsand_child_criteria.Both require
archived=False, so an archived child is invisible to its parent at the pointit is fetched.
combine_childrenreturns no status when no child has one, andraise_statusnever lowers ordeletes a stored row, so the kept-status and empty-group cases follow from the two filters.
Changes
src/openedx_learning/applets/cbe/rollup.py:_child_groupsand_child_criteriafilterarchived=False._roll_up_groupsskips both status writes at a group that is itself archived, and still addsits parent group (or, for a root, its competency tag) to the walk.
_log_unearnable_sub_competenciesalso requiresarchived=False.roll_up_competency_statusessay so.docs/openedx_learning/decisions/0002-competency-criteria-model.rst: Decision 6 bullet and changelog entry (see ADR).tests/openedx_learning/applets/cbe/test_rollup_api.pyandtest_tag_rollup.py: see Tests.Behavior
about
archived. Leaf evaluation at grade time already skips archived criteria. The rollup's entry query does not, so a rollup call naming an archived criterion's content still recomputes that group from its live children; the scenario "a previously demonstrated requirement changes nothing until the rollup runs" relies on that.it writes no
StudentCompetencyCriteriaGroupStatusfor it, and if that group is a root itwrites no
StudentCompetencyStatuseither. Its parent is still recomputed from the parent'slive children, and a root's competency still goes into the parent-competency walk. When other
graded tags already reach a level of the parent walk, the archived root's tag adds no reads and two queries per additional parent (four on a first write). When it is the only tag reaching a level, it adds that level's six batched reads plus two per parent, at every level to the top. Compared with feat: roll up learner competency statuses above a graded criterion openedx/openedx-core#870 this change adds no queries, because feat: roll up learner competency statuses above a graded criterion openedx/openedx-core#870 already fed that tag into the walk, and it removes the archived root's own writes.
write. An existing row is never deleted, and
raise_statusnever writes a lower value. Alearner who earned mastery through a requirement that was archived later keeps it.
_own_criteria_statusesis unfiltered, on purpose. A stored status on a parentcompetency's archived root group still counts toward that competency's own result, so a parent
that already reached "demonstrated" through it keeps doing so. This is consistent with "already
earned is kept".
"has no criteria beneath it and can never be demonstrated" warning, the same as one that was
never given requirements. A live root whose criteria are all archived is not reported, because
the query does not look at criteria (a known limitation from the ticket).
group status changes when the rollup next runs for a criterion in that group or beneath it, or
when the operator recomputation command ([BE] Recompute learner competency statuses on operator command openedx/openedx-core#774, not built yet) runs. Leaf evaluation skips
archived criteria, so a grade for an archived requirement writes no leaf row and returns a zero
count. The task drafted in openedx/edx-platform #39179 enqueues the rollup only when that count
is non-zero, so under that draft the acceptance scenario's "new grade for that requirement"
trigger is reachable only through the operator command.
Tests
Seventeen new tests. Ten of them cover the eleven acceptance scenarios and are named after the
scenario; the archived-branch and never-authored investigation cases share one test.
Six of the seventeen pass on the rollup without this change: the all-archived, kept-mastery, kept-unmet-status, and two parent-competency scenario tests, and the query-count guard. They pin the existing behavior each scenario relies on and give every scenario a named test; the other ten fail when the corresponding filter or guard is removed.
And in
test_tag_rollup.py: an archived root group still starts the parent-competency walk. Thearchived child gets no competency row, and the parent still reads its live sibling's stored
"demonstrated" and ends at "partially attempted".
The empty-collection case ("an AND group whose every child is archived") is the pure function
combine_children(op, []), whichtest_rollup_rules.py::test_combine_childrenalready covers.Verification
pytest tests/openedx_learning --no-cov: 430 passed on SQLite.pylint,pycodestyle,isort --check-only, andpydocstyleon the changed files: clean.mypyover the whole repository: no issues.lint-imports: all contracts kept.doc8on the changed ADR: clean.-W: clean.a scratch database migrated from scratch. Every expected value matched: both archived-requirement
cases ended at (30, 30), kept mastery stayed at 30 with
modifiedunchanged, the investigationwarning named the parent and the archived sub-competency once and the parent ended at 20, and
the unmet group status stayed at 10.
Notes for reviewers
group, so an author can add a live criterion under an archived root. The rollup then writes
that yet. An archived group whose criteria are still live gets no row, and its parent is
computed from its other live children. A test pins this.
counts toward that parent. This is left as is on purpose (see Behavior), so it has no new test.
Related to openedx#815
🤖 Generated with Claude Code