Skip to content

feat: copy competency criteria to a new course run - #933

Open
alezconsultant wants to merge 1 commit into
openedx:mainfrom
alezconsultant:alezconsultant/694-rerun-copy-criteria
Open

alezconsultant wants to merge 1 commit into
openedx:mainfrom
alezconsultant:alezconsultant/694-rerun-copy-criteria

Conversation

@alezconsultant

@alezconsultant alezconsultant commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

Description

Adds the openedx-core half of #694: a function that copies a course run's competency criteria onto a new run of the same course. openedx-platform calls it from the course rerun task, after it has copied the content tags.

copy_competency_criteria_for_course_rerun(
    source_course_key, destination_course_key, *, skipped_taxonomy_ids=()
) -> CompetencyCriteriaCopyResult  # groups_created, criteria_created

Behavior

  • Each competency with in-force criteria on the source run gets a new course-level group for the new run under the competency's existing root group. The two runs are therefore alternative ways to demonstrate the competency. Tags and taxonomies are referenced, not copied.
  • Descendant groups keep their name, ordering, and logic operator. Criteria keep their rule profile and overrides, and point at the new run's ObjectTag for the same block and tag. A rule on a retired profile keeps that profile: the copy reproduces the source run's rules and does not reassign a profile.
  • Archived groups, everything under them, and archived criteria are not copied. A group with no in-force criterion beneath it is not created.
  • A competency in skipped_taxonomy_ids is not copied. The platform passes the taxonomies that are not enabled for the new run's organization.
  • A competency that already has a course-level group on the new run is skipped and a warning is logged, so a retried rerun ends with one copy.
  • A source run with no catalog CourseRun row has no criteria, so the function returns zero counts. A missing destination CourseRun row or a missing destination ObjectTag raises, and the transaction leaves nothing behind.
  • Rows are created one at a time through save(), so history records are written for groups and criteria, and model validation runs for criteria.

Testing

pytest tests/openedx_learning/applets/cbe/test_copy_criteria.py --no-cov (25 tests). The full CBE suite, lint-imports, the linters, and mypy pass.

Manual testing

This function has no user-facing path of its own. It is exercised through the course rerun in the openedx-platform pull request, which lists the Studio steps.

Notes for reviewers

  • To keep the number of read queries fixed regardless of tree depth, the function loads the non-archived descendant groups of the copied competencies across all runs and keeps the source run's subtrees in memory.
  • The function is marked UNSTABLE, like the rest of the criteria-authoring API.

Known limits

  • A copied rule is saved through CompetencyCriterion.save(), which validates a custom override again. If a later release tightens that validation and leaves an older override invalid, a rerun of that course fails until the override is corrected. Grading already skips such a rule on the source run.

Related to #694

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Course reruns can now carry over eligible competency criteria and groups from a source course, linked to matching destination content.
    • Archived criteria, excluded taxonomy branches, and competencies already present in the destination are not copied.

Adds copy_competency_criteria_for_course_rerun(), which recreates a
course run's in-force criteria tree on a new run of the same course.
Each competency gets a new course-level group under its existing root,
so the two runs are alternative ways to demonstrate it. Archived groups,
archived criteria, and groups left without an in-force criterion are
not copied.

Each copied criterion points at the new run's ObjectTag for the same
block and tag, so the caller copies the content tags first. A competency
that already has a course-level group on the new run is skipped, which
lets a retried rerun finish with one copy.

Related to openedx#694

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
@openedx-webhooks openedx-webhooks added the open-source-contribution PR author is not from Axim or 2U label Nov 12, 2026
@openedx-webhooks

Copy link
Copy Markdown

Thanks for the pull request, @alezconsultant!

This repository is currently maintained by @axim-engineering.

Once you've gone through the following steps feel free to tag them in a comment and let them know that your changes are ready for engineering review.

🔘 Get product approval

If you haven't already, check this list to see if your contribution needs to go through the product review process.

  • If it does, you'll need to submit a product proposal for your contribution, and have it reviewed by the Product Working Group.
    • This process (including the steps you'll need to take) is documented here.
  • If it doesn't, simply proceed with the next step.
🔘 Provide context

To help your reviewers and other members of the community understand the purpose and larger context of your changes, feel free to add as much of the following information to the PR description as you can:

  • Dependencies

    This PR must be merged before / after / at the same time as ...

  • Blockers

    This PR is waiting for OEP-1234 to be accepted.

  • Timeline information

    This PR must be merged by XX date because ...

  • Partner information

    This is for a course on edx.org.

  • Supporting documentation
  • Relevant Open edX discussion forum threads
🔘 Get a green build

If one or more checks are failing, continue working on your changes until this is no longer the case and your build turns green.

Details
Where can I find more information?

If you'd like to get more details on all aspects of the review process for open source pull requests (OSPRs), check out the following resources:

When can I expect my changes to be merged?

Our goal is to get community contributions seen and reviewed as efficiently as possible.

However, the amount of time that it takes to review and merge a PR can vary significantly based on factors such as:

  • The size and impact of the changes that it introduces
  • The need for product review
  • Maintenance status of the parent repository

💡 As a result it may take up to several weeks or months to complete a review and merge your PR.

@coderabbitai

coderabbitai Bot commented Nov 12, 2026 •

Copy link
Copy Markdown

Explain Change →

No actionable comments were generated in the recent review.

Walkthrough

The change adds an API to copy eligible competency groups and criteria from one course run to another. It excludes archived or skipped items, maps criteria to destination object tags, and returns counts of created groups and criteria.

Changes: Course rerun criteria copying

Layer / File(s) Summary
API and source selection
src/openedx_learning/applets/cbe/api.py, tests/openedx_learning/applets/cbe/test_copy_criteria.py
The exported API selects eligible source groups and handles missing course runs. Tests cover initial selection, skipped taxonomies, and basic copy behavior.
Eligible group trees and destination tags
src/openedx_learning/applets/cbe/api.py, tests/openedx_learning/applets/cbe/test_copy_criteria.py
The copy retains group paths to in-force criteria and maps criteria to destination object tags. Tests cover nested groups, archived items, shared branches, and copied fields.
Copy outcomes and rollback checks
src/openedx_learning/applets/cbe/api.py, tests/openedx_learning/applets/cbe/test_copy_criteria.py
Tests check rollback on errors, repeat-copy results, row counts and history, unchanged source rows, and query counts.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Feature

Possibly related issues

  • openedx/openedx-core#652 — The API defines rerun criteria-copy behavior that the issue asks to document; this change does not add documentation.
  • openedx/openedx-core#694 — The API copies eligible criteria for a new course run, addressing the criteria-copy portion of the issue.
  • openedx/openedx-core#724 — The API implements criteria copying for course reruns, which is part of the broader copy requirement.

Suggested reviewers: jesperhodge, ufedaseyeuconsultant

Merge Risk: Minimal · up to 586f3

This adds an unstable API that copies competency criteria for course reruns. Its selection, destination-tag mapping, and rollback behavior are covered by tests. Only minor follow-ups remain, for related-tag conflicts on a pre-populated destination and for the size of the descendant-group load, and neither blocks merging.

Security architecture risk: Moderate · up to 586f3

The copy is transactional and requires matching destination tags, limiting partial writes and unintended associations. However, it can preserve a conflicting destination competency configuration that ordinary authoring rejects. Caller authorization and exclusive ownership of the destination during rerun could not be verified. No externally reachable authorization bypass was established.

Retained concerns

  • Medium · architecture · inferred: The copy can commit ancestor and descendant competency criteria into the same destination run, bypassing the dominance invariant enforced by ordinary authoring. If the destination already contains a criterion for a taxonomy relative of a copied competency, the exact-tag skip does not detect it, and direct model creation performs no containment check. A successful copy therefore can leave conflicting persisted competency configuration; repeating the copy skips rather than repairs it. Exclusive use of a fresh destination would avoid this condition, but that ownership guarantee is not enforced or verified here.
Security review details

Security Blast Radius

  • inferred — A successful invocation writes selected competency groups and criteria for one supplied destination run beneath existing shared competency parents. It requires matching destination ObjectTags and preserves existing tag and profile references. The supplied production caller is absent, so attacker reachability and the maximum organizational scope available through that caller remain unverified.

Trust Boundaries and Controls

  • inferred — Safe integration depends on a trusted caller supplying authorized source and destination identities and the appropriate taxonomy exclusions. Exact destination ObjectTag matching constrains writes to existing associations, but it is not an actor authorization or same-course control. The PR describes a platform rerun-task caller; its enforcement could not be checked here.

Resilience and Maintainability Implications

  • inferred — Transactional rollback contains failed copies, but does not reject semantically conflicting successful copies. Direct model creation avoids the existing authoring containment validator, allowing destination policy drift when related competencies already have criteria. This is a persisted-state concern, not a demonstrated privilege-escalation path.

Hardening Proposals

  • proposed — Make the trusted-caller contract explicit: authorized source and destination, sibling-run identity, organization-derived taxonomy exclusions, destination-tag readiness, and destination ownership during copying. Verify those guarantees at the platform integration boundary rather than treating library importability as evidence of a remotely accessible bypass.
Pre-merge checks: Passed 4

Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title "feat: copy competency criteria to a new course run" matches the main change in the changeset. The raw summary and PR objectives both describe the new copy_competency_criteria_for_course_rer…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title "feat: copy competency criteria to a new course run" matches the main change in the changeset. The raw summary and PR objectives both describe the new copy_competency_criteria_for_course_rerun function, which recreates in-force competency criteria for a new course run. The title is short, specific, and uses a conventional commit prefix, so a teammate scanning history can identify the primary change.

Finishing Touches

Generate unit tests (beta)

  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Recent review info

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 65146991-0f8c-4f04-87c8-435452ff5abf
Commits

Reviewing files that changed from the base of the PR and between 7e150e7 and 586f3ce.

Files selected for processing: 2

  • src/openedx_learning/applets/cbe/api.py
  • tests/openedx_learning/applets/cbe/test_copy_criteria.py

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.

@alezconsultant

Copy link
Copy Markdown
Contributor Author

Review of this change by /backend-code-review (Claude Fable 5.2, medium effort)
933-fix-report-core.md
933-review-core.md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

open-source-contribution PR author is not from Axim or 2U

Projects

Status: Needs Triage

Development

Successfully merging this pull request may close these issues.

2 participants