Part of the shared-curriculum sub-modules umbrella (#396), phase D of 4. Depends on #399 (phase C, website-side rendering complete) for the rollout ordering below, though the zoomcamp-ops checker work (step 1) can start independently/in parallel. Full design: _docs/planning/shared-curriculum-submodules-design.md, "Course-repository representation" section in full — this issue implements that section, it does not redesign it.
Goal
The course-repository side: the zoomcamp-ops v2 checker validates the new module.yaml/cohort.yaml fields, and real llm-zoomcamp content is migrated to use them for its genuinely-split modules (1, 3, 4). No schema version bump — this stays an additive schema-2 extension.
Scope
This work spans two repositories (DataTalksClub/zoomcamp-ops and DataTalksClub/llm-zoomcamp) plus a pinned reference in this repository. Sequence strictly, each step independently revertible (per the design doc's explicit "source publication must not precede the consumer that understands it" rule):
zoomcamp-ops: implement the twelve checker rules listed in the design doc's "Course-repository representation" section 4 (two new rule codes: sub_module_invalid, homework_anchor_invalid; reuse of existing codes elsewhere). Add fixtures: a third root module split into two parts (don't rewrite the existing 01-agentic-rag-equivalent fixture that other tests depend on), a part-anchor homework binding in a fixture cohort. One mutation test per new rule, in the existing tmp_path-copy style. Update zoomcamp-ops/docs/shared-curriculum-v2.md with the sub_modules/sub_module field documentation. Update templates/module-README.md and the process-course-video skill's authoring notes with a short paragraph on where a new lesson's unit entry goes inside a split module.
- This repository: confirm phase B/C are deployed; run a dry-run import against the
zoomcamp-ops fixture from step 1 (not synthetic test-only fixtures) to prove producer, checker, and website parser agree on one representation.
- This repository: update the pinned commit reference of the reusable checker workflow that
llm-zoomcamp's CI calls, to the zoomcamp-ops commit from step 1. This is itself a reviewed change (find the current pin location — likely a workflow file or checker-invocation config referencing a specific zoomcamp-ops ref).
llm-zoomcamp: author sub_modules: for modules 1 ("Part 1: RAG" / "Part 2: Agents"), 3 (five parts), and 4 (two parts) in three separate, individually revertible commits, matching the exact YAML shape in the design doc's section 1 example (real content_id UUIDs minted once, slug/title/optional summary per part). CI green on each commit before merging. cohorts/2026/cohort.yaml is explicitly NOT touched — all seven of its homework bindings stay module-level anchors, so Homework 1 keeps closing the whole of module 1 as one assignment (verified in the design doc: Q1-5 cover Part 1, Q6 covers Part 2, and splitting it would be an undesired content change, not a side effect of adding structure).
- Import the updated
llm-zoomcamp content into this website's database (production import, after independent review — do not run this against production without the owner's separate go-ahead per this repository's usual data-ingestion discipline).
Non-goals
- No schema version bump (confirmed in the design doc; both consumers' strict unknown-key rejection is the rollout safety net, not a version field).
- No folder/file restructuring in
llm-zoomcamp — lessons, images/, and code/ stay exactly where they are; the grouping lives only in module.yaml (design doc section 2 explains why folders moving would be actively harmful: it breaks every relative link and turns one shared images//code/ directory into a foldering problem for no content benefit).
- Splitting Homework 1 into two homeworks is explicitly NOT part of this issue — that would be a separate, deliberate content decision the owner has not made.
- The
mixed_homework_anchors checker rule (module-level and sub-module-level anchor coexisting on one module in one cohort) stays disabled unless the owner separately confirms it should be forbidden (open question 1 on the umbrella).
Dependencies
Acceptance criteria
Part of the shared-curriculum sub-modules umbrella (#396), phase D of 4. Depends on #399 (phase C, website-side rendering complete) for the rollout ordering below, though the
zoomcamp-opschecker work (step 1) can start independently/in parallel. Full design:_docs/planning/shared-curriculum-submodules-design.md, "Course-repository representation" section in full — this issue implements that section, it does not redesign it.Goal
The course-repository side: the
zoomcamp-opsv2 checker validates the newmodule.yaml/cohort.yamlfields, and realllm-zoomcampcontent is migrated to use them for its genuinely-split modules (1, 3, 4). No schema version bump — this stays an additive schema-2 extension.Scope
This work spans two repositories (
DataTalksClub/zoomcamp-opsandDataTalksClub/llm-zoomcamp) plus a pinned reference in this repository. Sequence strictly, each step independently revertible (per the design doc's explicit "source publication must not precede the consumer that understands it" rule):zoomcamp-ops: implement the twelve checker rules listed in the design doc's "Course-repository representation" section 4 (two new rule codes:sub_module_invalid,homework_anchor_invalid; reuse of existing codes elsewhere). Add fixtures: a third root module split into two parts (don't rewrite the existing01-agentic-rag-equivalent fixture that other tests depend on), a part-anchor homework binding in a fixture cohort. One mutation test per new rule, in the existingtmp_path-copy style. Updatezoomcamp-ops/docs/shared-curriculum-v2.mdwith thesub_modules/sub_modulefield documentation. Updatetemplates/module-README.mdand theprocess-course-videoskill's authoring notes with a short paragraph on where a new lesson's unit entry goes inside a split module.zoomcamp-opsfixture from step 1 (not synthetic test-only fixtures) to prove producer, checker, and website parser agree on one representation.llm-zoomcamp's CI calls, to thezoomcamp-opscommit from step 1. This is itself a reviewed change (find the current pin location — likely a workflow file or checker-invocation config referencing a specificzoomcamp-opsref).llm-zoomcamp: authorsub_modules:for modules 1 ("Part 1: RAG" / "Part 2: Agents"), 3 (five parts), and 4 (two parts) in three separate, individually revertible commits, matching the exact YAML shape in the design doc's section 1 example (realcontent_idUUIDs minted once,slug/title/optionalsummaryper part). CI green on each commit before merging.cohorts/2026/cohort.yamlis explicitly NOT touched — all seven of its homework bindings stay module-level anchors, so Homework 1 keeps closing the whole of module 1 as one assignment (verified in the design doc: Q1-5 cover Part 1, Q6 covers Part 2, and splitting it would be an undesired content change, not a side effect of adding structure).llm-zoomcampcontent into this website's database (production import, after independent review — do not run this against production without the owner's separate go-ahead per this repository's usual data-ingestion discipline).Non-goals
llm-zoomcamp— lessons,images/, andcode/stay exactly where they are; the grouping lives only inmodule.yaml(design doc section 2 explains why folders moving would be actively harmful: it breaks every relative link and turns one sharedimages//code/directory into a foldering problem for no content benefit).mixed_homework_anchorschecker rule (module-level and sub-module-level anchor coexisting on one module in one cohort) stays disabled unless the owner separately confirms it should be forbidden (open question 1 on the umbrella).Dependencies
zoomcamp-opschecker step itself can start in parallel).Acceptance criteria
zoomcamp-opschecker test suite green with the new rules and fixtures (verification happens in that repository, but must be confirmed and linked here before proceeding to step 2).zoomcamp-opsfixture succeeds against this website's importer with zero errors.llm-zoomcamp's CI passes against the new pin before any content commit lands.llm-zoomcampcontent commits (modules 1, 3, 4) pass CI independently and are reviewed/merged.llm-zoomcampcontent renders correctly on a local dev database: module 1's page shows two grouped parts with headings, Homework 1 still appears once (after Part 2, since it's module-anchored) closing the whole module, not split.