fix(agents): retain visible backticks and explicit path punctuation

This commit is contained in:
4gray committed 2026-09-20 23:47:48 +02:00
1 parent 505fa356ab
commit 900050be2e
4 files changed
+33 -11

No files matched your search

+2 -2
View File
@@ -37,7 +37,7 @@ Write generic filenames as prose; commands, templates, globs, URLs, package
aliases and dotted code symbols are excluded. Bare dotted names with conventional
file suffixes (such as .md, .json or .ts) are treated as filenames. Use a `./`
prefix or Markdown link for other ambiguous filenames that resemble code symbols.
Explicit relative literals denote paths, including spaces and hyphenated words.
Explicit relative literals denote paths, including spaces, filesystem punctuation and hyphenated words.
Put executable command examples in fenced code when their syntax also looks like a path.
Multi-part dotfiles are path candidates too.
Conventional extensionless filenames such as Dockerfile, Makefile and LICENSE
@@ -73,7 +73,7 @@ removed before matching a declared package, as are straight/curly apostrophe pos
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.
The import scan includes visible HTML text and excludes code and non-rendered containers.
The import scan includes visible HTML text and literal backticks; it excludes parsed code nodes and non-rendered containers.
Navigation uses the parsed rendered tree too. Temporary in-memory markers retain
definition, unresolved-reference and literal-path metadata, so Markdown inside
inert templates is excluded consistently with raw HTML navigation.
+1 -7
View File
@@ -179,13 +179,7 @@ function isLiteralRepositoryPath(token) {
// Exclude recognizable prose/code forms instead of allowlisting paths.
if (/^(?:@|--|[a-z][a-z\d+.-]*:|\/\/)/iu.test(token)) return false;
const explicitRelative = /^(?:\.\/|\.\.\/)/u.test(token);
if (
(explicitRelative
? /[^\p{L}\p{N}_./# -]/u
: /[^\p{L}\p{N}_./#-]/u
).test(token)
)
return false;
if (!explicitRelative && /[^\p{L}\p{N}_./#-]/u.test(token)) return false;
if (token.includes('YYYY-MM-DD') || /(?:^|\/)\.\.\.(?:\/|$)/u.test(token))
return false;
const path = token.split('#')[0];
+1 -2
View File
@@ -167,9 +167,8 @@ export async function validateAgentGuidance({ rootDir }) {
diagnostics.push(
`${source}: at most ${maxBytes} UTF-8 bytes allowed (received ${bytes})`
);
const unfenced = guidanceProse(markdown);
const prose = guidanceProse(markdown);
const imports = guidanceStandaloneImports(markdown);
const prose = unfenced.replace(/`[^`\n]+`/gu, '');
const inlineImports = [];
for (const match of prose.matchAll(
/(?:^|[^\p{L}\p{N}_@])@([^\s]+)/gu
@@ -1031,3 +1031,32 @@ test('ordinary unknown handle is not a file import', async (t) => {
[]
);
});
for (const wrapper of ['\\`', '`']) {
test(`visible literal backticks preserve imports: ${wrapper}`, async (t) => {
const result = await diagnostics(t, {
'CLAUDE.md':
'@AGENTS.md\n\nRead ' + wrapper + '@docs/example.md' + wrapper,
});
assert.ok(
result.some((message) => message.includes('additional or inline'))
);
});
}
for (const filename of [
'Guide (old).md',
"Author's guide.md",
'Guide [draft].md',
]) {
test(`explicit path punctuation is validated: ${filename}`, async (t) => {
const guidance = '`./docs/' + filename + '`';
assert.deepEqual(
await diagnostics(t, {
'AGENTS.md': guidance,
['docs/' + filename]: '# Guide',
}),
[]
);
assert.ok((await diagnostics(t, { 'AGENTS.md': guidance })).length > 0);
});
}