new-exam-scaffold

star 2

Scaffold a new certification exam into the LearningAzure workspace. Creates the folder structure, README files, StudyLog, Skills.psd1, and updates all cross-cutting files (scripts, governance, shared contract, top-level README). Use when asked to add a new exam, create an exam, scaffold an exam, or introduce a new certification.

Greg-T8 By Greg-T8 schedule Updated 4/15/2026

name: new-exam-scaffold description: 'Scaffold a new certification exam into the LearningAzure workspace. Creates the folder structure, README files, StudyLog, Skills.psd1, and updates all cross-cutting files (scripts, governance, shared contract, top-level README). Use when asked to add a new exam, create an exam, scaffold an exam, or introduce a new certification.' user-invokable: true argument-hint: '[exam code]'

New Exam Scaffold

Creates the complete folder structure and updates all cross-cutting files needed to introduce a new certification exam into the LearningAzure workspace. Uses the AZ-305 exam as the reference template.

When to Use

  • Adding a new Microsoft certification exam (e.g., AI-103, DP-100)
  • Replacing a retiring exam with its successor
  • Scaffolding a new exam structure from scratch

Input Required

Before scaffolding, gather the following from the user. Do not guess or infer — ask explicitly for anything not provided.

Input Description Example
Exam Code Uppercase exam identifier AI-103
Full Title Official exam title Designing and Implementing a Microsoft Azure AI Solution
Certification Name Credential name from Microsoft Azure AI Engineer Associate
Certification URL Microsoft credential page URL https://learn.microsoft.com/en-us/credentials/certifications/azure-ai-engineer/...
Study Guide URL Official study guide URL https://learn.microsoft.com/en-us/credentials/certifications/resources/study-guides/ai-103
Exam Domains Full domain → skill → task hierarchy with weights See Domain Structure Format
Start Date When study begins (or leave blank for later) 4/1/26
Expected Exam Date Target exam date 7/1/26
Study Pace Daily study commitment 1.5 hrs/day, 7 days/week
Include Labs? Whether to create hands-on labs structure Yes / No
Lab Domain Folders (Only if labs enabled) Subdirectory names for hands-on-labs compute, networking, storage

Domain Structure Format

Provide the official exam domain hierarchy. This populates the Skills.psd1 and coverage table in the exam README:

Domain 1: <Name> (<Weight>)
  Skill: <Skill Name>
    Task: <Task description>
    Task: <Task description>
  Skill: <Skill Name>
    Task: <Task description>
Domain 2: <Name> (<Weight>)
  ...

The domain/skill/task hierarchy can be found on the official Microsoft study guide page for the exam.


Phase 1: Create Exam Folder Structure

1.1 Directory Tree

Create the following directory structure under certs/:

certs/<EXAM>/
├── README.md
├── StudyLog.md
├── Skills.psd1
└── practice-questions/
    ├── README.md
    ├── .img/
    │   └── .gitkeep
    └── <NN>-<domain-slug>.md     ← one per domain

If labs are enabled, also create:

    └── hands-on-labs/
        ├── README.md
        └── <domain-folder>/      ← one per lab domain
            └── .gitkeep

Other folders (learning-paths/, video-courses/) are not created during scaffolding. They are added later when content is available.

1.2 File Templates

certs/<EXAM>/Skills.psd1 — Domain/Skill/Task Hierarchy

This file powers Invoke-AzStudySession.ps1 skill validation and practice exam organization. Create it before the README — it is the authoritative source for the domain/skill/task hierarchy.

# -------------------------------------------------------------------------
# Data: Skills.psd1
# Description: Domain, skill, and task hierarchy for the <EXAM> exam
# Context: <EXAM> — <Full Title>
# Author: Greg Tate
# -------------------------------------------------------------------------

@{
    Domains = @(
        @{
            Name   = '<Domain 1 full name>'
            Skills = @(
                @{
                    Name  = '<Skill 1 name>'
                    Tasks = @(
                        '<Task description>'
                        '<Task description>'
                    )
                }
                @{
                    Name  = '<Skill 2 name>'
                    Tasks = @(
                        '<Task description>'
                    )
                }
            )
        }
        @{
            Name   = '<Domain 2 full name>'
            Skills = @(
                # ... same structure
            )
        }
    )
}

Use the exact domain/skill/task wording from the official study guide — this data is the single source of truth for metadata matching.

certs/<EXAM>/README.md — Main Exam README

Sections in order:

  1. Title# <EXAM>: <Full Title> — Study Guide
  2. Objective statement with credential name
  3. Links — Certification page, study guide, study log
  4. Study Summary<!-- STUDY_SUMMARY --> marker block
  5. Coverage Dashboard## 📊 Exam Coverage with dashboard and coverage table
  6. Progress Tracker## 📚 Progress Tracker with per-skill phased format

Header and links format:

# <EXAM>: <Full Title> — Study Guide

**Objective:** Achieve the **<Certification Name>** certification using Microsoft Learn, practice exams, and video courses.

- **Certification Page:** [<Certification Name>](<certification-url>)
- **Official Study Guide:** [<EXAM> Study Guide](<study-guide-url>)
- **Study Log:** [Session-by-session study time tracker](./StudyLog.md)

<!-- STUDY_SUMMARY -->
**Hours Committed:** 0h · **Days Studied:** 0
<!-- /STUDY_SUMMARY -->

The <!-- STUDY_SUMMARY --> block is maintained by Update-CoverageTable.ps1. It replaces the legacy <!-- HOURS_COMMITTED --> marker.

Coverage section preamble (varies by labs):

With labs:

## 📊 Exam Coverage

Task-level coverage from [Practice Questions](./practice-questions/README.md) and [Hands-on Labs](./hands-on-labs/README.md).

Without labs:

## 📊 Exam Coverage

Task-level coverage from [Practice Questions](./practice-questions/README.md).

Dashboard table (between <!-- BEGIN COVERAGE DASHBOARD --> and <!-- END COVERAGE DASHBOARD --> markers):

Without labs (default):

<!-- BEGIN COVERAGE DASHBOARD -->

| Domain | Weight | Skills | Qs | Tasks Covered | Status |
| :----- | :----- | -----: | -: | :------------ | :----: |
| [1. <Short Name>](#domain-1) | XX–XX% | S | 0 | 0 / N (0%) | 🔴 |
| [2. <Short Name>](#domain-2) | XX–XX% | S | 0 | 0 / N (0%) | 🔴 |

**Totals:** 0 practice questions

**Legend:** 🟢 Strong (≥66%) · 🟡 Partial (33–65%) · 🔴 Low (<33%) — "Covered" = task has ≥1 practice question

> **Note:** Practice questions are those missed or not confidently answered correctly.

<!-- END COVERAGE DASHBOARD -->

With labs:

<!-- BEGIN COVERAGE DASHBOARD -->

| Domain | Weight | Skills | Qs | Labs | Tasks Covered | Status |
| :----- | :----- | -----: | -: | ---: | :------------ | :----: |
| [1. <Short Name>](#domain-1) | XX–XX% | S | 0 | 0 | 0 / N (0%) | 🔴 |
| [2. <Short Name>](#domain-2) | XX–XX% | S | 0 | 0 | 0 / N (0%) | 🔴 |

**Totals:** 0 practice questions · 0 hands-on labs

**Legend:** 🟢 Strong (≥66%) · 🟡 Partial (33–65%) · 🔴 Low (<33%) — "Covered" = task has ≥1 practice question or ≥1 lab

> **Note:** Practice questions are those missed or not confidently answered correctly.

<!-- END COVERAGE DASHBOARD -->
  • S = number of skills in each domain (from the exam study guide hierarchy).
  • N = total task count for each domain from the coverage table.
  • <Short Name> = abbreviated domain name for the dashboard (e.g., "Identity, Governance & Monitoring").
  • All new exams start with 🔴 status and zero counts.

Coverage table (between <!-- BEGIN COVERAGE TABLE --> and <!-- END COVERAGE TABLE --> markers):

Domain sections use the compact <details>/<summary> format (no ### headings):

Without labs (default):

<a id="domain-1"></a>
<details>
<summary><b>Domain 1: <Name> (<Weight>)</b> — N tasks · 0 Qs</summary>

| Skill | Task | Qs |
| :--- | :--- | -: |
| <Skill Name> (T tasks) | <Task description> | 0 |
|  | <Task description> | 0 |

</details>

With labs:

<a id="domain-1"></a>
<details>
<summary><b>Domain 1: <Name> (<Weight>)</b> — N tasks · 0 Qs · 0 Labs</summary>

| Skill | Task | Qs | Labs |
| :--- | :--- | -: | -: |
| <Skill Name> (T tasks) | <Task description> | 0 | 0 |
|  | <Task description> | 0 | 0 |

</details>

Dashboard status indicators:

  • 🟢 Strong (≥66% tasks covered)
  • 🟡 Partial (33–65%)
  • 🔴 Low (<33%)

Progress Tracker — per-skill phased format:

---

## 📚 Progress Tracker

**Goal:** Pass <EXAM> at the <duration> mark (~<Expected Exam Date>) · **Pace:** <Study Pace>

### Per-Skill Workload & Day Allocation

| # | Domain | Skill | ML (min) | PQs | PQ (min) | Total (min) | Days |
| -: | :----- | :---- | -------: | --: | -------: | ----------: | ---: |
| 1 | <Domain 1 short name> | <Skill 1 name> | 0 | 0 | 0 | 0 | 0 |
| 2 | <Domain 1 short name> | <Skill 2 name> | 0 | 0 | 0 | 0 | 0 |
| 3 | <Domain 2 short name> | <Skill 3 name> | 0 | 0 | 0 | 0 | 0 |
| | **Totals** | | **0** | **0** | **0** | **0** | **0** |

> ML = Microsoft Learn module time · PQs = MeasureUp practice questions · PQ (min) = PQs × ~6 min

### Phase 1 — Learn + Practice per Skill (<start date> – <end date>)

| # | Domain | Skill | Tasks | Expected Start | Status | Started | Completed | Days |
| -: | :----- | :---- | ----: | :------------- | :----- | :------ | :-------- | ---: |
| 1 | <Domain 1 short name> | <Skill 1 name> | 0 | <date> | Not Started | | | |
| 2 | <Domain 1 short name> | <Skill 2 name> | 0 | <date> | Not Started | | | |
| 3 | <Domain 2 short name> | <Skill 3 name> | 0 | <date> | Not Started | | | |

### Phase 2 — Review & Practice Exams (<start date> – <end date>)

| # | Modality | Expected Start | Status | Started | Completed | Days |
| -: | :------- | :------------- | :----- | :------ | :-------- | ---: |
| N+1 | Video Course | <date> | Not Started | | | |
| N+2 | Practice Exam (Tutorials Dojo) | <date> | Not Started | | | |
| N+3 | Practice Exam (Microsoft Assessment) | <date> | Not Started | | | |

**Legend:** Not Started · In Progress · Completed

Notes on per-skill workload table:

  • ML (min) — Sum of Microsoft Learn module times for the skill’s modules. Populate from the learning path module lengths.
  • PQs — Estimated MeasureUp practice questions. Roughly proportional to domain weight.
  • PQ (min) — PQs × ~6 min (estimated time per practice question).
  • Days — Total (min) ÷ daily study minutes.
  • Populate values after identifying Microsoft Learn paths and practice question sources. Use zeroes as placeholders if not yet known.

Phase 1 date calculation:

  • Start from the study start date
  • Add days allocated per skill sequentially
  • Phase 2 begins after Phase 1 ends

Script compatibility: The per-skill progress tracker format (header | # | Domain | Skill |) is not auto-detected by Update-ProgressTrackerDays.ps1, which only matches the legacy | Priority | Modality | header. Days tracking for the per-skill format is done by Invoke-AzStudySession.ps1 session logging. The Tasks and Hours columns are auto-populated by Update-CoverageTable.ps1 from Skills.psd1 and StudyLog.md.

certs/<EXAM>/StudyLog.md — Study Time Tracker

# Study Log — <EXAM>: <Full Title>

This log tracks individual study sessions for the **<EXAM>** exam. Fill in **End**, **Duration**, and **Notes** when the session concludes.

---

## Session History

| # | Date | Start | End | Duration | Mode | Skill | Notes |
|:--|:-----|:------|:----|:---------|:-----|:------|:------|

The Mode column values correspond to Invoke-AzStudySession.ps1 modes (e.g., MSLearn, PracticeQuestion, Video, Lab). The Skill column records which specific skill was studied.

certs/<EXAM>/practice-questions/README.md — Practice Questions Index

This file serves as an index page linking to per-domain practice question files.

# Practice Exam Questions — <EXAM>

Accounts for questions missed or unsure about in the practice exams. Questions are organized into per-domain files to keep each file small and responsive.

| # | Domain | File | Qs |
| -: | :----- | :--- | -: |
| 1 | <Domain 1 name> | [<filename>.md](<filename>.md) | 0 |
| 2 | <Domain 2 name> | [<filename>.md](<filename>.md) | 0 |
...

certs/<EXAM>/practice-questions/<NN>-<domain-slug>.md — Per-Domain Practice Question Files

Create one file per exam domain, using numbered-prefix kebab-case names (e.g., 01-identity-governance-monitoring.md). Each file uses the heading hierarchy: # domain title → ## skill subheadings → ### question headings.

# Practice Questions — <Domain Name>

Accounts for questions missed or unsure about in the practice exams.

---

## <Skill 1 Name>

## <Skill 2 Name>

1.3 Optional: Hands-on Labs Structure

Created only when the user confirms labs are planned for this exam.

certs/<EXAM>/hands-on-labs/README.md — Lab Catalog

# <EXAM> Hands-on Labs

Practice labs that reinforce exam objectives through real Azure deployments.

All labs follow the governance policies in [Governance-Lab.md](../../../.assets/shared/Governance-Lab.md).

---

## 📈 Lab Statistics

- **Total Labs:** 0
<domain counts — one line per domain, all 0>

---

## 🧪 Labs

*No labs yet. Labs are built as practice exam questions reveal knowledge gaps.*

---

## 📋 Governance & Standards

- **Governance Policy:** [Governance-Lab.md](../../../.assets/shared/Governance-Lab.md)
- **Shared Contract:** [lab-shared-contract](../../../.github/skills/lab-shared-contract/SKILL.md)

Phase 2: Update Cross-Cutting Files

2.1 Top-Level README.md

Add the new exam to the Certifications table (under ## 📚 Certifications):

| 📕 [**<EXAM>**](certs/<EXAM>/README.md) | <Certification Name> | Not Started | |
  • Use the appropriate emoji color (📗📙📘📕) and status text based on start date.
  • If a start date is provided, use In Progress as the status and add the start date in the Duration column.
  • Adding the exam to this table makes it discoverable by Get-ActiveExam.ps1, which all maintenance scripts use for dynamic exam discovery.

2.2 Governance-Lab.md

Only update if the exam includes hands-on labs.

Add the exam code to the title scope:

Standards for all Terraform and Bicep labs (AZ-104, AZ-305, <NEW-EXAM>).

If the exam has distinct resource types, add an exam-specific resource prefix table under §2.2 Resource Naming following the format of existing prefix tables:

#### <EXAM> Prefixes

| Resource | Prefix |
| -------- | ------ |
| ...      | ...    |

Add the exam to the Project tag examples in §1.2 Required Tags:

| Project | AZ-104 / AZ-305 / <NEW-EXAM> |

2.3 lab-shared-contract SKILL.md

Only update if the exam includes hands-on labs.

R-001 — Add the lowercase exam code to the <exam> definition:

- `<exam>`: lowercase exam code (`az104`, `ai102`, `<new-exam-lowercase>`)

R-005 — Add the exam code to the Project tag examples:

| Project | Uppercase: `AZ-104` or `AZ-305` or `<NEW-EXAM>` |

New R-0xx (if exam has distinct resource types) — Add an exam-specific resource naming rule following the pattern of R-002 and R-003:

## R-0xx: Resource Naming — <EXAM> Prefixes

Pattern: `<prefix>-<role>[-instance]`

| Resource | Prefix | Random Suffix? |
| -------- | ------ | -------------- |
| ...      | ...    | ...            |

Assign the next available R-0xx ID.

2.4 Scripts

All maintenance scripts use dynamic exam discovery via Get-ActiveExam.ps1, which parses the main README's certifications table. Adding the exam to the top-level README (§2.1) automatically makes it visible to these scripts:

  • Update-CoverageTable.ps1
  • Invoke-PracticeExamReorganizer.ps1
  • Update-StudyLogGaps.ps1

No ValidateSet updates or hardcoded exam lists are needed in these scripts.

Update-LabReferences.ps1

Only update if the exam includes hands-on labs. Add the exam to the $DomainConfig hashtable with domain folder→display-name mappings:

$DomainConfig = @{
    'AZ-104' = [ordered]@{
        'storage'             = 'Storage'
        'compute'             = 'Compute'
        'monitoring'          = 'Monitoring'
        'identity-governance' = 'Identity & Governance'
        'networking'          = 'Networking'
    }
    '<NEW-EXAM>' = [ordered]@{
        '<domain-folder>' = '<Display Name>'
        # ... one entry per lab domain folder
    }
}

The domain ordering determines how labs are grouped and sequenced in the catalog.

Invoke-AzStudySession.ps1

Standard exams under certs/<EXAM>/ using StudyLog.md and Skills.psd1 require no changes — the script discovers them automatically via Get-ActiveExam.ps1 and defaults to certs\<EXAM> folder and StudyLog.md.

Only add entries if the exam uses a non-standard folder or log file:

  • $ExamFolderMap — Add only if the exam folder is not certs\<EXAM>.
  • $ExamLogFileMap — Add only if the log file is not StudyLog.md.

Update-ProgressTrackerDays.ps1

The per-skill progress tracker format (header | # | Domain | Skill |) used by new exams is not auto-detected by this script. The script only matches the legacy | Priority | Modality | header pattern. No changes are needed — days tracking for the per-skill format is handled by Invoke-AzStudySession.ps1 session logging instead. The Tasks and Hours columns are auto-populated by Update-CoverageTable.ps1.

Invoke-ContentMaintenance.ps1

No changes required. This orchestrator script runs all maintenance scripts in dependency order:

  1. Invoke-PracticeExamReorganizer (when -Reorganize is specified)
  2. Update-StudyLogGaps
  3. Update-ProgressTrackerDays
  4. Update-CoverageTable (also generates the root README activity table)
  5. Update-LabReferences
  6. Invoke-CollapseDetailBlock
  7. Remove-UnusedImages

Since child scripts use dynamic discovery, the orchestrator automatically processes new exams once they are added to the top-level README.

2.5 Skills

lab-catalog-updater/SKILL.md

Only update if the exam includes hands-on labs. Add the exam to the Scope section and define its domain ordering:

- `certs/<NEW-EXAM>/hands-on-labs/README.md`

Also add a domain ordering entry following the existing pattern:

- **<NEW-EXAM>:** <Domain1>, <Domain2>, ...

The domain ordering determines how labs are grouped and sequenced in the catalog.

exam-question-organizer/SKILL.md

Add the exam to the Per-domain exams target table:

| <NEW-EXAM> | `certs/<NEW-EXAM>/practice-questions/<NN>-<domain-slug>.md` (one row per domain file) | `certs/<NEW-EXAM>/README.md` — Practice Exam Coverage section | `certs/<NEW-EXAM>/README.md` — Practice Exam Coverage section |

Phase 3: Validation

After all files are created and updated, verify:

Check How
Folder structure exists List certs/<EXAM>/ directory recursively
Skills.psd1 is valid Run Import-PowerShellDataFile certs/<EXAM>/Skills.psd1 — should parse without errors
README has coverage markers Confirm <!-- BEGIN COVERAGE TABLE -->, <!-- END COVERAGE TABLE -->, <!-- BEGIN COVERAGE DASHBOARD -->, and <!-- END COVERAGE DASHBOARD --> markers exist
README has study summary Confirm <!-- STUDY_SUMMARY --> and <!-- /STUDY_SUMMARY --> markers exist
Content maintenance passes Run Invoke-ContentMaintenance.ps1 -WhatIf — all steps should complete without errors
Study session works Run Invoke-AzStudySession.ps1 -Action Start -Mode <NEW-EXAM> then -Action Stop
Top-level README links resolve Confirm the certifications table links to existing certs/<EXAM>/README.md
Governance references exam (Labs only) Search Governance-Lab.md for the exam code
Lab domain config (Labs only) Confirm Update-LabReferences.ps1 $DomainConfig contains the new exam entry
Domain count matches Count tasks in coverage table vs. <summary> tag totals
No raw unicode escapes Scan all generated files for literal unicode escape sequences (\uXXXX, \u{XXXXX}, &#xNNNN;). If any are found, replace them with the actual rendered character.

Rules

  • Do not pre-populate question or lab content — those are built organically from practice exams.
  • Do initialize all coverage counts to zero.
  • Do use the compact <details>/<summary> format for domain sections (no ### headings).
  • Do preserve exact domain/skill/task wording from the official study guide — these are the single source of truth for the exam-question-organizer metadata matching.
  • Do assign the next available R-0xx ID when adding shared contract rules.
  • Do follow existing file formatting conventions exactly (line endings, marker comments, table alignment).
  • Do not modify any existing exam's content — only add the new exam and update shared references.
  • Do create Skills.psd1 before the README — it is the authoritative source for the domain/skill/task hierarchy.
  • Do use <!-- STUDY_SUMMARY --> markers (not the legacy <!-- HOURS_COMMITTED -->).
  • Do generate per-domain practice question files (not a single combined file).

Output

After completing the scaffold, report:

  1. Files Created — Full list of new files and directories
  2. Files Updated — Each cross-cutting file modified with a one-line description of the change
  3. Validation Results — Pass/fail for each check in Phase 3
  4. Next Steps — Remind user to populate the per-skill workload table from Microsoft Learn module times and practice question estimates
Install via CLI
npx skills add https://github.com/Greg-T8/LearningAzure --skill new-exam-scaffold
Repository Details
star Stars 2
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator