diff --git a/docs/development/agent-workflow.md b/docs/development/agent-workflow.md
index f9505a6ff..2bd1c9081 100644
--- a/docs/development/agent-workflow.md
+++ b/docs/development/agent-workflow.md
@@ -66,7 +66,7 @@ The first active HTML base href sets reference resolution, including nested srcd
Resolved file URLs use native filesystem conversion, including Windows drive paths.
Explicit srcset attributes must contain at least one parsed candidate.
Image and media references require a nonempty path that resolves to a file, not a directory.
-Direct file URLs and file-scheme HTML bases are rejected; use portable repository-relative paths.
+Direct file URLs, Windows drive paths and HTML bases using either form are rejected; use portable repository-relative paths.
Image references check file existence without interpreting image fragments as
Markdown headings; document links keep anchor checks even when sharing a target.
SVG image/use hrefs (including xlink), HTML image-input, video, audio, source and track `src` assets and video posters use the same
diff --git a/tools/skills/validate-agent-guidance.mjs b/tools/skills/validate-agent-guidance.mjs
index f09a6a22a..eac2649cd 100644
--- a/tools/skills/validate-agent-guidance.mjs
+++ b/tools/skills/validate-agent-guidance.mjs
@@ -41,6 +41,8 @@ async function validateReference(
) {
if (unresolvedReference !== undefined)
return `${source}: unresolved Markdown reference "${unresolvedReference}"`;
+ if (/^[a-z]:[\\/]/iu.test(target))
+ return `${source}: use a repository-relative path instead of a Windows drive path: ${target}`;
if (/^file:/iu.test(target))
return `${source}: use a repository-relative path instead of a file URL: ${target}`;
if (image && !target) return `${source}: empty media target`;
@@ -49,8 +51,12 @@ async function validateReference(
try {
let base = pathToFileURL(resolve(rootDir, source));
for (const href of bases) {
- if (/^file:/iu.test(href.replace(/[\t\n\r]/gu, '').trimStart()))
- return `${source}: use a repository-relative HTML base instead of a file URL`;
+ if (
+ /^(?:file:|[a-z]:[\\/])/iu.test(
+ href.replace(/[\t\n\r]/gu, '').trimStart()
+ )
+ )
+ return `${source}: use a repository-relative HTML base instead of a file URL or Windows drive path`;
base = new URL(href, base);
}
const url = new URL(target, base);
diff --git a/tools/skills/validate-agent-guidance.test.mjs b/tools/skills/validate-agent-guidance.test.mjs
index 4ed638520..52239f2bd 100644
--- a/tools/skills/validate-agent-guidance.test.mjs
+++ b/tools/skills/validate-agent-guidance.test.mjs
@@ -1850,3 +1850,19 @@ for (const prose of [
);
});
}
+
+for (const reference of [
+ '[Guide](C:/workspace/docs/missing.md)',
+ 'Guide',
+ 'Guide',
+ 'Guide',
+ 'Guide',
+]) {
+ test(`Windows drive paths require portable references: ${reference}`, async (t) => {
+ assert.ok(
+ (await diagnostics(t, { 'AGENTS.md': reference })).some((message) =>
+ message.includes('repository-relative')
+ )
+ );
+ });
+}