Skip to content

Microsoft Learn Documentation Monitor - How It Works

This guide explains how the automated Microsoft Learn documentation monitoring system works, when it runs, and how to use it locally.


Quick Reference

Question Answer
When does it run? Daily at 6:00 AM UTC via GitHub Actions
When is a PR created? Every Sunday (weekly baseline) OR when changes are detected
Where are changes stored? data/monitor-state.json (unified state), reports/monitoring/learn-changes-*.md (reports)
How to test locally? python scripts/learn_monitor.py --dry-run --limit 5

System Overview

The Learn monitor tracks ~207 Microsoft Learn URLs from the Microsoft Learn URLs watchlist and detects content changes that may require updates to framework documentation.

Part of Unified Monitoring System: The Learn Monitor is one source adapter within the broader unified monitoring architecture. See monitoring-architecture.md for the complete system design.

+---------------------------------------------------------------------+
|                      How the Learn Monitor Works                    |
+---------------------------------------------------------------------+
|                                                                     |
|  1. WATCHLIST                    2. FETCH & HASH                    |
|  +---------------------+         +---------------------+            |
|  | microsoft-learn-    |   -->   | For each URL:       |            |
|  | urls.md (209 URLs)  |         | - Fetch HTML        |            |
|  +---------------------+         | - Extract content   |            |
|                                  | - Compute SHA-256   |            |
|                                  +---------------------+            |
|                                           |                         |
|                                           v                         |
|  3. COMPARE                      4. CLASSIFY CHANGES                |
|  +---------------------+         +---------------------+            |
|  | data/monitor-       |   -->   | meaningful/minor/   |            |
|  | state.json (unified)|         | noise               |            |
|  | (previous hashes)   |         +---------------------+            |
|  +---------------------+                  |                         |
|                                           v                         |
|  5. OUTPUT                       6. CI TRIGGERS PR                  |
|  +---------------------+         +---------------------+            |
|  | reports/monitoring/ |         | Exit code 1 OR      |            |
|  | learn-changes-*.md  |         | Sunday = Create PR  |            |
|  +---------------------+         +---------------------+            |
|                                                                     |
+---------------------------------------------------------------------+
|  Framework: monitoring_shared.py provides state, classification,   |
|  control mapping, and report generation capabilities               |
+---------------------------------------------------------------------+

Key Files

File Purpose
scripts/learn_monitor.py Learn Monitor source adapter
scripts/monitoring_shared.py Unified monitoring framework (state, classification, control mapping)
scripts/regulatory_monitor.py Regulatory source adapter (Federal Register, FINRA)
.github/workflows/learn-monitor.yml GitHub Actions workflow for Learn Monitor
docs/reference/microsoft-learn-urls.md Watchlist of 209 URLs to monitor
data/monitor-state.json Unified state file (content hashes for all sources)
reports/monitoring/learn-changes-*.md Learn change reports
reports/monitoring/regulatory-changes-*.md Regulatory change reports

Change Classification

The monitor classifies changes into categories to prioritize review:

Classification Triggers Priority
CRITICAL Affects portal-walkthrough.md playbooks Immediate update required
HIGH UI navigation steps, policy language, deprecations Review and update
MEDIUM General content updates Review optional
NOISE Metadata, dates, formatting Ignored

Patterns Detected as Meaningful

The monitor looks for patterns that indicate substantive changes:

UI Navigation (affects playbooks):

  • Navigation keywords: click, select, go to, navigate
  • Portal references: Admin center, portal, Power Platform, Purview
  • UI elements: button, menu, tab, panel, dialog, blade

Policy/Compliance (affects controls):

  • Callout boxes: Important:, Warning:, Note:, Caution:
  • Requirement language: required, must, should not, prohibited
  • Compliance terms: compliance, audit, retention, DLP

Deprecation (requires action):

  • Lifecycle terms: deprecated, removed, no longer, retired
  • Release stages: preview, GA, generally available

GitHub Actions Workflow

The workflow (.github/workflows/learn-monitor.yml) runs:

  • Schedule: Daily at 6:00 AM UTC (cron: '0 6 * * *')
  • Manual: Can be triggered via workflow_dispatch

PR Creation Logic

IF (today is Sunday) OR (exit_code == 1):
    Create PR with changes
ELSE:
    No PR (just update state)

Baseline vs. Change Detection Runs

The workflow detects whether this is a baseline run (first successful execution) or a change detection run (subsequent executions):

Run Type Condition PR Body Content
Baseline State file doesn't exist before script runs Explains this establishes the baseline; no change reports expected; simplified 2-step review
Change Detection State file exists Full instructions to check reports and update affected documentation

How it works:

# Before running the monitor script:
if [ ! -f "data/learn-monitor-state.json" ]; then
    echo "is_baseline=true"  # First run
else
    echo "is_baseline=false"  # Subsequent run
fi

This ensures PR reviewers see appropriate instructions based on the run type.

Exit Codes:

Code Meaning Action
0 No meaningful changes detected No PR created
1 Meaningful changes detected PR created
2 Error during execution Check workflow logs

Testing Locally

1. Quick Test (5 URLs, no state changes)

python scripts/learn_monitor.py --dry-run --limit 5

2. Test with Verbose Output

python scripts/learn_monitor.py --dry-run --limit 10 --verbose

3. Debug a Single URL

python scripts/learn_monitor.py --url "https://learn.microsoft.com/en-us/power-platform/admin/managed-environment-overview"

4. Full Run (creates state file)

# First run establishes baseline (no report generated)
python scripts/learn_monitor.py

# Subsequent runs detect changes
python scripts/learn_monitor.py

Understanding the Output

State File (data/monitor-state.json)

The unified state file stores SHA-256 content hashes for all monitored sources (Learn + Regulatory):

{
  "last_updated": "2026-02-04T06:00:00Z",
  "sources": {
    "learn": {
      "urls": {
        "https://learn.microsoft.com/...": {
          "hash": "sha256:abc123...",
          "last_checked": "2026-02-04T06:00:00Z",
          "title": "Managed Environments Overview"
        }
      }
    },
    "regulatory": { ... }
  }
}

Change Reports (reports/monitoring/learn-changes-YYYY-MM-DD.md)

Reports are generated when changes are detected:

  • Date and summary of changes
  • List of affected URLs with classification
  • Diff snippets showing what changed
  • Recommended actions for each change

Verifying the Monitor is Working

Option 1: Check GitHub Actions

gh run list --workflow=learn-monitor.yml --limit 5

Option 2: Run Locally

# Dry run (no state changes)
python scripts/learn_monitor.py --dry-run --limit 5 --verbose

# Full baseline run
python scripts/learn_monitor.py --limit 20

Option 3: Check for Recent Reports

ls -la reports/monitoring/learn-changes-*.md

Responding to Change Alerts

When the monitor detects changes and creates a PR:

Use the /review-learn-changes Claude Code skill for automated analysis:

# 1. Checkout the PR branch
gh pr checkout {PR_NUMBER}

# 2. Run the review skill in Claude Code
/review-learn-changes

# 3. Claude will:
#    - Read and categorize all changes
#    - Propose specific documentation edits
#    - Apply edits with your confirmation
#    - Run validation (mkdocs build --strict)

# 4. Commit and push the documentation updates
git add .
git commit -m "docs: Apply Learn Monitor updates"
git push

# 5. Merge the PR
gh pr merge {PR_NUMBER} --squash

Option 2: Manual Review

  1. Review the change report in reports/monitoring/
  2. Assess the classification (CRITICAL, HIGH, MEDIUM, NOISE)
  3. Update affected documentation:
  4. CRITICAL: Update playbooks immediately
  5. HIGH: Update controls and playbooks
  6. MEDIUM: Review and update if needed
  7. NOISE: No action required
  8. Merge the PR to update the baseline state

PR Labels

Label Meaning
learn-watch All Learn Monitor PRs
needs-review Changes detected that may require documentation updates
documentation Documentation-related PR
automated Created by automation

End-to-End Verification Procedure

To verify the Learn Monitor works correctly, follow these steps:

Step 1: Establish Baseline (or use existing)

# If no state file exists for Learn URLs, create baseline
python3 scripts/learn_monitor.py --limit 5

# Expected: "Baseline established. No report generated on first run."
# State saved to: data/monitor-state.json (unified state file)

Step 2: Run Again (No Changes Expected)

python3 scripts/learn_monitor.py --limit 5

# Expected: "Meaningful changes: 0" - No report generated

Step 3: Simulate a Content Change

# Inject fake old content to trigger change detection
python3 -c "
import json
with open('data/monitor-state.json', 'r') as f:
    state = json.load(f)
first_url = list(state['sources']['learn']['urls'].keys())[0]
state['sources']['learn']['urls'][first_url]['normalized_content'] = 'OLD CONTENT'
state['sources']['learn']['urls'][first_url]['hash'] = 'sha256:fake_hash'
with open('data/monitor-state.json', 'w') as f:
    json.dump(state, f, indent=2)
"

# Run monitor - should detect change
python3 scripts/learn_monitor.py --limit 5

# Expected: "CHANGED: meaningful" and report generated

Step 4: Verify Report Created

ls -la reports/monitoring/learn-changes-*.md
cat reports/monitoring/learn-changes-*.md

Step 5: Restore State File

git checkout data/monitor-state.json
rm reports/monitoring/learn-changes-*.md

Verification Summary

Step Expected Result
Baseline run "Baseline established. No report generated."
No-change run "Meaningful changes: 0"
Simulated change "CHANGED: meaningful" + report generated
Report content Shows diff, affected controls, priority

Troubleshooting

Issue Cause Resolution
No state file exists Monitor hasn't run yet Run python scripts/learn_monitor.py to create baseline (stored in unified data/monitor-state.json)
URL fetch failures Network issues or URL changed Check URL validity, retry later
Too many false positives NOISE detection needs tuning Review patterns in monitoring_shared.py classification logic
Workflow not running GitHub Actions disabled Check repository Actions settings
State file corrupted JSON parsing errors Restore from backup or delete and re-run monitor (establishes new baseline)

  • Monitoring Architecture: monitoring-architecture.md - Comprehensive unified monitoring system documentation
  • AI-Assisted Review: learn-monitor-ai-enhancement.md - AI-assisted review implementation guide
  • Microsoft Learn URLs: microsoft-learn-urls.md - The watchlist of monitored URLs (~207 URLs)
  • Claude Code Skill: .claude/skills/review-learn-changes.md - User-invocable skill for reviewing changes
  • Repository Instructions: .claude/CLAUDE.md - Complete repository instructions (in project root)

FSI Agent Governance Framework v1.2 - February 2026