Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
147 commits
Select commit Hold shift + click to select a range
f37eda6
docs: add user-facing documentation site (MkDocs Material)
tezheng May 26, 2026
e15d9f1
docs: add docs/README.md for contributor workflow + exclude it from t…
tezheng May 27, 2026
6109af4
docs(review): record fact-check findings against microsoft/winml-cli …
tezheng May 27, 2026
e440a59
docs(fix): apply 47 validated fixes from microsoft/winml-cli source r…
tezheng May 27, 2026
ed28a40
docs(install): drop redundant tagline paragraph (and its stale EP enu…
tezheng May 27, 2026
612d692
docs: expand analyze/optimize content, rename hub→catalog (#769)
DingmaomaoBJTU May 27, 2026
9f182c8
Release/v0.1.0 back to main (#758)
xieofxie May 27, 2026
a30d5a9
fix integration test(only unit test _skip_winml_ep_init) (#760)
fangyangci May 27, 2026
04b74ae
Remove WindowsAppRuntimeVersion from SysInfo (#761)
timenick May 27, 2026
9feca07
fix: move VitisAI EP to last in ordering and fit catalog table width …
DingmaomaoBJTU May 27, 2026
5bdb1fb
example: add readme and example.py for microsoft/table-transformer-de…
xieofxie May 28, 2026
c8f7c55
docs: restructure README into 5-section layout (#770)
hi-brenda May 28, 2026
fd0e44a
docs: fix duplicate Releases row and switch install to pip (#784)
timenick May 28, 2026
7319628
fix: config validates device/EP combination without system check (#780)
xieofxie May 28, 2026
9ec0345
chore: enable checking types and fix analyze folder (#768)
xieofxie May 28, 2026
80bc7e0
examples: add 12 builtin model recipes (fp16 + w8a8 + w8a16, 36 confi…
ssss141414 May 29, 2026
7152b82
Validate model task in config. (#723)
chinazhangchao May 29, 2026
32e2584
fix: run eval failed on amd (#783)
KayMKM May 29, 2026
3dcee5b
fix(inspect): validate --task at Click time with clean error (#546) (…
ziyuanguo1998 May 29, 2026
3f0a890
fix: align `winml catalog` `-t` short flag with other commands (#541)…
ziyuanguo1998 May 29, 2026
b59a5d8
Skip some e2e test cases or assertion (#796)
zhenchaoni Jun 1, 2026
4db0187
example: add microsoft/swin-large-patch4-window7-224 (#787)
xieofxie Jun 2, 2026
9c94bbc
feat(timm): enable timm image-classification models via library routi…
vortex-captain Jun 2, 2026
679a11b
Fix model-task inconsistency for vision feature-extraction models (#786)
zhenchaoni Jun 2, 2026
2d967c1
Fix integration tests. (#773)
chinazhangchao Jun 2, 2026
4923fd9
chore: typechecking build, commands, compiler folder (#789)
xieofxie Jun 3, 2026
d96aa0c
refactor(task): relocate map_task_synonym to loader.task as to_optimu…
timenick Jun 3, 2026
c047cf3
fix: unify verbosity declaration and stderr-only logger output (#566)…
xieofxie Jun 3, 2026
cd951a9
fix: align analyzer API EP list with CLI (#803)
DingmaomaoBJTU Jun 3, 2026
17fdfc3
feat(eval): add depth-estimation evaluator (#326) (#437)
jeon185 Jun 3, 2026
4b47688
Enable telemetry in shipped wheel and reword consent as "unlinked pse…
timenick Jun 4, 2026
881f1dc
ci: split scheduled pipelines into weekly Eval Report and daily E2E T…
KayMKM Jun 4, 2026
af1cbe2
feat: show tqdm for _ensure_provider_ready (#788)
xieofxie Jun 4, 2026
be6a939
fix(export): resolve timm image_size from pretrained_cfg (#806)
vortex-captain Jun 4, 2026
cf96c14
feat: update color for --list-device (#812)
xieofxie Jun 4, 2026
244f7b8
update eval scripts: add ONNX size tracking and output sanitization (…
DingmaomaoBJTU Jun 4, 2026
b98c818
docs: fill Reference, Troubleshooting, and Contributing pages
DingmaomaoBJTU Jun 4, 2026
86daf43
docs: add Python API, Output Layout, and Supported Models reference p…
DingmaomaoBJTU Jun 4, 2026
c55cf55
docs: fix factual errors in reference pages after source verification
DingmaomaoBJTU Jun 4, 2026
03ce1e0
docs: fix factual errors in supported-models.md
DingmaomaoBJTU Jun 4, 2026
fab8069
docs: remove custom build logic section from supported-models
DingmaomaoBJTU Jun 4, 2026
81abd26
docs: add analyze_result.json section to output-layout from actual build
DingmaomaoBJTU Jun 4, 2026
e800c35
docs: add 'Build from Your Own ONNX File' tutorial
DingmaomaoBJTU Jun 4, 2026
222227b
docs: rewrite ONNX tutorial as 'Bring Your Own Model'
DingmaomaoBJTU Jun 4, 2026
66c521d
docs: rename tutorial to 'Bring Your Own ONNX Model'
DingmaomaoBJTU Jun 4, 2026
99a80dd
docs: add QNN GPU (Adreno) device to EP table
DingmaomaoBJTU Jun 4, 2026
644d832
docs: add Bring Your Own ONNX Model to tutorials overview
DingmaomaoBJTU Jun 4, 2026
d92636a
docs: fix analyze/optimize workflow in BYOM tutorial
DingmaomaoBJTU Jun 4, 2026
d1a3fba
docs: fix analyze/optimize output in BYOM tutorial from actual runs
DingmaomaoBJTU Jun 4, 2026
d9ccc8a
docs: fix build stage defaults in BYOM tutorial
DingmaomaoBJTU Jun 4, 2026
441e03d
docs: fix 8 factual errors found during audit
DingmaomaoBJTU Jun 5, 2026
55ee223
docs: add Agent Skill reference page
DingmaomaoBJTU Jun 5, 2026
849298d
docs: reorder quickstart to inspect before export
DingmaomaoBJTU Jun 5, 2026
b53add9
docs: move agent skill page to Getting Started
DingmaomaoBJTU Jun 5, 2026
acbc074
docs: fix agent skill usage section for accuracy
DingmaomaoBJTU Jun 5, 2026
94c71ea
docs: add ONNX input entry point to pipeline diagram
DingmaomaoBJTU Jun 5, 2026
f61b209
docs: add EP alias column to eps-and-devices table
DingmaomaoBJTU Jun 5, 2026
05048f2
docs: document auto/all for --device and --ep flags
DingmaomaoBJTU Jun 5, 2026
5f87603
docs: fix compile validation description to match code
DingmaomaoBJTU Jun 5, 2026
9551e34
docs: fix commands overview factual errors
DingmaomaoBJTU Jun 5, 2026
abd8ef2
docs: note ort vs qairt compiler backends in compile step
DingmaomaoBJTU Jun 5, 2026
1c6ac5c
write Qwen3 composite model sample from source code
DingmaomaoBJTU Jun 5, 2026
912cc9f
add ORT compiler backend to tutorial compile step
DingmaomaoBJTU Jun 5, 2026
94e060d
clarify ORT vs QAIRT compiler backends in compile sections
DingmaomaoBJTU Jun 5, 2026
274fcaf
document auto field behavior and fix convnext compile tabs
DingmaomaoBJTU Jun 5, 2026
6ad30d6
emphasize winml_build_config.json as reproducible CI/CD artifact
DingmaomaoBJTU Jun 5, 2026
1e5e057
add CI/CD reproducibility callouts for build config
DingmaomaoBJTU Jun 5, 2026
526c9c3
fix EP table: add missing EPs, correct device order and notes
DingmaomaoBJTU Jun 5, 2026
16bf426
simplify docs contributing page to reference repo CONTRIBUTING.md
DingmaomaoBJTU Jun 5, 2026
a27d635
add runtime check rules download step to contributing
DingmaomaoBJTU Jun 5, 2026
da79281
remove trivial 'config file empty' troubleshooting entry
DingmaomaoBJTU Jun 5, 2026
2ac1e8a
note that compile is off by default in winml build
DingmaomaoBJTU Jun 5, 2026
a5f6361
expand unsupported nodes guidance with optim-config workflow
DingmaomaoBJTU Jun 5, 2026
96acb21
add normalize-before-analyze troubleshooting tip
DingmaomaoBJTU Jun 5, 2026
c5217fa
add --compile flag to config example in troubleshooting
DingmaomaoBJTU Jun 5, 2026
e7d8536
remove Device and EP Issues section from troubleshooting
DingmaomaoBJTU Jun 5, 2026
72c340b
remove Quantization/Compilation and Output/File sections from trouble…
DingmaomaoBJTU Jun 5, 2026
e68817b
add --rebuild tip to troubleshooting general tips
DingmaomaoBJTU Jun 5, 2026
5bc6927
docs: add mike version control plugin for multi-version docs
DingmaomaoBJTU Jun 5, 2026
be316f3
docs: reorganize troubleshooting by component, replace mermaid with S…
DingmaomaoBJTU Jun 5, 2026
bb3a40c
docs: move Analyze section after Export in how-it-works
DingmaomaoBJTU Jun 5, 2026
a7bec60
docs: replace qwen3 composite sample with clip composite sample
Jun 8, 2026
f8c31f6
merge: resolve conflicts by accepting main for non-docs files
DingmaomaoBJTU Jun 8, 2026
b5cd5c1
docs: remove internal planning files (superpowers/, naming-convention…
DingmaomaoBJTU Jun 8, 2026
b55c64b
docs: restore naming-convention, pytest-best-practices, and README (p…
DingmaomaoBJTU Jun 8, 2026
494c24f
docs: reset e2e test files and .gitignore to main (not part of docs c…
DingmaomaoBJTU Jun 8, 2026
cbfd909
chore: reset e2e tests to match main exactly
DingmaomaoBJTU Jun 8, 2026
93a19a3
docs: exclude internal files from build, gitignore versions.json
DingmaomaoBJTU Jun 8, 2026
606cd26
docs: generalize NPU prerequisites (not Qualcomm-only, QAIRT SDK only…
DingmaomaoBJTU Jun 8, 2026
044893a
docs: address review comments on perf pages
DingmaomaoBJTU Jun 9, 2026
60d61e2
Fix: link 404 in doc (#840)
ssss141414 Jun 9, 2026
958178b
docs: address timenick review comments
DingmaomaoBJTU Jun 9, 2026
81e54fb
docs: rename 'Build Config Schema' to 'Config Schema' (it's general-p…
DingmaomaoBJTU Jun 9, 2026
c42702a
docs: move Python API to last in Reference nav
DingmaomaoBJTU Jun 9, 2026
f5b7ecb
docs: fix Qwen3->CLIP in samples description; add doc-check extension
DingmaomaoBJTU Jun 9, 2026
d818286
docs: simplify installation prerequisites
DingmaomaoBJTU Jun 9, 2026
dfec878
docs: remove QNN/OpenVINO SDK installation references
DingmaomaoBJTU Jun 9, 2026
ed7e9ab
docs: replace Unicode box-drawing chars with ASCII for consistent ren…
DingmaomaoBJTU Jun 9, 2026
bf01055
docs: fix incorrect claim about Coding Agent auto-reading skills/
DingmaomaoBJTU Jun 9, 2026
8ba1a46
docs: remove redundant 'Key principles' section (already in table above)
DingmaomaoBJTU Jun 9, 2026
48081c7
docs: remove unnecessary 'Updating the skill' section
DingmaomaoBJTU Jun 9, 2026
b884b25
docs: add eval to config tree, link to Config Schema reference page
DingmaomaoBJTU Jun 9, 2026
77fa880
docs: clarify -c config.json is optional for winml build
DingmaomaoBJTU Jun 9, 2026
d018281
docs: add cross-references to Reference pages (Config Schema, Output …
DingmaomaoBJTU Jun 9, 2026
5fd701f
docs: fix cross-references - remove Output Layout from export, add Su…
DingmaomaoBJTU Jun 9, 2026
32351f8
docs: update CLI flags for --flag/--no-flag pairs (per PR #844)
DingmaomaoBJTU Jun 9, 2026
5c24711
docs: fix catalog flag short forms (-t is for --task, not --model-type)
DingmaomaoBJTU Jun 9, 2026
6112368
docs: remove incorrect -k pitfall and fix -k → -t for --task
DingmaomaoBJTU Jun 9, 2026
141181c
docs: add winml analyze to primitives-and-pipeline page
DingmaomaoBJTU Jun 9, 2026
018adee
docs: fix EP context description - not QNN-family, separate vendors
DingmaomaoBJTU Jun 9, 2026
2a4e34c
docs: clarify ort compiler backend uses ORT built-in EP context
DingmaomaoBJTU Jun 9, 2026
c2346e3
Revert "docs: clarify ort compiler backend uses ORT built-in EP context"
DingmaomaoBJTU Jun 9, 2026
7f781a0
docs: align tutorials, fix nav categorization, simplify EP tables
DingmaomaoBJTU Jun 9, 2026
662f173
docs: correct option flags and aliases in command tables
ZiyuanGuo Jun 9, 2026
25d11bb
Merge branch 'docs/draft' of https://github.com/microsoft/winml-cli i…
ZiyuanGuo Jun 9, 2026
744720d
docs: restore --hierarchy/--no-hierarchy pairs per merged PR #844
DingmaomaoBJTU Jun 9, 2026
32644c2
adjust config-and-build.md order
chinazhangchao Jun 10, 2026
c846a7d
docs: update quickstart and index landing page
hi-brenda Jun 10, 2026
6be9dc1
Merge branches 'main' and 'docs/draft' of https://github.com/microsof…
DingmaomaoBJTU Jun 10, 2026
9be4f9f
docs: update supported-models to match actual catalog data
DingmaomaoBJTU Jun 10, 2026
2f383b2
docs: remove size column from supported-models
DingmaomaoBJTU Jun 10, 2026
375d465
docs: add UI quickstart and update index landing page
hi-brenda Jun 10, 2026
cb1215c
docs: remove End-to-End Tour page and update references
DingmaomaoBJTU Jun 10, 2026
e40ad9c
docs: add UI Quickstart to nav
DingmaomaoBJTU Jun 10, 2026
6c8f2c3
docs: remove ConvNeXt primitives page and fix all references
DingmaomaoBJTU Jun 10, 2026
570f9b4
docs: rename ConvNeXt tutorial, remove site logo icon
DingmaomaoBJTU Jun 10, 2026
bcdd421
docs: expand What you learned section in BERT sample
hi-brenda Jun 10, 2026
621ff23
docs: add repo access link to index and tutorials pages
hi-brenda Jun 10, 2026
e4ecb6c
docs: rename site to Windows ML CLI, hide logo icon
DingmaomaoBJTU Jun 10, 2026
5484ab6
docs: expand hierarchy tagging section in load-and-export
DingmaomaoBJTU Jun 11, 2026
dfad05f
docs: add concrete tag examples, mermaid diagram, and real export data
DingmaomaoBJTU Jun 11, 2026
6d4f4d4
docs: fix inaccuracies in load-and-export tagging section
DingmaomaoBJTU Jun 11, 2026
191a8e9
docs: move Load and export before Primitives in nav
DingmaomaoBJTU Jun 11, 2026
cbe63fc
docs: remove unimplemented optimizer scoping claim
DingmaomaoBJTU Jun 11, 2026
facf95e
docs: enrich perf-and-monitoring with real output, flag table, JSON e…
DingmaomaoBJTU Jun 11, 2026
94b6ac0
docs: fix perf output table rendering
DingmaomaoBJTU Jun 11, 2026
29c8da6
docs: remove per-operator tracing section (not ready)
DingmaomaoBJTU Jun 11, 2026
49c8cde
Merge remote-tracking branch 'origin/main' into docs/draft
DingmaomaoBJTU Jun 11, 2026
6090cf8
docs: add memory measurement details to perf monitoring section
DingmaomaoBJTU Jun 11, 2026
e692180
docs(perf): separate live monitoring and memory metrics sections
DingmaomaoBJTU Jun 11, 2026
ddbdf04
docs(perf): fix hw_monitor JSON to match actual output
DingmaomaoBJTU Jun 11, 2026
e43d8c3
docs(perf): add per-device metrics breakdown (CPU/GPU/NPU)
DingmaomaoBJTU Jun 11, 2026
8f69373
docs(perf): fix inaccuracies found during review
DingmaomaoBJTU Jun 11, 2026
c29a69d
docs(perf): address review findings
DingmaomaoBJTU Jun 11, 2026
559cd77
Fix docs for eval, compile and quantize (#874)
zhenchaoni Jun 11, 2026
0426ec8
docs: fix --ep choices in compile.md, clarify quantize defaults
DingmaomaoBJTU Jun 12, 2026
9e961e8
docs: address PR review comments
DingmaomaoBJTU Jun 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
274 changes: 274 additions & 0 deletions .github/extensions/doc-check/extension.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
// Extension: doc-check
// Verify docs are self-consistent, cross-referenced correctly, and match source code

import { joinSession } from "@github/copilot-sdk/extension";
import { readFile } from "fs/promises";
import { resolve, join, dirname } from "path";
import { glob } from "fs/promises";

const ROOT = resolve(import.meta.dirname, "../../..");
const DOCS_DIR = join(ROOT, "docs");
const SRC_DIR = join(ROOT, "src");

async function readTextFile(path) {
try {
return await readFile(path, "utf-8");
} catch {
return null;
}
}

async function findFiles(pattern, cwd) {
const results = [];
for await (const entry of glob(pattern, { cwd })) {
results.push(entry);
}
return results;
}

const session = await joinSession({
tools: [
{
name: "doc_check_consistency",
description:
"Audit the docs/ folder for internal consistency issues: broken cross-references between markdown files, nav entries in mkdocs.yml that point to missing files, and markdown files in docs/ that are not listed in nav or exclude_docs. Returns a report of findings.",
parameters: { type: "object", properties: {} },
skipPermission: true,
handler: async () => {
const findings = [];

// 1. Read mkdocs.yml nav and check all referenced files exist
const mkdocsContent = await readTextFile(join(ROOT, "mkdocs.yml"));
if (!mkdocsContent) return "Error: mkdocs.yml not found";

const navFileRefs = [...mkdocsContent.matchAll(/:\s+(\S+\.md)/g)].map((m) => m[1]);
for (const ref of navFileRefs) {
const fullPath = join(DOCS_DIR, ref);
const content = await readTextFile(fullPath);
if (content === null) {
findings.push(`[NAV_MISSING_FILE] mkdocs.yml references '${ref}' but file does not exist`);
}
}

// 2. Check internal markdown links in all docs files
const mdFiles = await findFiles("**/*.md", DOCS_DIR);
for (const relPath of mdFiles) {
const fullPath = join(DOCS_DIR, relPath);
const content = await readTextFile(fullPath);
if (!content) continue;

// Find markdown links like [text](../path/to/file.md) or [text](./file.md#anchor)
const linkPattern = /\[([^\]]*)\]\(([^)]+)\)/g;
let match;
while ((match = linkPattern.exec(content)) !== null) {
const target = match[2];
// Skip external URLs and anchors-only
if (target.startsWith("http") || target.startsWith("#") || target.startsWith("mailto:")) continue;
// Strip anchor
const filePart = target.split("#")[0];
if (!filePart) continue;
// Resolve relative to current file's directory
const resolvedPath = resolve(dirname(fullPath), filePart);
const exists = await readTextFile(resolvedPath);
if (exists === null) {
findings.push(`[BROKEN_LINK] ${relPath}: link to '${filePart}' resolves to non-existent file`);
}
}
}

// 3. Check for md files not in nav and not in exclude_docs
const excludeMatch = mkdocsContent.match(/exclude_docs:\s*\|([\s\S]*?)(?=\n\S|\n*$)/);
const excludePatterns = excludeMatch
? excludeMatch[1]
.split("\n")
.map((l) => l.trim())
.filter(Boolean)
: [];
const navSet = new Set(navFileRefs);
for (const relPath of mdFiles) {
const normalized = relPath.replace(/\\/g, "/");
if (navSet.has(normalized)) continue;
if (normalized === "index.md") continue;
// Check exclude patterns (simple glob: just filename or path prefix)
const excluded = excludePatterns.some((pat) => {
const cleanPat = pat.replace(/^\//, "");
return normalized === cleanPat || normalized.startsWith(cleanPat);
});
if (excluded) continue;
findings.push(`[ORPHAN_FILE] ${normalized} is not in mkdocs.yml nav or exclude_docs`);
}

if (findings.length === 0) return "✅ No consistency issues found.";
return `Found ${findings.length} issue(s):\n\n${findings.join("\n")}`;
},
},
{
name: "doc_check_code_alignment",
description:
"Cross-reference documentation claims against source code. Checks: CLI flag names documented in command pages match actual Click/Typer parameter definitions in src/; EP names and device mappings in docs match source; config schema fields match the WinMLBuildConfig dataclass. Returns mismatches.",
parameters: {
type: "object",
properties: {
scope: {
type: "string",
description: "Which aspect to check: 'flags' (CLI flags vs source), 'eps' (EP table vs source), 'config' (config schema fields vs dataclass), or 'all'",
enum: ["flags", "eps", "config", "all"],
},
},
},
skipPermission: true,
handler: async (args) => {
const scope = args.scope || "all";
const findings = [];

// Helper: find Python files containing a pattern
async function searchSrc(pattern) {
const pyFiles = await findFiles("**/*.py", SRC_DIR);
const results = [];
for (const f of pyFiles) {
const content = await readTextFile(join(SRC_DIR, f));
if (content && content.includes(pattern)) {
results.push({ file: f, content });
}
}
return results;
}

if (scope === "flags" || scope === "all") {
// Check command docs for flags and verify they exist in source
const cmdFiles = await findFiles("*.md", join(DOCS_DIR, "commands"));
for (const cmdFile of cmdFiles) {
const content = await readTextFile(join(DOCS_DIR, "commands", cmdFile));
if (!content) continue;
// Extract flags from markdown tables: | `--flag-name` |
const flagPattern = /\|\s*`(--[\w-]+)`/g;
let match;
const docFlags = [];
while ((match = flagPattern.exec(content)) !== null) {
docFlags.push(match[1]);
}
if (docFlags.length === 0) continue;

// Try to find the command source file
const cmdName = cmdFile.replace(".md", "");
const srcFiles = await searchSrc(`def ${cmdName}`);
if (srcFiles.length === 0) continue;

// Check each documented flag exists in source (as click option or argument)
const srcContent = srcFiles.map((s) => s.content).join("\n");
for (const flag of docFlags) {
const paramName = flag.replace(/^--/, "").replace(/-/g, "_");
const altName = flag; // --flag-name form
if (!srcContent.includes(paramName) && !srcContent.includes(altName)) {
findings.push(`[FLAG_NOT_IN_SRC] ${cmdFile}: '${flag}' not found in source for '${cmdName}' command`);
}
}
}
}

if (scope === "eps" || scope === "all") {
// Check EP table in docs/concepts/eps-and-devices.md
const epDoc = await readTextFile(join(DOCS_DIR, "concepts", "eps-and-devices.md"));
if (epDoc) {
const epPattern = /\|\s*`(\w+ExecutionProvider)`\s*\|\s*`(\w+)`/g;
let match;
while ((match = epPattern.exec(epDoc)) !== null) {
const epName = match[1];
const shortName = match[2];
// Verify EP short name exists somewhere in source
const srcHits = await searchSrc(shortName);
if (srcHits.length === 0) {
findings.push(`[EP_SHORT_NAME_MISSING] EP '${epName}' short name '${shortName}' not found in source`);
}
}
}
}

if (scope === "config" || scope === "all") {
// Check config schema fields in docs/reference/index.md against source dataclass
const refDoc = await readTextFile(join(DOCS_DIR, "reference", "index.md"));
if (refDoc) {
// Extract field names from table rows: | `field_name` |
const fieldPattern = /\|\s*`([\w.]+)`\s*\|/g;
let match;
const docFields = new Set();
while ((match = fieldPattern.exec(refDoc)) !== null) {
docFields.add(match[1].split(".").pop()); // Get leaf field name
}
// Find WinMLBuildConfig in source
const configFiles = await searchSrc("WinMLBuildConfig");
if (configFiles.length > 0) {
const configSrc = configFiles.map((f) => f.content).join("\n");
// Check each doc field appears in source
for (const field of docFields) {
if (!configSrc.includes(field)) {
findings.push(`[CONFIG_FIELD_MISSING] Field '${field}' documented but not found in WinMLBuildConfig source`);
}
}
}
}
}

if (findings.length === 0) return "✅ Documentation aligns with source code.";
return `Found ${findings.length} mismatch(es):\n\n${findings.join("\n")}`;
},
},
{
name: "doc_check_samples",
description:
"Verify that sample pages (docs/samples/) use correct model IDs, command flags, and pipeline steps that match the current CLI capabilities. Checks model IDs are valid HuggingFace references and command examples use documented flags.",
parameters: { type: "object", properties: {} },
skipPermission: true,
handler: async () => {
const findings = [];
const sampleFiles = await findFiles("*.md", join(DOCS_DIR, "samples"));

// Load all documented flags from command pages
const cmdFiles = await findFiles("*.md", join(DOCS_DIR, "commands"));
const allFlags = new Map(); // command -> Set of flags
for (const cmdFile of cmdFiles) {
const content = await readTextFile(join(DOCS_DIR, "commands", cmdFile));
if (!content) continue;
const cmdName = cmdFile.replace(".md", "");
const flags = new Set();
const flagPattern = /\|\s*`(--[\w-]+)`/g;
let match;
while ((match = flagPattern.exec(content)) !== null) {
flags.add(match[1]);
}
allFlags.set(cmdName, flags);
}

for (const sampleFile of sampleFiles) {
const content = await readTextFile(join(DOCS_DIR, "samples", sampleFile));
if (!content) continue;

// Check command examples use valid flags
const codeBlocks = content.match(/```bash\n([\s\S]*?)```/g) || [];
for (const block of codeBlocks) {
// Find winml commands
const cmdPattern = /winml\s+(\w+)(.*)/g;
let match;
while ((match = cmdPattern.exec(block)) !== null) {
const cmd = match[1];
const argsStr = match[2];
const docFlags = allFlags.get(cmd);
if (!docFlags || docFlags.size === 0) continue;

// Extract flags used
const usedFlags = argsStr.match(/--[\w-]+/g) || [];
for (const flag of usedFlags) {
if (!docFlags.has(flag)) {
findings.push(`[UNDOCUMENTED_FLAG] ${sampleFile}: 'winml ${cmd} ${flag}' uses flag not in docs/commands/${cmd}.md`);
}
}
}
}
}

if (findings.length === 0) return "✅ All sample commands use documented flags.";
return `Found ${findings.length} issue(s):\n\n${findings.join("\n")}`;
},
},
],
});
68 changes: 68 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
name: Build & Publish Docs

on:
push:
branches: [main]
paths: ["docs/**", "mkdocs.yml"]
release:
types: [published]
workflow_dispatch:
inputs:
version:
description: "Version label to deploy (e.g., 0.2). Leave empty to use 'dev'."
required: false

permissions:
contents: write
pages: write

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- uses: astral-sh/setup-uv@v3
with:
python-version: "3.11"

- run: uv sync --extra dev

- name: Configure git for mike
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"

- name: Determine version
id: version
run: |
if [[ "${{ github.event_name }}" == "release" ]]; then
# Strip 'v' prefix from tag: v0.2.0 → 0.2
TAG="${{ github.event.release.tag_name }}"
VERSION="${TAG#v}"
VERSION="${VERSION%.*}"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "alias=latest" >> "$GITHUB_OUTPUT"
elif [[ -n "${{ github.event.inputs.version }}" ]]; then
echo "version=${{ github.event.inputs.version }}" >> "$GITHUB_OUTPUT"
echo "alias=latest" >> "$GITHUB_OUTPUT"
else
echo "version=dev" >> "$GITHUB_OUTPUT"
echo "alias=" >> "$GITHUB_OUTPUT"
fi

- name: Deploy docs with mike
run: |
VERSION="${{ steps.version.outputs.version }}"
ALIAS="${{ steps.version.outputs.alias }}"
if [[ -n "$ALIAS" ]]; then
uv run mike deploy "$VERSION" "$ALIAS" --update-aliases --push
else
uv run mike deploy "$VERSION" --push
fi

- name: Set default version
if: steps.version.outputs.alias == 'latest'
run: uv run mike set-default latest --push
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -264,3 +264,6 @@ specs/

# Runtime check rule artifacts (hosted in external repo)
src/winml/modelkit/analyze/rules/runtime_check_rules/**/*.parquet

# Generated by mike (docs versioning)
docs/versions.json
Comment thread
xieofxie marked this conversation as resolved.
11 changes: 10 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ We're always looking for your help to improve the product (bug fixes, new featur
See the [README](./README.md#getting-started) for prerequisites and installation instructions. Then set up your development environment:

```bash
uv sync
git clone https://github.com/microsoft/winml-cli.git
cd winml-cli
uv sync --extra dev
uv run pre-commit install
```

Expand All @@ -24,6 +26,13 @@ This installs all dependencies and enables [pre-commit hooks](https://pre-commit

When running WinML CLI from a source tree (`uv run winml ...`), you need to populate the runtime check rule zips locally. See [`src/winml/modelkit/analyze/rules/runtime_check_rules/README.md`](./src/winml/modelkit/analyze/rules/runtime_check_rules/README.md) for setup options (GitHub release for external contributors, `gim-home` script for Microsoft internal, `WINMLCLI_RULES_DIR` override).

For external contributors, download from a GitHub release:

```bash
gh release download <tag> --repo microsoft/winml-cli --pattern 'rules-v*.zip' --dir .
Expand-Archive -Path .\rules-v*.zip -DestinationPath src\winml\modelkit\analyze\rules\runtime_check_rules -Force
```

## Coding conventions and standards

### Python code style
Expand Down
Loading
Loading