#1476·DeepTutor

feat(learning): persist mastery prerequisites and topic-source links

Author: evan188199-techCreated Sep 15, 2026Updated Sep 16, 2026

Background

Discussion #1290 proposes Mastery-gated progressive knowledge bases / Learn-Answer modes. Today a KnowledgePoint stores only its identity, name, type, and module. It cannot express which objectives are required before an objective, nor which selected topic sources justify that objective.

First-slice proposal

Add durable structural metadata to mastery objectives:

  • prerequisite_ids: required prerequisite objectives, suitable for a future hard eligibility gate.
  • topic_source_ids: selected non-goal topic sources that justify the objective.

Keep this first slice to the structural foundation:

  • Add both fields with empty defaults so legacy paths require no migration.
  • Resolve request-local client_ref / relation refs and persistent ids inside the mastery service transaction.
  • Remap prerequisite refs after final module/KP ids are allocated, including append renumbering and revise rewrites.
  • Validate that prerequisite targets exist on the same path; there are no self references or cycles; topic sources exist on the current topic and are not the goal source; and duplicate references are removed while preserving first occurrence.
  • Wire mastery_build, mastery_revise, topic create/edit, map payloads, and lossless frontend round-tripping.

Non-goals for this slice

  • No automatic relationship generation in topic drafts.
  • No retrieval restriction, mastery gate, or Learn-Answer behavior change.
  • No visual relationship editor.
  • No claim that source links prove factual correctness; access and availability checks remain downstream concerns.

Acceptance

  • Legacy paths load with empty relation lists.
  • A failed relation validation rolls back the whole mutation.
  • Replace creates fresh objective identities rather than inheriting evidence by positional id collision.
  • Append renumbering leaves no dangling prerequisites.
  • Rewriting an objective that is referenced across modules remaps every incoming edge.
  • Removing an objective still referenced by others reports its dependents.
  • Renaming or reordering objectives in the route editor preserves all relations.

Refs #1290