From 795946d2a05025693f7348ee669336db012c5e33 Mon Sep 17 00:00:00 2001 From: 4gray Date: Sun, 20 Sep 2026 21:49:06 +0200 Subject: [PATCH] fix(agents): route source work and check extensionless files --- AGENTS.md | 2 +- docs/development/agent-workflow.md | 7 ++++-- tools/skills/agent-guidance-markdown.mjs | 3 +++ tools/skills/validate-agent-guidance.test.mjs | 24 +++++++++++++++++++ 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index b461b300c..3119f7d6a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -88,7 +88,7 @@ contracts below before changing a subsystem; do not load every document. | Angular conventions, docs and skills maintenance | [Agent workflow](docs/development/agent-workflow.md) | | Electron debugging, CDP, trace flags | [Electron debugging](docs/development/electron-debugging.md) | | SQLite, worker IPC, persistence migrations | [DB worker](docs/architecture/sqlite-db-worker.md), [database migrations](libs/shared/database/README.md) | -| M3U, XMLTV, startup, source health, OS playlist opening | [M3U contracts](docs/architecture/m3u-playlist-module.md) | +| M3U, XMLTV, startup, source health, OS playlist opening | [M3U contracts](docs/architecture/m3u-playlist-module.md), [adding sources across layers](docs/development/agent-workflow.md#adding-behavior-across-layers) | | Xtream / Stalker | [Xtream compatibility](docs/architecture/xtream-portal-compatibility.md), [Stalker contracts](docs/architecture/stalker-portal.md) (affected provider only) | | Player controls, diagnostics, radio, keep-awake | [Controls contract](docs/architecture/player-controls-contract.md) | | Embedded MPV, native runtime and packaging | [Embedded MPV](docs/architecture/embedded-mpv-native.md) | diff --git a/docs/development/agent-workflow.md b/docs/development/agent-workflow.md index 85e790ced..056cd95e4 100644 --- a/docs/development/agent-workflow.md +++ b/docs/development/agent-workflow.md @@ -37,8 +37,11 @@ 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. -Multi-part dotfiles are path candidates too. Link paths and fragments are decoded -separately so encoded filename delimiters stay in the filename. Fenced and indented examples +Multi-part dotfiles are path candidates too. +Conventional extensionless filenames such as Dockerfile, Makefile and LICENSE +are also path candidates; use an explicit `./` prefix for other extensionless files. +Link paths and fragments are decoded separately so encoded filename delimiters +stay in the filename. Fenced and indented examples do not count as root guidance imports or satisfy the required Claude import. The required Claude import must be an unformatted standalone line in a top-level paragraph; headings, quotes and list items do not satisfy it. diff --git a/tools/skills/agent-guidance-markdown.mjs b/tools/skills/agent-guidance-markdown.mjs index 5f40a7953..131eebb5b 100644 --- a/tools/skills/agent-guidance-markdown.mjs +++ b/tools/skills/agent-guidance-markdown.mjs @@ -176,6 +176,9 @@ function isLiteralRepositoryPath(token) { return false; return ( path.includes('/') || + /^(?:Dockerfile|Containerfile|Makefile|GNUmakefile|Justfile|Procfile|Gemfile|Rakefile|Vagrantfile|LICENSE|LICENCE|NOTICE|COPYING|AUTHORS|CONTRIBUTORS|README|CHANGELOG)$/u.test( + path + ) || /^(?:\.[\p{L}\p{N}_-][\p{L}\p{N}_.-]*|[\p{L}\p{N}_-][\p{L}\p{N}_.-]*\.[\p{L}][\p{L}\p{N}_-]*)$/u.test( path ) diff --git a/tools/skills/validate-agent-guidance.test.mjs b/tools/skills/validate-agent-guidance.test.mjs index 6bb8d37e1..f8c03f5f6 100644 --- a/tools/skills/validate-agent-guidance.test.mjs +++ b/tools/skills/validate-agent-guidance.test.mjs @@ -787,3 +787,27 @@ test('declared packages allow safe subpaths', async (t) => { [] ); }); + +for (const filename of [ + 'Dockerfile', + 'Makefile', + 'LICENSE', + 'NOTICE', + 'Procfile', +]) { + test(`conventional extensionless filename is validated: ${filename}`, async (t) => { + assert.match( + (await diagnostics(t, { 'AGENTS.md': '`' + filename + '`' })).join( + '\n' + ), + /does not exist/ + ); + assert.deepEqual( + await diagnostics(t, { + 'AGENTS.md': '`' + filename + '`', + [filename]: '', + }), + [] + ); + }); +}