From workflow-skills
Generate a comprehensive curriculum performance report for a Datadog Learning Center curriculum area. Queries Snowflake for enrollment, completion, survey, RUM pageview, and demographic data; analyzes git history for content staleness; compiles a markdown report and interactive HTML dashboard. Use when asked to generate a course performance report, curriculum analytics, learning center metrics, course health report, or content staleness analysis for any curriculum area (APM, Logs, Infrastructure, Security, Monitors, RUM, etc.). Accepts a curriculum area label and category slug pattern as inputs.
npx claudepluginhub arosenkranz/claude-code-config --plugin workflow-skillsThis skill uses the workspace's default tool permissions.
Generates two output files for a named curriculum area:
Compares coding agents like Claude Code and Aider on custom YAML-defined codebase tasks using git worktrees, measuring pass rate, cost, time, and consistency.
Designs and optimizes AI agent action spaces, tool definitions, observation formats, error recovery, and context for higher task completion rates.
Designs, implements, and audits WCAG 2.2 AA accessible UIs for Web (ARIA/HTML5), iOS (SwiftUI traits), and Android (Compose semantics). Audits code for compliance gaps.
Generates two output files for a named curriculum area:
{area_lower}-course-performance-{YYYY-MM}.md){area_lower}-course-performance-{YYYY-MM}.html)All data comes from Snowflake (REPORTING.GENERAL) via the Snowflake MCP server and from git history in the learning-center/courses repo.
Collect before starting Phase 1. Required fields must be confirmed; optional fields use defaults if not provided.
| Input | Required | Default | Example |
|---|---|---|---|
area_label | Yes | -- | "APM", "Logs", "Infrastructure" |
category_slug_pattern | Yes | -- | %apm%, %log%, %infrastructure% |
report_as_of_date | No | today (YYYY-MM-DD) | "2026-03-10" |
time_range_months | No | 6 | 3, 6, 12 |
exclude_slugs | No | (none) | 'intro-to-apm', 'apm-draft' |
bundle_ids | No | (none -- skip LP sections) | 198361, 263268 |
courses_repo_path | No | /Users/alex.rosenkranz/workspace/learning-center/courses | -- |
output_dir | No | /Users/alex.rosenkranz/workspace/alex/alex-admin/reports | -- |
Run once during Phase 1 to discover courses:
WITH area_courses AS (
SELECT DISTINCT
c.ID AS course_id,
c.NAME AS course_name,
c.SLUG AS course_slug
FROM REPORTING.GENERAL.DIM_THINKIFIC_COURSE c
JOIN REPORTING.GENERAL.DIM_THINKIFIC_PRODUCT p
ON p.PRODUCTABLE_ID = c.ID AND p.PRODUCTABLE_TYPE = 'Course'
JOIN REPORTING.GENERAL.DIM_THINKIFIC_CATEGORY cat
ON cat.PRODUCT_ID = p.ID
WHERE LOWER(cat.SLUG) LIKE '{category_slug_pattern}'
AND c.SLUG NOT IN ({exclude_slugs_or_empty_string})
)
SELECT * FROM area_courses ORDER BY course_name
After user confirms the course list, freeze it as a VALUES CTE used in all subsequent queries:
WITH area_courses AS (
SELECT * FROM VALUES
({course_id_1}, '{course_name_1}', '{course_slug_1}'),
({course_id_2}, '{course_name_2}', '{course_slug_2}')
-- ... one row per approved course
AS t(course_id, course_name, course_slug)
)
This prevents the LIKE pattern from overmatching in later queries.
Apply these throughout report generation:
When suppressing, note "< minimum threshold" in the report cell rather than leaving it blank.
| Table | Purpose | Key Columns |
|---|---|---|
DIM_THINKIFIC_COURSE | Course catalog | ID, NAME, SLUG |
DIM_THINKIFIC_PRODUCT | Course-to-category bridge | PRODUCTABLE_ID, PRODUCTABLE_TYPE, ID |
DIM_THINKIFIC_CATEGORY | Category by slug | PRODUCT_ID, SLUG |
DIM_THINKIFIC_ENROLLMENT | Enrollment + completion events | ID, USER_ID, COURSE_ID, ENROLLMENT_TIMESTAMP, STATUS |
DEFAULT_LEARNING_CENTER_COURSE_SURVEY_RESPONSES | Survey answers (4 questions) | ENROLLMENT_ID, RESPONSE1-4 |
FACT_RUM_SITE_PAGEVIEW_HISTORY | Browser pageview events | PAGEVIEW_TIMESTAMP, PAGE_URLPATH, PAGE_URLHOST, SESSION_ID, DEVICE_TYPE, TIME_SPENT_ON_PAGE_SECONDS, SCROLL_DEPTH_PERCENTAGE, REFERRER_URL, GEO_COUNTRY |
DIM_THINKIFIC_USER | Learner profile | ID, EMAIL_DOMAIN, COMPANY |
COURSES_BY_TCD | Course-to-author mapping | COURSE_TITLE, PRIMARY_COURSE_DEVELOPER |
Key join patterns:
PAGE_URLPATH LIKE '/courses/take/' || ac.course_slug || '/%' and PAGE_URLHOST = 'learn.datadoghq.com'DEFAULT_LEARNING_CENTER_COURSE_SURVEY_RESPONSES.ENROLLMENT_ID = DIM_THINKIFIC_ENROLLMENT.IDDIM_THINKIFIC_ENROLLMENT.USER_ID = DIM_THINKIFIC_USER.IDVISITOR_ID in RUM is unpopulated -- use SESSION_ID for unique session countsRead references/queries.md before executing any query. All SQL templates are there.
area_label and category_slug_pattern with the user if not already provided.start_date and end_date from report_as_of_date and time_range_months.courses_repo_path (use ls {courses_repo_path} and match on slug or a close variant).Run using the frozen area_courses CTE and {start_date}/{end_date}:
bundle_ids (Section 6)bundle_ids (Section 8)Run using the frozen CTE:
For each course with a resolved repo directory:
git -C {courses_repo_path} log --reverse --format=%aI -- {repo_dir} | head -1 for creation date.git -C {courses_repo_path} log --format="%aI %s" -- {repo_dir} | head -20 for recent commits.lab_config or changelog (bulk config updates)splash page or TRAIN-2568 (site-wide splash page rework)alt + image or TRAIN-3773 (alt image formatting pass)partner timeout or timeout-only changesTrain-3160 or TRAIN-2834 (known bulk landing page/lab_config passes)references/report-template.md as the section structure. Fill each section with data from Phases 2-4.assets/dashboard-template.html as the base. Replace all /* PLACEHOLDER */ data arrays with actual values. Replace {area_label} with the confirmed area name.{output_dir}/.{output_dir}/{area_label_lower}-course-performance-{report_as_of_date_YYYY-MM}.md{output_dir}/{area_label_lower}-course-performance-{report_as_of_date_YYYY-MM}.htmlData notes: RUM
VISITOR_IDis unpopulated in this dataset; unique visitor counts useSESSION_IDas a proxy. Survey results reflect only learners who completed the course and submitted a survey (self-selection bias). Learning path completion rates reflect full-path completions only; partial completions are counted as enrolled. Data for the final partial month is noted as partial. Org cost and pricing data are not included in this report.