test(#489): stop docs-parity tokenizer matching repo path open-gsd/gsd-core as a command (#491)

extractCommandTokens regexes matched the /gsd-core substring inside the
org/repo path open-gsd/gsd-core#22. Add a negative lookbehind so only
actual invocations (BOL / space / backtick / paren) match, not path or
word-embedded segments. Add a regression test covering the repo-path
false positive while proving real broken command refs are still caught.

Refs #489

Co-authored-by: CI Rebase Check <ci@gsd-redux>
This commit is contained in:
Tom Boucher
2026-05-29 18:08:27 -04:00
committed by GitHub
parent b9ea06fa8b
commit 28cf6b444f

View File

@@ -197,9 +197,14 @@ function extractCommandTokens(content) {
return false;
}
const allSlash = (stripped.match(/\/gsd-[a-z0-9][a-z0-9-]*/g) || []);
const allColon = (stripped.match(/\/gsd:[a-z0-9][a-z0-9-]*/g) || []);
const allDollar = (stripped.match(/\$gsd-[a-z0-9][a-z0-9-]*/g) || []);
// Negative lookbehind: only match tokens NOT preceded by a letter, digit,
// `/`, `_`, or `-`. This prevents matching the `/gsd-core` substring inside
// the org/repo path `open-gsd/gsd-core` (and similar path-embedded segments)
// while still matching real invocations preceded by BOL, space, backtick, or
// `(`. Fixes false-positive class identified in #489.
const allSlash = (stripped.match(/(?<![A-Za-z0-9/_-])\/gsd-[a-z0-9][a-z0-9-]*/g) || []);
const allColon = (stripped.match(/(?<![A-Za-z0-9/_-])\/gsd:[a-z0-9][a-z0-9-]*/g) || []);
const allDollar = (stripped.match(/(?<![A-Za-z0-9/_-])\$gsd-[a-z0-9][a-z0-9-]*/g) || []);
const slash = new Set(allSlash.filter(t => !isInternal(t)));
const colon = new Set(allColon.filter(t => !isInternal(t)));
@@ -483,3 +488,44 @@ describe('adversarial: polarity inversion catches drift deny-list misses', () =>
assert.ok(!registry.has('/gsd-research-phase'), '/gsd-research-phase must not be in the live registry');
});
});
// ─── Tokenizer regression tests (#489) ───────────────────────────────────────
describe('extractCommandTokens() — repo-path false-positive regression (#489)', () => {
test('open-gsd/gsd-core#22 repo path does NOT produce a /gsd-core token', () => {
// Before the lookbehind fix, /gsd-core inside `open-gsd/gsd-core#22`
// would be matched by the slash regex — a false positive.
const { slash, colon, dollar } = extractCommandTokens(
'see open-gsd/gsd-core#22 for details'
);
const all = [...slash, ...colon, ...dollar];
assert.ok(
!all.includes('/gsd-core'),
'repo path open-gsd/gsd-core#22 must not produce a /gsd-core token; got: ' + all.join(', ')
);
assert.strictEqual(all.length, 0, 'expected zero tokens from a bare repo-path string; got: ' + all.join(', '));
});
test('space-preceded /gsd-totally-not-a-real-command is still extracted (real invocation)', () => {
// A genuine (but unregistered) command reference after whitespace must be
// captured so the live-registry check can flag it as unknown.
const { slash } = extractCommandTokens(
'run /gsd-totally-not-a-real-command here'
);
assert.ok(
slash.has('/gsd-totally-not-a-real-command'),
'invocation after whitespace must be extracted; slash set: ' + [...slash].join(', ')
);
});
test('backtick-wrapped `/gsd-plan` is still extracted (real invocation)', () => {
// Backtick-wrapped commands (common in markdown) must still be captured.
const { slash } = extractCommandTokens(
'use `/gsd-plan` to plan'
);
assert.ok(
slash.has('/gsd-plan'),
'backtick-wrapped invocation must be extracted; slash set: ' + [...slash].join(', ')
);
});
});