mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 17:06:15 -08:00
fix(agents): preserve filenames across prose punctuation
This commit is contained in:
1 parent
4a73cf3828
commit
82d582bb74
3 files changed
+59
-12
No files matched your search
@@ -64,7 +64,7 @@ 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.
|
||||
Extensionless inline candidates are also imports when they resolve to repository files,
|
||||
after removing prose punctuation, including Unicode separators.
|
||||
checking the full filename before prefixes at ASCII/Unicode prose separators.
|
||||
Declared scoped dependencies, scope wildcards and matching TypeScript path aliases
|
||||
are recognized as package/alias mentions. Traversal and document-file imports are
|
||||
rejected before those exemptions. TypeScript configuration is parsed as JSONC.
|
||||
@@ -72,7 +72,8 @@ 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.
|
||||
Unicode punctuation and ASCII commas, semicolons, colons, question/exclamation marks
|
||||
separate 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.
|
||||
|
||||
@@ -115,7 +115,7 @@ async function packageMentions(rootDir) {
|
||||
const scopes = new Set(declared.map((name) => name.split('/')[0]));
|
||||
return (raw) => {
|
||||
// ASCII punctuation also belongs to package names and version ranges.
|
||||
let token = raw.split(/(?=[^\x00-\x7f])\p{P}/u, 1)[0];
|
||||
let token = raw.split(/[,;:!?]|(?=[^\x00-\x7f])\p{P}/u, 1)[0];
|
||||
token = token.replace(/[?!.,;:)"'\]}]+$/u, '');
|
||||
token = token.replace(/['’]s$/iu, '');
|
||||
token = token.replace(
|
||||
@@ -188,15 +188,27 @@ export async function validateAgentGuidance({ rootDir }) {
|
||||
inlineImports.push(token);
|
||||
continue;
|
||||
}
|
||||
const candidate = token
|
||||
.split(/(?=[^\x00-\x7f])\p{P}/u, 1)[0]
|
||||
.replace(/[?!.,;:)"'\]}]+$/u, '');
|
||||
try {
|
||||
if ((await stat(resolve(rootDir, candidate))).isFile())
|
||||
inlineImports.push(token);
|
||||
} catch (error) {
|
||||
if (error.code !== 'ENOENT' && error.code !== 'ENOTDIR')
|
||||
throw error;
|
||||
// Check real filenames before interpreting punctuation as prose.
|
||||
const candidates = new Set([
|
||||
token,
|
||||
token.replace(/[?!.,;:)"'\]}]+$/u, ''),
|
||||
]);
|
||||
for (const boundary of token.matchAll(
|
||||
/[,;:!?]|(?=[^\x00-\x7f])\p{P}/gu
|
||||
))
|
||||
candidates.add(token.slice(0, boundary.index));
|
||||
for (const candidate of candidates) {
|
||||
try {
|
||||
if (
|
||||
(await stat(resolve(rootDir, candidate))).isFile()
|
||||
) {
|
||||
inlineImports.push(token);
|
||||
break;
|
||||
}
|
||||
} catch (error) {
|
||||
if (error.code !== 'ENOENT' && error.code !== 'ENOTDIR')
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (
|
||||
|
||||
@@ -1136,3 +1136,37 @@ for (const suffix of ['—then', ',next', '”']) {
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
for (const name of ['INSTRUCTIONS—v2', 'INSTRUCTIONS,extra']) {
|
||||
test(`full punctuation filename remains an import: ${name}`, async (t) => {
|
||||
assert.ok(
|
||||
(
|
||||
await diagnostics(t, {
|
||||
'CLAUDE.md': '@AGENTS.md\n\nRead @' + name,
|
||||
[name]: 'Guidance',
|
||||
})
|
||||
).some((message) => message.includes('additional or inline'))
|
||||
);
|
||||
});
|
||||
}
|
||||
for (const suffix of [',then', ';then', ':then', '!then', '?then']) {
|
||||
test(`ASCII prose boundary handles imports and packages: ${suffix}`, async (t) => {
|
||||
assert.ok(
|
||||
(
|
||||
await diagnostics(t, {
|
||||
'CLAUDE.md': '@AGENTS.md\n\nRead @INSTRUCTIONS' + suffix,
|
||||
INSTRUCTIONS: 'Guidance',
|
||||
})
|
||||
).some((message) => message.includes('additional or inline'))
|
||||
);
|
||||
assert.deepEqual(
|
||||
await diagnostics(t, {
|
||||
'AGENTS.md': 'Use @angular/core' + suffix + ' continue',
|
||||
'package.json': JSON.stringify({
|
||||
dependencies: { '@angular/core': '*' },
|
||||
}),
|
||||
}),
|
||||
[]
|
||||
);
|
||||
});
|
||||
}
|
||||
Reference in new issue
Block a user