From cb42c74f43c52ae3c6353da101354b68ba9b62f9 Mon Sep 17 00:00:00 2001 From: 4gray Date: Sun, 20 Sep 2026 23:23:11 +0200 Subject: [PATCH] fix(agents): recognize possessive package mentions --- docs/development/agent-workflow.md | 2 +- tools/skills/validate-agent-guidance.mjs | 1 + tools/skills/validate-agent-guidance.test.mjs | 14 ++++++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/docs/development/agent-workflow.md b/docs/development/agent-workflow.md index 891a2e27b..5682c0c85 100644 --- a/docs/development/agent-workflow.md +++ b/docs/development/agent-workflow.md @@ -68,7 +68,7 @@ rejected before those exemptions. TypeScript configuration is parsed as JSONC. Declared packages also permit safe subpaths; exact aliases stay exact. Declared package mentions may include a version or dist-tag qualifier. Qualifier handling includes unscoped names; terminal sentence punctuation is -removed before matching a declared package. +removed before matching a declared package, as are straight/curly apostrophe possessives. 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 074bdf317..1929170b2 100644 --- a/tools/skills/validate-agent-guidance.mjs +++ b/tools/skills/validate-agent-guidance.mjs @@ -115,6 +115,7 @@ async function packageMentions(rootDir) { const scopes = new Set(declared.map((name) => name.split('/')[0])); return (raw) => { let token = raw.replace(/[?!.,;:)"'\]}]+$/u, ''); + token = token.replace(/['’]s$/iu, ''); token = token.replace( /^([^/@]+(?:\/[^/@]+)?)@(?:[~^]?\d[\w.+-]*|[a-z][\w-]*)$/iu, '$1' diff --git a/tools/skills/validate-agent-guidance.test.mjs b/tools/skills/validate-agent-guidance.test.mjs index 941f74a3a..621dc80e9 100644 --- a/tools/skills/validate-agent-guidance.test.mjs +++ b/tools/skills/validate-agent-guidance.test.mjs @@ -991,3 +991,17 @@ for (const html of [ ); }); } + +for (const suffix of ["'s", '’s']) { + test(`declared package may be possessive: ${suffix}`, async (t) => { + assert.deepEqual( + await diagnostics(t, { + 'package.json': JSON.stringify({ + dependencies: { '@angular/core': '*' }, + }), + 'AGENTS.md': '@angular/core' + suffix + ' API', + }), + [] + ); + }); +}