diff --git a/docs/development/agent-workflow.md b/docs/development/agent-workflow.md
index 950007ecb..1f6a857ae 100644
--- a/docs/development/agent-workflow.md
+++ b/docs/development/agent-workflow.md
@@ -69,7 +69,7 @@ Image and media references require a nonempty path that resolves to a file, not
Direct file URLs and file-scheme HTML bases 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 hrefs (including xlink), HTML image-input, video, audio, source and track `src` assets and video posters use the same
+SVG image/use hrefs (including xlink), HTML image-input, video, audio, source and track `src` assets and video posters use the same
existence checks as images. Entity decoding uses full HTML text/attribute rules,
including references whose semicolon may be omitted.
Inline guidance imports are rejected after punctuation as well as whitespace.
@@ -91,6 +91,8 @@ from package exemptions. Recognized extensionless guidance names (including AGEN
CLAUDE, INSTRUCTIONS, README, CONTRIBUTING and SECURITY, case-insensitively) are excluded in package subpaths too. URL-encoded
paths do not receive package exemptions. TypeScript configuration is parsed as JSONC.
Declared packages also permit safe subpaths; exact aliases stay exact.
+Federated handles in the @user@host form are prose, not imports.
+Exact declared packages remain exempt after version normalization.
Declared package mentions may include a version (including semver comparators and wildcard ranges) or dist-tag qualifier.
Qualifier handling includes unscoped names; terminal sentence punctuation is
removed before matching a declared package, as are straight/curly apostrophe possessives.
diff --git a/tools/skills/agent-guidance-markdown.mjs b/tools/skills/agent-guidance-markdown.mjs
index 173905117..88a6782d9 100644
--- a/tools/skills/agent-guidance-markdown.mjs
+++ b/tools/skills/agent-guidance-markdown.mjs
@@ -77,7 +77,7 @@ function htmlNavigation(html, inspect = () => {}) {
)
anchors.push(attribute.value);
if (
- (['a', 'area', 'image'].includes(node.tagName) &&
+ (['a', 'area', 'image', 'use'].includes(node.tagName) &&
attribute.name === 'href') ||
([
'img',
@@ -100,6 +100,7 @@ function htmlNavigation(html, inspect = () => {}) {
))
)
references.push({
+ svgUse: node.tagName === 'use',
target: attribute.value
.replace(/[\t\n\r]/gu, '')
.replace(/^[\u0000-\u0020]+|[\u0000-\u0020]+$/gu, ''),
@@ -135,6 +136,16 @@ function htmlNavigation(html, inspect = () => {}) {
for (const child of node.childNodes ?? []) visit(child);
}
visit(parseFragment(html));
+ for (const reference of references) {
+ if (
+ reference.svgUse &&
+ !reference.embeddedAnchors &&
+ reference.target.startsWith('#')
+ ) {
+ reference.image = false;
+ reference.embeddedAnchors = anchors;
+ }
+ }
return {
anchors,
references:
diff --git a/tools/skills/validate-agent-guidance.mjs b/tools/skills/validate-agent-guidance.mjs
index 228598340..0b8169546 100644
--- a/tools/skills/validate-agent-guidance.mjs
+++ b/tools/skills/validate-agent-guidance.mjs
@@ -162,6 +162,8 @@ async function packageMentions(rootDir) {
token.split(/[\/\\]/u).some((part) => part === '.' || part === '..')
)
return false;
+ if (packages.includes(token) || packages.includes(`@${token}`))
+ return true;
const path = token.split(/[?#]/u, 1)[0];
if (
/%[\da-f]{2}/iu.test(token) ||
@@ -224,6 +226,12 @@ export async function validateAgentGuidance({ rootDir }) {
)) {
const token = match[1];
if (isPackageMention(token)) continue;
+ if (
+ /^[\w.-]+@(?:[a-z\d](?:[a-z\d-]*[a-z\d])?\.)+[a-z]{2,}[.,;!?]?$/iu.test(
+ token
+ )
+ )
+ continue;
if (
/[./\\]/u.test(token) ||
/^(?:LICENSE|Makefile|Dockerfile|AGENTS|CLAUDE)(?:$|[.,;)])/u.test(
diff --git a/tools/skills/validate-agent-guidance.test.mjs b/tools/skills/validate-agent-guidance.test.mjs
index 3c251366a..8bfd3c2fd 100644
--- a/tools/skills/validate-agent-guidance.test.mjs
+++ b/tools/skills/validate-agent-guidance.test.mjs
@@ -1702,3 +1702,48 @@ for (const name of ['CONTRIBUTING', 'SECURITY', 'code_of_conduct', 'SUPPORT']) {
);
});
}
+
+test('versioned declared package may share a guidance basename', async (t) => {
+ assert.deepEqual(
+ await diagnostics(t, {
+ 'package.json': JSON.stringify({
+ dependencies: { '@scope/support': '*' },
+ }),
+ 'AGENTS.md': 'Use @scope/support@^2',
+ }),
+ []
+ );
+});
+test('federated handle is not an import', async (t) => {
+ assert.deepEqual(
+ await diagnostics(t, { 'AGENTS.md': 'Contact @alice@example.social' }),
+ []
+ );
+});
+for (const attribute of ['href', 'xlink:href']) {
+ test(`SVG use references are checked: ${attribute}`, async (t) => {
+ assert.ok(
+ (
+ await diagnostics(t, {
+ 'AGENTS.md': ``,
+ })
+ ).length > 0
+ );
+ assert.deepEqual(
+ await diagnostics(t, {
+ 'AGENTS.md': ``,
+ }),
+ []
+ );
+ });
+}
+
+test('srcdoc SVG use keeps its own anchors', async (t) => {
+ assert.deepEqual(
+ await diagnostics(t, {
+ 'AGENTS.md':
+ '',
+ }),
+ []
+ );
+});