diff --git a/docs/development/agent-workflow.md b/docs/development/agent-workflow.md index bf63e7a44..d319228ee 100644 --- a/docs/development/agent-workflow.md +++ b/docs/development/agent-workflow.md @@ -71,6 +71,7 @@ Declared packages also permit safe subpaths; exact aliases stay exact. Declared package mentions may include a version (including semver comparators) 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. +Non-ASCII punctuation separates package mentions from adjacent prose. Markdown destinations decode HTML entities before URI parsing, matching rendered links. Heading-anchor lookup is limited to Markdown targets. Source-file line fragments, PDF page fragments and other non-Markdown fragments retain file-existence checks. diff --git a/tools/skills/validate-agent-guidance.mjs b/tools/skills/validate-agent-guidance.mjs index 7ed5aa9d6..6470e0551 100644 --- a/tools/skills/validate-agent-guidance.mjs +++ b/tools/skills/validate-agent-guidance.mjs @@ -114,7 +114,9 @@ async function packageMentions(rootDir) { .map((name) => name.slice(1)); const scopes = new Set(declared.map((name) => name.split('/')[0])); return (raw) => { - let token = raw.replace(/[?!.,;:)"'\]}]+$/u, ''); + // ASCII punctuation also belongs to package names and version ranges. + let token = raw.split(/(?=[^\x00-\x7f])\p{P}/u, 1)[0]; + token = token.replace(/[?!.,;:)"'\]}]+$/u, ''); token = token.replace(/['’]s$/iu, ''); token = token.replace( /^([^/@]+(?:\/[^/@]+)?)@(?:(?:[~^]|[<>]=?|=)?\d[\w.+-]*|[a-z][\w-]*)$/iu, diff --git a/tools/skills/validate-agent-guidance.test.mjs b/tools/skills/validate-agent-guidance.test.mjs index 2e997b531..adb3e80a1 100644 --- a/tools/skills/validate-agent-guidance.test.mjs +++ b/tools/skills/validate-agent-guidance.test.mjs @@ -1109,3 +1109,17 @@ for (const ending of ['\n', '\r\n', '\r']) { }); } } + +for (const punctuation of ['—its', '–its', '…', ',next', '。next', '”']) { + test(`package mention stops at Unicode punctuation: ${punctuation}`, async (t) => { + assert.deepEqual( + await diagnostics(t, { + 'package.json': JSON.stringify({ + dependencies: { '@angular/core': '*' }, + }), + 'AGENTS.md': 'Use @angular/core' + punctuation + ' APIs', + }), + [] + ); + }); +}