Generate lab page blocks as markdown instead of Liquid includes - #237
Closed
ivorb wants to merge 4 commits into
Closed
Generate lab page blocks as markdown instead of Liquid includes#237ivorb wants to merge 4 commits into
ivorb wants to merge 4 commits into
Conversation
Per-task section, difficulty and duration previously existed only as prose in the hand-written "Lab at a glance" tables on the three landing pages. Nothing validated them against the task pages they described. Moves that data into task frontmatter (type, parent, order, section, difficulty, duration, access) and replaces the hand-written tables with an include that generates them, so the tables can no longer drift. Also: - Corrects level on six task pages. Every page carried level 300 inherited from its lab, but the tables listed per-task levels of L200-L400. Level now matches difficulty on every task. - Drops islab from task pages. Tasks are steps within a lab, not labs. - Marks B2, B3 and B4 as access: gated, each with what it requires and a quick way to check, since they need tenant rights or a Copilot licence. Verified by rendering the include against the real frontmatter: row counts and core/full totals match the values the tables previously stated by hand (A 35/2h25, B 35/1h50, C 30/2h). Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: dc4690cc-57d6-48a7-abc8-bc8570113ab1
Three surfaces over the same content, each generated from the frontmatter of the pages under Instructions/Consolidated. Nothing is hard-coded and there is no generated file to keep in sync: add a task page and it appears in all three. - workshop.html - instructor-led core path, ordered by lab then task, with cumulative elapsed time, optional tasks listed per session, and gated tasks called out as demo-only with what they require. - explore.html - every task as a card, filterable by lab, section, level, duration and access. - labs.json - the same catalogue as a machine-readable endpoint, for anything that needs the data without scraping the pages. index.md is untouched: it still filters to /Instructions/Exercises, so the published lab list is unaffected. Verified by rendering all three against the real frontmatter. Totals match the values the labs previously stated by hand - A 35/145 min, B 35/110, C 30/120 - and labs.json parses as valid JSON. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: dc4690cc-57d6-48a7-abc8-bc8570113ab1
Tasks B2, B3 and B4 need permissions or licensing many learners don't have, but each buried that below the setup instructions. B4 was the worst case: it told you to create a Foundry project, clone the code and run a preflight check, and only then mentioned that the whole task needs a Microsoft 365 Copilot licence. Adds _includes/gated-notice.html, rendered from the page's own frontmatter and placed directly under the title on all three, so a learner who can't do the task finds out in about thirty seconds instead of after provisioning. The notice states what the task needs, how to check, and - importantly - that skipping it costs nothing, because nothing else in the lab depends on these tasks. Also corrects the metadata to match what the pages actually say. B3 recorded 'permission to publish in your tenant' when the page asks for a Copilot licence, and B4's Node.js requirement existed only in prose. Splits the check into �erify and �erify_command so a shell command renders as code rather than being guessed at. Verified by rendering the include against all 30 consolidated pages: it appears on exactly the 3 gated ones and nowhere else. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: dc4690cc-57d6-48a7-abc8-bc8570113ab1
The lab instruction pages are read directly by platforms that never run
Liquid. GitHub's own markdown renderer is one: passing a page through the
GitHub markdown API returns
<p>{% include lab-tasks-table.html lab='A' %}</p>
so anyone browsing a lab on github.com sees the raw tag where the task table
should be. No lab page on main has ever contained Liquid - only index.md -
so this restores an existing convention rather than inventing one.
tools/generate_lab_blocks.py now writes both generated blocks - the task
table on each landing page, and the access notice on each gated task - as
real markdown between HTML comment markers, which are invisible in every
renderer. Frontmatter stays the single source of truth, and --check makes
drift a build failure, in the same pattern as Labfiles/_shared/sync.py.
A lab page missing its markers is an error, so a new lab cannot silently
ship without its table.
Removes _includes/ entirely. The web-only pages - workshop.md, explore.md,
labs.json - keep using Liquid directly; they are never consumed as raw
markdown.
Two things this fixes beyond portability:
- Link checking is back to 117 references from 103. The 14 task links became
literal markdown again, so check_links.py can see them.
- The cross-branch dependency disappears. Lab D's landing page referenced an
include that existed only on the PoC branch, which would have failed the
site build and is why that PR is currently a draft.
Verified: generated output matches what the Liquid produced, including the
totals (A 35 min core / 2 hours 25 minutes); the generator is idempotent;
and corrupting a block makes --check fail with a diff.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: dc4690cc-57d6-48a7-abc8-bc8570113ab1
ivorb
force-pushed
the
gated-task-notices
branch
from
August 17, 2026 14:34
a19c23a to
7410980
Compare
Collaborator
Author
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.
Recap of the problem
The lab instruction pages are read directly by platforms that never run Liquid. GitHub's own markdown renderer is one — passing a page through the GitHub markdown API returns:
So anyone browsing a lab on github.com sees the raw tag where the task table should be.
No lab page on
mainhas ever contained Liquid — onlyindex.md. This restores an existing convention rather than inventing one.How it works
tools/generate_lab_blocks.pywrites both generated blocks as real markdown between HTML comment markers, which are invisible in every renderer:Two blocks are generated: the task table on each landing page, and the access notice on each gated task.
Frontmatter stays the single source of truth.
--checkruns incontent-checksand makes drift a build failure — the same pattern asLabfiles/_shared/sync.py --check. A lab page missing its markers is a hard error, so a new lab can't silently ship without its table._includes/is removed entirely. The web-only pages —workshop.md,explore.md,labs.json— keep Liquid, because they're never consumed as raw markdown.Two problems this fixes beyond portability
Link checking is back to 117 references, from 103. The 14 task links became literal markdown again, so
check_links.pycan see them. That regression was introduced when the tables became generated.The cross-branch dependency disappears. Lab D's landing page referenced an include that existed only on the PoC branch — it would have failed the site build, and is why #234 is currently a draft. With generated markdown there's nothing to depend on.
Verification
--checkexit 1 with a diff, and re-running the generator restores itStacking
Branches off
gated-task-notices(#233), because it converts both includes — the table from #231 and the notice from #233. Merge order: #231 → #233 → this.If you'd rather not merge an "add include, then replace it" sequence, I can fold this back into #231 and #233 so they ship pre-rendered from the start. Say the word — it's mechanical, but it means force-pushing two PRs you may already have reviewed.