fix(engine): LINK-DEAD false positive on API endpoint paths

URL_REF matched `open/<name>` anywhere in a URL path, so a Forgejo API
call like `.../api/v1/orgs/open/repos` read as a dead reference to a
repo named "repos" — "open" there is the org argument to the API, not
a repo reference. Restrict the host segment to exclude `/`, so `open`
must be the first path segment after the host, matching how every
real repo URL is shaped. Measured twice against the catalog's own
RUNBOOK.md:39 and :114.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W1ZJFViVYpr8cvf4fs91j1
This commit is contained in:
Kjell Tore Guttormsen 2026-08-04 22:01:53 +02:00
commit 568b8e374a
2 changed files with 17 additions and 1 deletions

View file

@ -72,7 +72,14 @@ export function normalizeRepoRef(raw) {
// excludes all three of the measured "correct text that looks broken" cases at
// once: a path position (`~/.claude/coord/_broadcast/`), running prose (`coord`
// is still the transport protocol's name), and a bare directory name.
const URL_REF = /(?::\/\/[^\s)\]"'`]*\/|@[^\s:]+:)open\/([A-Za-z0-9._-]+)/g;
//
// The host segment excludes `/`: `open` must be the FIRST path segment after
// the host, matching how every real repo URL is shaped
// (`https://host/open/<name>`, `user@host:open/<name>.git`). Without that
// restriction, an API endpoint like `/api/v1/orgs/open/repos` also matches —
// `open` there is the org argument to the API, and `repos` is the literal
// resource segment, not a repo name (measured: catalog RUNBOOK.md:39, :114).
const URL_REF = /(?::\/\/[^\s)\]"'`/]+\/|@[^\s:]+:)open\/([A-Za-z0-9._-]+)/g;
export function extractOpenRefs(text) {
const out = [];

View file

@ -124,6 +124,15 @@ test('extractOpenRefs ignores path position, prose and bare directory names', ()
assert.deepEqual(extractOpenRefs(text), []);
});
test('extractOpenRefs ignores an org segment inside an API endpoint path', () => {
// Measured false positive (catalog RUNBOOK.md:39, :114): the Forgejo API
// path /api/v1/orgs/open/repos has "open" as the org argument to the API,
// not a repo reference — "repos" is the literal API resource segment, and
// "open" is not the first path segment after the host.
const text = 'curl -X POST https://git.fromaitochitta.com/api/v1/orgs/open/repos';
assert.deepEqual(extractOpenRefs(text), []);
});
test('extractOpenRefs handles the ssh scp-style form', () => {
const refs = extractOpenRefs('git@git.fromaitochitta.com:open/llm-security.git');
assert.deepEqual(refs.map((r) => r.name), ['llm-security']);