Skip to content

fix(skill): resolve references/ wikilinks whose stem contains a dot - #120

Merged
KylinMountain merged 2 commits into
VectifyAI:mainfrom
jichaowang02-lang:fix/wikilink-dotted-stem-suffix
Jun 23, 2026
Merged

fix(skill): resolve references/ wikilinks whose stem contains a dot#120
KylinMountain merged 2 commits into
VectifyAI:mainfrom
jichaowang02-lang:fix/wikilink-dotted-stem-suffix

Conversation

@jichaowang02-lang

Copy link
Copy Markdown
Contributor

Summary

validate_skill reports a false "doesn't exist" error for a valid
[[references/...]] wikilink whose target stem contains a dot (e.g.
[[references/api.v2]], [[references/v1.2-guide]]), even when the file
(references/api.v2.md) is present and correctly linked.

Root cause

openkb/skill/validator.py only appended the implicit .md when
Path(link).suffix was empty:

target=refs_dir/linkifnottarget.suffix: # <-- ".v2" is a truthy suffixtarget=target.with_suffix(".md")
ifnottarget.exists(): # looks for "references/api.v2" (no .md) -> false error

Path.suffix returns everything after the last dot, so api.v2 has a
truthy suffix (.v2). The .md is never appended, and the validator then
checks for an extension-less references/api.v2, which doesn't exist —
producing a false error. WIKILINK_RE ([a-z0-9._/-]+) allows . in the
target, so such links are legal and reach this branch.

linkfile on diskbeforeafter
[[references/topic]]topic.md✅ resolves✅ (unchanged)
[[references/api.v2.md]]api.v2.md✅ resolves✅ (unchanged)
[[references/api.v2]]api.v2.md❌ false "doesn't exist"✅ resolves
[[references/ghost]](absent)✅ errors✅ errors (unchanged)

Fix

Append .md based on a literal .md check instead of Path.suffix:

target=refs_dir/ (linkiflink.lower().endswith(".md") elsef"{link}.md")

A dotted stem is now suffixed correctly; an explicit ...md link is left
alone; genuinely missing references still error.

Testing

$ pytest tests/test_skill_validator.py -q
30 passed
$ ruff check openkb/skill/validator.py tests/test_skill_validator.py
All checks passed!

Adds test_wikilink_dotted_stem_without_md_suffix_resolves — the existing
test_wikilink_without_md_suffix_resolves only covered a dot-free stem, so
this path was uncovered.

`validate_skill` appended the implicit `.md` to a `[[references/...]]` link
only when `Path(link).suffix` was empty. `Path.suffix` returns everything
after the last dot, so a reference whose stem contains a dot — e.g.
`[[references/api.v2]]` or `[[references/v1.2-guide]]` — has a truthy suffix
(`.v2` / `.2-guide`). The `.md` was therefore never appended and the
validator looked for an extension-less `references/api.v2`, emitting a false
"doesn't exist" error even though `references/api.v2.md` is present and
correctly linked. (`WIKILINK_RE` allows `.` in the target, so such links are
legal and reach this branch.)
Append `.md` based on a literal `.md` check instead of `Path.suffix`, so a
dotted stem is suffixed correctly while an explicit `...md` link is left
alone. Genuinely missing references still error.
Adds a regression test for the dotted-stem case (the existing
`test_wikilink_without_md_suffix_resolves` only covered a dot-free stem).
CopilotAI review requested due to automatic review settings June 20, 2026 02:57

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes validate_skill false negatives when resolving [[references/...]] wikilinks whose stems contain dots (e.g. api.v2), by appending .md based on a literal suffix check rather than Path.suffix. This aligns validator behavior with the allowed wikilink pattern and adds a regression test to cover the previously untested path.

Changes:

  • Update openkb/skill/validator.py to treat links as “already suffixed” only when they literally end with .md (case-insensitive).
  • Add a unit test ensuring dotted stems without an explicit .md suffix resolve correctly.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

FileDescription
openkb/skill/validator.pyFixes reference target path construction so dotted stems still resolve to *.md.
tests/test_skill_validator.pyAdds regression coverage for [[references/api.v2]] resolving to references/api.v2.md.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +210 to +214
# The link may already include the .md suffix; append it otherwise.
# Test the literal ".md" rather than Path.suffix — a dotted stem like
# "api.v2" has a truthy suffix (".v2"), so Path.suffix would skip the
# ".md" and then look for a non-existent extension-less file.
target = refs_dir / (link if link.lower().endswith(".md") else f"{link}.md")
Review feedback: WIKILINK_RE allows '.' and '/', so '[[references/../SKILL]]'
resolved outside references/ and was accepted whenever the resolved file
existed (and would crash the not-found message's relative_to(skill_dir)).
Reject any link whose resolved target is not under references/.

@KylinMountainKylinMountain left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jichaowang02-lang — clean fix. The dotted-stem resolution is correct, and the escape guard is a nice catch (the old code silently accepted [[references/../SKILL]]). LGTM 👍

@KylinMountain
KylinMountain merged commit 3fea8cf into VectifyAI:mainJun 23, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jichaowang02-lang@KylinMountain
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
fix(skill): resolve references/ wikilinks whose stem contains a dot by jichaowang02-lang · Pull Request #120 · VectifyAI/OpenKB · GitHub
Skip to content

fix(skill): resolve references/ wikilinks whose stem contains a dot - #120

Merged
KylinMountain merged 2 commits into
VectifyAI:mainfrom
jichaowang02-lang:fix/wikilink-dotted-stem-suffix
Jun 23, 2026
Merged

fix(skill): resolve references/ wikilinks whose stem contains a dot#120
KylinMountain merged 2 commits into
VectifyAI:mainfrom
jichaowang02-lang:fix/wikilink-dotted-stem-suffix

Conversation

@jichaowang02-lang

Copy link
Copy Markdown
Contributor

Summary

validate_skill reports a false "doesn't exist" error for a valid
[[references/...]] wikilink whose target stem contains a dot (e.g.
[[references/api.v2]], [[references/v1.2-guide]]), even when the file
(references/api.v2.md) is present and correctly linked.

Root cause

openkb/skill/validator.py only appended the implicit .md when
Path(link).suffix was empty:

target=refs_dir/linkifnottarget.suffix: # <-- ".v2" is a truthy suffixtarget=target.with_suffix(".md")
ifnottarget.exists(): # looks for "references/api.v2" (no .md) -> false error

Path.suffix returns everything after the last dot, so api.v2 has a
truthy suffix (.v2). The .md is never appended, and the validator then
checks for an extension-less references/api.v2, which doesn't exist —
producing a false error. WIKILINK_RE ([a-z0-9._/-]+) allows . in the
target, so such links are legal and reach this branch.

linkfile on diskbeforeafter
[[references/topic]]topic.md✅ resolves✅ (unchanged)
[[references/api.v2.md]]api.v2.md✅ resolves✅ (unchanged)
[[references/api.v2]]api.v2.md❌ false "doesn't exist"✅ resolves
[[references/ghost]](absent)✅ errors✅ errors (unchanged)

Fix

Append .md based on a literal .md check instead of Path.suffix:

target=refs_dir/ (linkiflink.lower().endswith(".md") elsef"{link}.md")

A dotted stem is now suffixed correctly; an explicit ...md link is left
alone; genuinely missing references still error.

Testing

$ pytest tests/test_skill_validator.py -q
30 passed
$ ruff check openkb/skill/validator.py tests/test_skill_validator.py
All checks passed!

Adds test_wikilink_dotted_stem_without_md_suffix_resolves — the existing
test_wikilink_without_md_suffix_resolves only covered a dot-free stem, so
this path was uncovered.

`validate_skill` appended the implicit `.md` to a `[[references/...]]` link
only when `Path(link).suffix` was empty. `Path.suffix` returns everything
after the last dot, so a reference whose stem contains a dot — e.g.
`[[references/api.v2]]` or `[[references/v1.2-guide]]` — has a truthy suffix
(`.v2` / `.2-guide`). The `.md` was therefore never appended and the
validator looked for an extension-less `references/api.v2`, emitting a false
"doesn't exist" error even though `references/api.v2.md` is present and
correctly linked. (`WIKILINK_RE` allows `.` in the target, so such links are
legal and reach this branch.)
Append `.md` based on a literal `.md` check instead of `Path.suffix`, so a
dotted stem is suffixed correctly while an explicit `...md` link is left
alone. Genuinely missing references still error.
Adds a regression test for the dotted-stem case (the existing
`test_wikilink_without_md_suffix_resolves` only covered a dot-free stem).
CopilotAI review requested due to automatic review settings June 20, 2026 02:57

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes validate_skill false negatives when resolving [[references/...]] wikilinks whose stems contain dots (e.g. api.v2), by appending .md based on a literal suffix check rather than Path.suffix. This aligns validator behavior with the allowed wikilink pattern and adds a regression test to cover the previously untested path.

Changes:

  • Update openkb/skill/validator.py to treat links as “already suffixed” only when they literally end with .md (case-insensitive).
  • Add a unit test ensuring dotted stems without an explicit .md suffix resolve correctly.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

FileDescription
openkb/skill/validator.pyFixes reference target path construction so dotted stems still resolve to *.md.
tests/test_skill_validator.pyAdds regression coverage for [[references/api.v2]] resolving to references/api.v2.md.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +210 to +214
# The link may already include the .md suffix; append it otherwise.
# Test the literal ".md" rather than Path.suffix — a dotted stem like
# "api.v2" has a truthy suffix (".v2"), so Path.suffix would skip the
# ".md" and then look for a non-existent extension-less file.
target = refs_dir / (link if link.lower().endswith(".md") else f"{link}.md")
Review feedback: WIKILINK_RE allows '.' and '/', so '[[references/../SKILL]]'
resolved outside references/ and was accepted whenever the resolved file
existed (and would crash the not-found message's relative_to(skill_dir)).
Reject any link whose resolved target is not under references/.

@KylinMountainKylinMountain left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jichaowang02-lang — clean fix. The dotted-stem resolution is correct, and the escape guard is a nice catch (the old code silently accepted [[references/../SKILL]]). LGTM 👍

@KylinMountain
KylinMountain merged commit 3fea8cf into VectifyAI:mainJun 23, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jichaowang02-lang@KylinMountain
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix(skill): resolve references/ wikilinks whose stem contains a dot by jichaowang02-lang · Pull Request #120 · VectifyAI/OpenKB · GitHub
Skip to content

fix(skill): resolve references/ wikilinks whose stem contains a dot - #120

Merged
KylinMountain merged 2 commits into
VectifyAI:mainfrom
jichaowang02-lang:fix/wikilink-dotted-stem-suffix
Jun 23, 2026
Merged

fix(skill): resolve references/ wikilinks whose stem contains a dot#120
KylinMountain merged 2 commits into
VectifyAI:mainfrom
jichaowang02-lang:fix/wikilink-dotted-stem-suffix

Conversation

@jichaowang02-lang

Copy link
Copy Markdown
Contributor

Summary

validate_skill reports a false "doesn't exist" error for a valid
[[references/...]] wikilink whose target stem contains a dot (e.g.
[[references/api.v2]], [[references/v1.2-guide]]), even when the file
(references/api.v2.md) is present and correctly linked.

Root cause

openkb/skill/validator.py only appended the implicit .md when
Path(link).suffix was empty:

target=refs_dir/linkifnottarget.suffix: # <-- ".v2" is a truthy suffixtarget=target.with_suffix(".md")
ifnottarget.exists(): # looks for "references/api.v2" (no .md) -> false error

Path.suffix returns everything after the last dot, so api.v2 has a
truthy suffix (.v2). The .md is never appended, and the validator then
checks for an extension-less references/api.v2, which doesn't exist —
producing a false error. WIKILINK_RE ([a-z0-9._/-]+) allows . in the
target, so such links are legal and reach this branch.

linkfile on diskbeforeafter
[[references/topic]]topic.md✅ resolves✅ (unchanged)
[[references/api.v2.md]]api.v2.md✅ resolves✅ (unchanged)
[[references/api.v2]]api.v2.md❌ false "doesn't exist"✅ resolves
[[references/ghost]](absent)✅ errors✅ errors (unchanged)

Fix

Append .md based on a literal .md check instead of Path.suffix:

target=refs_dir/ (linkiflink.lower().endswith(".md") elsef"{link}.md")

A dotted stem is now suffixed correctly; an explicit ...md link is left
alone; genuinely missing references still error.

Testing

$ pytest tests/test_skill_validator.py -q
30 passed
$ ruff check openkb/skill/validator.py tests/test_skill_validator.py
All checks passed!

Adds test_wikilink_dotted_stem_without_md_suffix_resolves — the existing
test_wikilink_without_md_suffix_resolves only covered a dot-free stem, so
this path was uncovered.

`validate_skill` appended the implicit `.md` to a `[[references/...]]` link
only when `Path(link).suffix` was empty. `Path.suffix` returns everything
after the last dot, so a reference whose stem contains a dot — e.g.
`[[references/api.v2]]` or `[[references/v1.2-guide]]` — has a truthy suffix
(`.v2` / `.2-guide`). The `.md` was therefore never appended and the
validator looked for an extension-less `references/api.v2`, emitting a false
"doesn't exist" error even though `references/api.v2.md` is present and
correctly linked. (`WIKILINK_RE` allows `.` in the target, so such links are
legal and reach this branch.)
Append `.md` based on a literal `.md` check instead of `Path.suffix`, so a
dotted stem is suffixed correctly while an explicit `...md` link is left
alone. Genuinely missing references still error.
Adds a regression test for the dotted-stem case (the existing
`test_wikilink_without_md_suffix_resolves` only covered a dot-free stem).
CopilotAI review requested due to automatic review settings June 20, 2026 02:57

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes validate_skill false negatives when resolving [[references/...]] wikilinks whose stems contain dots (e.g. api.v2), by appending .md based on a literal suffix check rather than Path.suffix. This aligns validator behavior with the allowed wikilink pattern and adds a regression test to cover the previously untested path.

Changes:

  • Update openkb/skill/validator.py to treat links as “already suffixed” only when they literally end with .md (case-insensitive).
  • Add a unit test ensuring dotted stems without an explicit .md suffix resolve correctly.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

FileDescription
openkb/skill/validator.pyFixes reference target path construction so dotted stems still resolve to *.md.
tests/test_skill_validator.pyAdds regression coverage for [[references/api.v2]] resolving to references/api.v2.md.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +210 to +214
# The link may already include the .md suffix; append it otherwise.
# Test the literal ".md" rather than Path.suffix — a dotted stem like
# "api.v2" has a truthy suffix (".v2"), so Path.suffix would skip the
# ".md" and then look for a non-existent extension-less file.
target = refs_dir / (link if link.lower().endswith(".md") else f"{link}.md")
Review feedback: WIKILINK_RE allows '.' and '/', so '[[references/../SKILL]]'
resolved outside references/ and was accepted whenever the resolved file
existed (and would crash the not-found message's relative_to(skill_dir)).
Reject any link whose resolved target is not under references/.

@KylinMountainKylinMountain left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jichaowang02-lang — clean fix. The dotted-stem resolution is correct, and the escape guard is a nice catch (the old code silently accepted [[references/../SKILL]]). LGTM 👍

@KylinMountain
KylinMountain merged commit 3fea8cf into VectifyAI:mainJun 23, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jichaowang02-lang@KylinMountain
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix(skill): resolve references/ wikilinks whose stem contains a dot by jichaowang02-lang · Pull Request #120 · VectifyAI/OpenKB · GitHub
Skip to content

fix(skill): resolve references/ wikilinks whose stem contains a dot - #120

Merged
KylinMountain merged 2 commits into
VectifyAI:mainfrom
jichaowang02-lang:fix/wikilink-dotted-stem-suffix
Jun 23, 2026
Merged

fix(skill): resolve references/ wikilinks whose stem contains a dot#120
KylinMountain merged 2 commits into
VectifyAI:mainfrom
jichaowang02-lang:fix/wikilink-dotted-stem-suffix

Conversation

@jichaowang02-lang

Copy link
Copy Markdown
Contributor

Summary

validate_skill reports a false "doesn't exist" error for a valid
[[references/...]] wikilink whose target stem contains a dot (e.g.
[[references/api.v2]], [[references/v1.2-guide]]), even when the file
(references/api.v2.md) is present and correctly linked.

Root cause

openkb/skill/validator.py only appended the implicit .md when
Path(link).suffix was empty:

target=refs_dir/linkifnottarget.suffix: # <-- ".v2" is a truthy suffixtarget=target.with_suffix(".md")
ifnottarget.exists(): # looks for "references/api.v2" (no .md) -> false error

Path.suffix returns everything after the last dot, so api.v2 has a
truthy suffix (.v2). The .md is never appended, and the validator then
checks for an extension-less references/api.v2, which doesn't exist —
producing a false error. WIKILINK_RE ([a-z0-9._/-]+) allows . in the
target, so such links are legal and reach this branch.

linkfile on diskbeforeafter
[[references/topic]]topic.md✅ resolves✅ (unchanged)
[[references/api.v2.md]]api.v2.md✅ resolves✅ (unchanged)
[[references/api.v2]]api.v2.md❌ false "doesn't exist"✅ resolves
[[references/ghost]](absent)✅ errors✅ errors (unchanged)

Fix

Append .md based on a literal .md check instead of Path.suffix:

target=refs_dir/ (linkiflink.lower().endswith(".md") elsef"{link}.md")

A dotted stem is now suffixed correctly; an explicit ...md link is left
alone; genuinely missing references still error.

Testing

$ pytest tests/test_skill_validator.py -q
30 passed
$ ruff check openkb/skill/validator.py tests/test_skill_validator.py
All checks passed!

Adds test_wikilink_dotted_stem_without_md_suffix_resolves — the existing
test_wikilink_without_md_suffix_resolves only covered a dot-free stem, so
this path was uncovered.

`validate_skill` appended the implicit `.md` to a `[[references/...]]` link
only when `Path(link).suffix` was empty. `Path.suffix` returns everything
after the last dot, so a reference whose stem contains a dot — e.g.
`[[references/api.v2]]` or `[[references/v1.2-guide]]` — has a truthy suffix
(`.v2` / `.2-guide`). The `.md` was therefore never appended and the
validator looked for an extension-less `references/api.v2`, emitting a false
"doesn't exist" error even though `references/api.v2.md` is present and
correctly linked. (`WIKILINK_RE` allows `.` in the target, so such links are
legal and reach this branch.)
Append `.md` based on a literal `.md` check instead of `Path.suffix`, so a
dotted stem is suffixed correctly while an explicit `...md` link is left
alone. Genuinely missing references still error.
Adds a regression test for the dotted-stem case (the existing
`test_wikilink_without_md_suffix_resolves` only covered a dot-free stem).
CopilotAI review requested due to automatic review settings June 20, 2026 02:57

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes validate_skill false negatives when resolving [[references/...]] wikilinks whose stems contain dots (e.g. api.v2), by appending .md based on a literal suffix check rather than Path.suffix. This aligns validator behavior with the allowed wikilink pattern and adds a regression test to cover the previously untested path.

Changes:

  • Update openkb/skill/validator.py to treat links as “already suffixed” only when they literally end with .md (case-insensitive).
  • Add a unit test ensuring dotted stems without an explicit .md suffix resolve correctly.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

FileDescription
openkb/skill/validator.pyFixes reference target path construction so dotted stems still resolve to *.md.
tests/test_skill_validator.pyAdds regression coverage for [[references/api.v2]] resolving to references/api.v2.md.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +210 to +214
# The link may already include the .md suffix; append it otherwise.
# Test the literal ".md" rather than Path.suffix — a dotted stem like
# "api.v2" has a truthy suffix (".v2"), so Path.suffix would skip the
# ".md" and then look for a non-existent extension-less file.
target = refs_dir / (link if link.lower().endswith(".md") else f"{link}.md")
Review feedback: WIKILINK_RE allows '.' and '/', so '[[references/../SKILL]]'
resolved outside references/ and was accepted whenever the resolved file
existed (and would crash the not-found message's relative_to(skill_dir)).
Reject any link whose resolved target is not under references/.

@KylinMountainKylinMountain left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jichaowang02-lang — clean fix. The dotted-stem resolution is correct, and the escape guard is a nice catch (the old code silently accepted [[references/../SKILL]]). LGTM 👍

@KylinMountain
KylinMountain merged commit 3fea8cf into VectifyAI:mainJun 23, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jichaowang02-lang@KylinMountain
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' fix(skill): resolve references/ wikilinks whose stem contains a dot by jichaowang02-lang · Pull Request #120 · VectifyAI/OpenKB · GitHub
Skip to content

fix(skill): resolve references/ wikilinks whose stem contains a dot - #120

Merged
KylinMountain merged 2 commits into
VectifyAI:mainfrom
jichaowang02-lang:fix/wikilink-dotted-stem-suffix
Jun 23, 2026
Merged

fix(skill): resolve references/ wikilinks whose stem contains a dot#120
KylinMountain merged 2 commits into
VectifyAI:mainfrom
jichaowang02-lang:fix/wikilink-dotted-stem-suffix

Conversation

@jichaowang02-lang

Copy link
Copy Markdown
Contributor

Summary

validate_skill reports a false "doesn't exist" error for a valid
[[references/...]] wikilink whose target stem contains a dot (e.g.
[[references/api.v2]], [[references/v1.2-guide]]), even when the file
(references/api.v2.md) is present and correctly linked.

Root cause

openkb/skill/validator.py only appended the implicit .md when
Path(link).suffix was empty:

target=refs_dir/linkifnottarget.suffix: # <-- ".v2" is a truthy suffixtarget=target.with_suffix(".md")
ifnottarget.exists(): # looks for "references/api.v2" (no .md) -> false error

Path.suffix returns everything after the last dot, so api.v2 has a
truthy suffix (.v2). The .md is never appended, and the validator then
checks for an extension-less references/api.v2, which doesn't exist —
producing a false error. WIKILINK_RE ([a-z0-9._/-]+) allows . in the
target, so such links are legal and reach this branch.

linkfile on diskbeforeafter
[[references/topic]]topic.md✅ resolves✅ (unchanged)
[[references/api.v2.md]]api.v2.md✅ resolves✅ (unchanged)
[[references/api.v2]]api.v2.md❌ false "doesn't exist"✅ resolves
[[references/ghost]](absent)✅ errors✅ errors (unchanged)

Fix

Append .md based on a literal .md check instead of Path.suffix:

target=refs_dir/ (linkiflink.lower().endswith(".md") elsef"{link}.md")

A dotted stem is now suffixed correctly; an explicit ...md link is left
alone; genuinely missing references still error.

Testing

$ pytest tests/test_skill_validator.py -q
30 passed
$ ruff check openkb/skill/validator.py tests/test_skill_validator.py
All checks passed!

Adds test_wikilink_dotted_stem_without_md_suffix_resolves — the existing
test_wikilink_without_md_suffix_resolves only covered a dot-free stem, so
this path was uncovered.

`validate_skill` appended the implicit `.md` to a `[[references/...]]` link
only when `Path(link).suffix` was empty. `Path.suffix` returns everything
after the last dot, so a reference whose stem contains a dot — e.g.
`[[references/api.v2]]` or `[[references/v1.2-guide]]` — has a truthy suffix
(`.v2` / `.2-guide`). The `.md` was therefore never appended and the
validator looked for an extension-less `references/api.v2`, emitting a false
"doesn't exist" error even though `references/api.v2.md` is present and
correctly linked. (`WIKILINK_RE` allows `.` in the target, so such links are
legal and reach this branch.)
Append `.md` based on a literal `.md` check instead of `Path.suffix`, so a
dotted stem is suffixed correctly while an explicit `...md` link is left
alone. Genuinely missing references still error.
Adds a regression test for the dotted-stem case (the existing
`test_wikilink_without_md_suffix_resolves` only covered a dot-free stem).
CopilotAI review requested due to automatic review settings June 20, 2026 02:57

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes validate_skill false negatives when resolving [[references/...]] wikilinks whose stems contain dots (e.g. api.v2), by appending .md based on a literal suffix check rather than Path.suffix. This aligns validator behavior with the allowed wikilink pattern and adds a regression test to cover the previously untested path.

Changes:

  • Update openkb/skill/validator.py to treat links as “already suffixed” only when they literally end with .md (case-insensitive).
  • Add a unit test ensuring dotted stems without an explicit .md suffix resolve correctly.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

FileDescription
openkb/skill/validator.pyFixes reference target path construction so dotted stems still resolve to *.md.
tests/test_skill_validator.pyAdds regression coverage for [[references/api.v2]] resolving to references/api.v2.md.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +210 to +214
# The link may already include the .md suffix; append it otherwise.
# Test the literal ".md" rather than Path.suffix — a dotted stem like
# "api.v2" has a truthy suffix (".v2"), so Path.suffix would skip the
# ".md" and then look for a non-existent extension-less file.
target = refs_dir / (link if link.lower().endswith(".md") else f"{link}.md")
Review feedback: WIKILINK_RE allows '.' and '/', so '[[references/../SKILL]]'
resolved outside references/ and was accepted whenever the resolved file
existed (and would crash the not-found message's relative_to(skill_dir)).
Reject any link whose resolved target is not under references/.

@KylinMountainKylinMountain left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jichaowang02-lang — clean fix. The dotted-stem resolution is correct, and the escape guard is a nice catch (the old code silently accepted [[references/../SKILL]]). LGTM 👍

@KylinMountain
KylinMountain merged commit 3fea8cf into VectifyAI:mainJun 23, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jichaowang02-lang@KylinMountain
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix(skill): resolve references/ wikilinks whose stem contains a dot by jichaowang02-lang · Pull Request #120 · VectifyAI/OpenKB · GitHub
Skip to content

fix(skill): resolve references/ wikilinks whose stem contains a dot - #120

Merged
KylinMountain merged 2 commits into
VectifyAI:mainfrom
jichaowang02-lang:fix/wikilink-dotted-stem-suffix
Jun 23, 2026
Merged

fix(skill): resolve references/ wikilinks whose stem contains a dot#120
KylinMountain merged 2 commits into
VectifyAI:mainfrom
jichaowang02-lang:fix/wikilink-dotted-stem-suffix

Conversation

@jichaowang02-lang

Copy link
Copy Markdown
Contributor

Summary

validate_skill reports a false "doesn't exist" error for a valid
[[references/...]] wikilink whose target stem contains a dot (e.g.
[[references/api.v2]], [[references/v1.2-guide]]), even when the file
(references/api.v2.md) is present and correctly linked.

Root cause

openkb/skill/validator.py only appended the implicit .md when
Path(link).suffix was empty:

target=refs_dir/linkifnottarget.suffix: # <-- ".v2" is a truthy suffixtarget=target.with_suffix(".md")
ifnottarget.exists(): # looks for "references/api.v2" (no .md) -> false error

Path.suffix returns everything after the last dot, so api.v2 has a
truthy suffix (.v2). The .md is never appended, and the validator then
checks for an extension-less references/api.v2, which doesn't exist —
producing a false error. WIKILINK_RE ([a-z0-9._/-]+) allows . in the
target, so such links are legal and reach this branch.

linkfile on diskbeforeafter
[[references/topic]]topic.md✅ resolves✅ (unchanged)
[[references/api.v2.md]]api.v2.md✅ resolves✅ (unchanged)
[[references/api.v2]]api.v2.md❌ false "doesn't exist"✅ resolves
[[references/ghost]](absent)✅ errors✅ errors (unchanged)

Fix

Append .md based on a literal .md check instead of Path.suffix:

target=refs_dir/ (linkiflink.lower().endswith(".md") elsef"{link}.md")

A dotted stem is now suffixed correctly; an explicit ...md link is left
alone; genuinely missing references still error.

Testing

$ pytest tests/test_skill_validator.py -q
30 passed
$ ruff check openkb/skill/validator.py tests/test_skill_validator.py
All checks passed!

Adds test_wikilink_dotted_stem_without_md_suffix_resolves — the existing
test_wikilink_without_md_suffix_resolves only covered a dot-free stem, so
this path was uncovered.

`validate_skill` appended the implicit `.md` to a `[[references/...]]` link
only when `Path(link).suffix` was empty. `Path.suffix` returns everything
after the last dot, so a reference whose stem contains a dot — e.g.
`[[references/api.v2]]` or `[[references/v1.2-guide]]` — has a truthy suffix
(`.v2` / `.2-guide`). The `.md` was therefore never appended and the
validator looked for an extension-less `references/api.v2`, emitting a false
"doesn't exist" error even though `references/api.v2.md` is present and
correctly linked. (`WIKILINK_RE` allows `.` in the target, so such links are
legal and reach this branch.)
Append `.md` based on a literal `.md` check instead of `Path.suffix`, so a
dotted stem is suffixed correctly while an explicit `...md` link is left
alone. Genuinely missing references still error.
Adds a regression test for the dotted-stem case (the existing
`test_wikilink_without_md_suffix_resolves` only covered a dot-free stem).
CopilotAI review requested due to automatic review settings June 20, 2026 02:57

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes validate_skill false negatives when resolving [[references/...]] wikilinks whose stems contain dots (e.g. api.v2), by appending .md based on a literal suffix check rather than Path.suffix. This aligns validator behavior with the allowed wikilink pattern and adds a regression test to cover the previously untested path.

Changes:

  • Update openkb/skill/validator.py to treat links as “already suffixed” only when they literally end with .md (case-insensitive).
  • Add a unit test ensuring dotted stems without an explicit .md suffix resolve correctly.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

FileDescription
openkb/skill/validator.pyFixes reference target path construction so dotted stems still resolve to *.md.
tests/test_skill_validator.pyAdds regression coverage for [[references/api.v2]] resolving to references/api.v2.md.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +210 to +214
# The link may already include the .md suffix; append it otherwise.
# Test the literal ".md" rather than Path.suffix — a dotted stem like
# "api.v2" has a truthy suffix (".v2"), so Path.suffix would skip the
# ".md" and then look for a non-existent extension-less file.
target = refs_dir / (link if link.lower().endswith(".md") else f"{link}.md")
Review feedback: WIKILINK_RE allows '.' and '/', so '[[references/../SKILL]]'
resolved outside references/ and was accepted whenever the resolved file
existed (and would crash the not-found message's relative_to(skill_dir)).
Reject any link whose resolved target is not under references/.

@KylinMountainKylinMountain left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jichaowang02-lang — clean fix. The dotted-stem resolution is correct, and the escape guard is a nice catch (the old code silently accepted [[references/../SKILL]]). LGTM 👍

@KylinMountain
KylinMountain merged commit 3fea8cf into VectifyAI:mainJun 23, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jichaowang02-lang@KylinMountain
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix(skill): resolve references/ wikilinks whose stem contains a dot by jichaowang02-lang · Pull Request #120 · VectifyAI/OpenKB · GitHub
Skip to content

fix(skill): resolve references/ wikilinks whose stem contains a dot - #120

Merged
KylinMountain merged 2 commits into
VectifyAI:mainfrom
jichaowang02-lang:fix/wikilink-dotted-stem-suffix
Jun 23, 2026
Merged

fix(skill): resolve references/ wikilinks whose stem contains a dot#120
KylinMountain merged 2 commits into
VectifyAI:mainfrom
jichaowang02-lang:fix/wikilink-dotted-stem-suffix

Conversation

@jichaowang02-lang

Copy link
Copy Markdown
Contributor

Summary

validate_skill reports a false "doesn't exist" error for a valid
[[references/...]] wikilink whose target stem contains a dot (e.g.
[[references/api.v2]], [[references/v1.2-guide]]), even when the file
(references/api.v2.md) is present and correctly linked.

Root cause

openkb/skill/validator.py only appended the implicit .md when
Path(link).suffix was empty:

target=refs_dir/linkifnottarget.suffix: # <-- ".v2" is a truthy suffixtarget=target.with_suffix(".md")
ifnottarget.exists(): # looks for "references/api.v2" (no .md) -> false error

Path.suffix returns everything after the last dot, so api.v2 has a
truthy suffix (.v2). The .md is never appended, and the validator then
checks for an extension-less references/api.v2, which doesn't exist —
producing a false error. WIKILINK_RE ([a-z0-9._/-]+) allows . in the
target, so such links are legal and reach this branch.

linkfile on diskbeforeafter
[[references/topic]]topic.md✅ resolves✅ (unchanged)
[[references/api.v2.md]]api.v2.md✅ resolves✅ (unchanged)
[[references/api.v2]]api.v2.md❌ false "doesn't exist"✅ resolves
[[references/ghost]](absent)✅ errors✅ errors (unchanged)

Fix

Append .md based on a literal .md check instead of Path.suffix:

target=refs_dir/ (linkiflink.lower().endswith(".md") elsef"{link}.md")

A dotted stem is now suffixed correctly; an explicit ...md link is left
alone; genuinely missing references still error.

Testing

$ pytest tests/test_skill_validator.py -q
30 passed
$ ruff check openkb/skill/validator.py tests/test_skill_validator.py
All checks passed!

Adds test_wikilink_dotted_stem_without_md_suffix_resolves — the existing
test_wikilink_without_md_suffix_resolves only covered a dot-free stem, so
this path was uncovered.

`validate_skill` appended the implicit `.md` to a `[[references/...]]` link
only when `Path(link).suffix` was empty. `Path.suffix` returns everything
after the last dot, so a reference whose stem contains a dot — e.g.
`[[references/api.v2]]` or `[[references/v1.2-guide]]` — has a truthy suffix
(`.v2` / `.2-guide`). The `.md` was therefore never appended and the
validator looked for an extension-less `references/api.v2`, emitting a false
"doesn't exist" error even though `references/api.v2.md` is present and
correctly linked. (`WIKILINK_RE` allows `.` in the target, so such links are
legal and reach this branch.)
Append `.md` based on a literal `.md` check instead of `Path.suffix`, so a
dotted stem is suffixed correctly while an explicit `...md` link is left
alone. Genuinely missing references still error.
Adds a regression test for the dotted-stem case (the existing
`test_wikilink_without_md_suffix_resolves` only covered a dot-free stem).
CopilotAI review requested due to automatic review settings June 20, 2026 02:57

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes validate_skill false negatives when resolving [[references/...]] wikilinks whose stems contain dots (e.g. api.v2), by appending .md based on a literal suffix check rather than Path.suffix. This aligns validator behavior with the allowed wikilink pattern and adds a regression test to cover the previously untested path.

Changes:

  • Update openkb/skill/validator.py to treat links as “already suffixed” only when they literally end with .md (case-insensitive).
  • Add a unit test ensuring dotted stems without an explicit .md suffix resolve correctly.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

FileDescription
openkb/skill/validator.pyFixes reference target path construction so dotted stems still resolve to *.md.
tests/test_skill_validator.pyAdds regression coverage for [[references/api.v2]] resolving to references/api.v2.md.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +210 to +214
# The link may already include the .md suffix; append it otherwise.
# Test the literal ".md" rather than Path.suffix — a dotted stem like
# "api.v2" has a truthy suffix (".v2"), so Path.suffix would skip the
# ".md" and then look for a non-existent extension-less file.
target = refs_dir / (link if link.lower().endswith(".md") else f"{link}.md")
Review feedback: WIKILINK_RE allows '.' and '/', so '[[references/../SKILL]]'
resolved outside references/ and was accepted whenever the resolved file
existed (and would crash the not-found message's relative_to(skill_dir)).
Reject any link whose resolved target is not under references/.

@KylinMountainKylinMountain left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jichaowang02-lang — clean fix. The dotted-stem resolution is correct, and the escape guard is a nice catch (the old code silently accepted [[references/../SKILL]]). LGTM 👍

@KylinMountain
KylinMountain merged commit 3fea8cf into VectifyAI:mainJun 23, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jichaowang02-lang@KylinMountain
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); fix(skill): resolve references/ wikilinks whose stem contains a dot by jichaowang02-lang · Pull Request #120 · VectifyAI/OpenKB · GitHub
Skip to content

fix(skill): resolve references/ wikilinks whose stem contains a dot - #120

Merged
KylinMountain merged 2 commits into
VectifyAI:mainfrom
jichaowang02-lang:fix/wikilink-dotted-stem-suffix
Jun 23, 2026
Merged

fix(skill): resolve references/ wikilinks whose stem contains a dot#120
KylinMountain merged 2 commits into
VectifyAI:mainfrom
jichaowang02-lang:fix/wikilink-dotted-stem-suffix

Conversation

@jichaowang02-lang

Copy link
Copy Markdown
Contributor

Summary

validate_skill reports a false "doesn't exist" error for a valid
[[references/...]] wikilink whose target stem contains a dot (e.g.
[[references/api.v2]], [[references/v1.2-guide]]), even when the file
(references/api.v2.md) is present and correctly linked.

Root cause

openkb/skill/validator.py only appended the implicit .md when
Path(link).suffix was empty:

target=refs_dir/linkifnottarget.suffix: # <-- ".v2" is a truthy suffixtarget=target.with_suffix(".md")
ifnottarget.exists(): # looks for "references/api.v2" (no .md) -> false error

Path.suffix returns everything after the last dot, so api.v2 has a
truthy suffix (.v2). The .md is never appended, and the validator then
checks for an extension-less references/api.v2, which doesn't exist —
producing a false error. WIKILINK_RE ([a-z0-9._/-]+) allows . in the
target, so such links are legal and reach this branch.

linkfile on diskbeforeafter
[[references/topic]]topic.md✅ resolves✅ (unchanged)
[[references/api.v2.md]]api.v2.md✅ resolves✅ (unchanged)
[[references/api.v2]]api.v2.md❌ false "doesn't exist"✅ resolves
[[references/ghost]](absent)✅ errors✅ errors (unchanged)

Fix

Append .md based on a literal .md check instead of Path.suffix:

target=refs_dir/ (linkiflink.lower().endswith(".md") elsef"{link}.md")

A dotted stem is now suffixed correctly; an explicit ...md link is left
alone; genuinely missing references still error.

Testing

$ pytest tests/test_skill_validator.py -q
30 passed
$ ruff check openkb/skill/validator.py tests/test_skill_validator.py
All checks passed!

Adds test_wikilink_dotted_stem_without_md_suffix_resolves — the existing
test_wikilink_without_md_suffix_resolves only covered a dot-free stem, so
this path was uncovered.

`validate_skill` appended the implicit `.md` to a `[[references/...]]` link
only when `Path(link).suffix` was empty. `Path.suffix` returns everything
after the last dot, so a reference whose stem contains a dot — e.g.
`[[references/api.v2]]` or `[[references/v1.2-guide]]` — has a truthy suffix
(`.v2` / `.2-guide`). The `.md` was therefore never appended and the
validator looked for an extension-less `references/api.v2`, emitting a false
"doesn't exist" error even though `references/api.v2.md` is present and
correctly linked. (`WIKILINK_RE` allows `.` in the target, so such links are
legal and reach this branch.)
Append `.md` based on a literal `.md` check instead of `Path.suffix`, so a
dotted stem is suffixed correctly while an explicit `...md` link is left
alone. Genuinely missing references still error.
Adds a regression test for the dotted-stem case (the existing
`test_wikilink_without_md_suffix_resolves` only covered a dot-free stem).
CopilotAI review requested due to automatic review settings June 20, 2026 02:57

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes validate_skill false negatives when resolving [[references/...]] wikilinks whose stems contain dots (e.g. api.v2), by appending .md based on a literal suffix check rather than Path.suffix. This aligns validator behavior with the allowed wikilink pattern and adds a regression test to cover the previously untested path.

Changes:

  • Update openkb/skill/validator.py to treat links as “already suffixed” only when they literally end with .md (case-insensitive).
  • Add a unit test ensuring dotted stems without an explicit .md suffix resolve correctly.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

FileDescription
openkb/skill/validator.pyFixes reference target path construction so dotted stems still resolve to *.md.
tests/test_skill_validator.pyAdds regression coverage for [[references/api.v2]] resolving to references/api.v2.md.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +210 to +214
# The link may already include the .md suffix; append it otherwise.
# Test the literal ".md" rather than Path.suffix — a dotted stem like
# "api.v2" has a truthy suffix (".v2"), so Path.suffix would skip the
# ".md" and then look for a non-existent extension-less file.
target = refs_dir / (link if link.lower().endswith(".md") else f"{link}.md")
Review feedback: WIKILINK_RE allows '.' and '/', so '[[references/../SKILL]]'
resolved outside references/ and was accepted whenever the resolved file
existed (and would crash the not-found message's relative_to(skill_dir)).
Reject any link whose resolved target is not under references/.

@KylinMountainKylinMountain left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jichaowang02-lang — clean fix. The dotted-stem resolution is correct, and the escape guard is a nice catch (the old code silently accepted [[references/../SKILL]]). LGTM 👍

@KylinMountain
KylinMountain merged commit 3fea8cf into VectifyAI:mainJun 23, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jichaowang02-lang@KylinMountain