Summary
openclaw wiki lint produces two classes of false/unfixable "Broken wikilink target" warnings that are rooted in the wikilink extractor and link resolver implementations themselves, not in vault content. After a live vault audit (~150 pages, 84 warnings), roughly all warnings fall into these two buckets:
- Parser is markdown-blind — literal
[[...]] inside prose/code/transcripts is extracted as a wikilink target, even when it is clearly documentation syntax, an OpenClaw directive tag, or a quoted transcript.
- Resolver only indexes slugified path + basename, never frontmatter
title — natural-title wikilinks like [[Codex harness plugin 配置清单]] can never resolve, because the resolver's validTargets set only contains post-slugification forms.
These are upstream bugs in the memory-wiki plugin, independent of #64696 (which proposes tag-specific sanitization for [[reply_to_*]]). The fix scope proposed below targets the root causes, which would also cover #64696 without per-tag bandaids.
Installed version: openclaw 2026.4.22 (commit 00bd2cf).
Evidence
Class 1 — parser false positives on literal [[...]]
Sample warnings from Wiki/reports/lint.md:
Broken wikilink target `tts:text`.
Broken wikilink target `reply_to:<id>`.
Broken wikilink target `reply_to_current`.
Broken wikilink target `wikilinks`.
Broken wikilink target `...`.
Concrete example — reply_to_current occurs 8 times in this one bridged source page, always in plain prose inside transcript text, not as a real wikilink:
Wiki/sources/bridge-workspace-system-architect-1ca28ce0-memory-2026-04-19-provider-name-c3ee55a4 2.md
line 34: assistant: [[reply_to_current]]
line 124: assistant: [[reply_to_current]]
line 218: assistant: [[reply_to_current]]
...
These are literal OpenClaw reply directives that were captured verbatim when the session transcript was bridged into the vault. Similar patterns occur for [[tts:text]], [[reply_to:<id>]], and for markdown meta-discussions where users literally write [[wikilinks]] or [[...]] as documentation syntax. [[Omitted long matching line]] (system truncation hint) also gets extracted.
Class 2 — resolver cannot match wikilinks written by natural title
All four of the following are real, on-disk, indexed source pages whose frontmatter title exactly matches the [[...]] target — but lint flags them as broken:
| Wikilink in body |
Target file that exists |
Frontmatter title |
[[Codex harness plugin 配置清单]] |
Wiki/sources/codex-harness-plugin-配置清单.md (bridged from OpenClaw/GPT 5 系列/Codex harness plugin 配置清单.md) |
Codex harness plugin 配置清单 |
[[OpenClaw Agent 体系深度分析 — openclaw-agent-system]] |
Wiki/sources/openclaw-agent-体系深度分析.md |
OpenClaw Agent 体系深度分析 |
[[深度解析 OpenClaw Prompt Context Harness]] |
Wiki/sources/深度解析-openclaw-prompt-context-harness.md (verified on-disk) |
深度解析 OpenClaw Prompt Context Harness |
[[OpenClaw × Claude Code × Codex 共享 Memory 方案]] |
slugified filename drops the × characters |
OpenClaw × Claude Code × Codex 共享 Memory 方案 |
Frontmatter of the first target, verified via head:
---
pageType: source
id: source.codex-harness-plugin-配置清单
title: Codex harness plugin 配置清单
sourceType: local-file
sourcePath: /…/OpenClaw/GPT 5 系列/Codex harness plugin 配置清单.md
---
Users naturally write [[Codex harness plugin 配置清单]]. The resolver never matches, because its validTargets set only contains sources/codex-harness-plugin-配置清单 and codex-harness-plugin-配置清单 — the slugified forms.
Root cause (verified in installed source)
1. Parser is not markdown-aware
/opt/homebrew/lib/node_modules/openclaw/dist/cli-BF_4kd_o.js:
// line 180
const OBSIDIAN_LINK_PATTERN = /\[\[([^\]|]+)(?:\|[^\]]+)?\]\]/g;
// line 273
function extractWikiLinks(markdown) {
const searchable = markdown.replace(RELATED_BLOCK_PATTERN, "");
const links = [];
for (const match of searchable.matchAll(OBSIDIAN_LINK_PATTERN)) {
const target = match[1]?.trim();
if (target) links.push(target);
}
…
}
The regex is run directly against the raw document minus only the openclaw:wiki:related managed block. It does not skip:
- fenced code blocks (```` ``` `)
- inline code (
`)
- YAML frontmatter
- HTML comments
- Obsidian callouts with code examples
Any document that talks about OpenClaw directives, Obsidian wikilink syntax, or session transcripts will emit spurious targets. Known Issue tts-parser-markdown-blind (our internal tracker) describes the exact same class of bug in the TTS directive parser — this is the wiki parser's sibling.
2. Resolver only knows slugified paths
Same bundle, lines ~2286–2300:
function collectBrokenLinkIssues(pages) {
const validTargets = new Set();
for (const page of pages) {
const withoutExtension = page.relativePath.replace(/\.md$/i, "");
validTargets.add(withoutExtension); // "sources/codex-harness-plugin-配置清单"
validTargets.add(path.basename(withoutExtension)); // "codex-harness-plugin-配置清单"
}
const issues = [];
for (const page of pages)
for (const linkTarget of page.linkTargets)
if (!validTargets.has(linkTarget))
issues.push({ severity: "warning", category: "links", code: "broken-wikilink", … });
return issues;
}
validTargets never contains page.title, so [[<natural title>]] is guaranteed to miss whenever the stored file has been slugified (which is the default for ingested Chinese-title content, any filename with special characters like ×, or long-title files). formatWikiLink() emits Obsidian-style [[slug|Title]] aliases, which the extractor correctly strips via its (?:\|[^\]]+)? group — but anything the user or Librarian writes as [[Title]] bare is unresolvable.
Expected behavior
- The wikilink extractor should respect Markdown / MDX structure and not extract
[[...]] tokens that appear inside:
- fenced code blocks (
… and ~~~)
- inline code (
`…`)
- YAML frontmatter
- HTML comments
- The resolver should additionally accept:
- a match against
page.title (case-insensitive, or case-sensitive + normalized whitespace)
- optionally, a match after the user's stored slug rule is applied to the extracted target (so both
[[Codex harness plugin 配置清单]] and [[codex-harness-plugin-配置清单]] resolve to the same page)
Proposed fix scope
- Parser: strip fenced code blocks, inline code, and HTML comments from
searchable before the wikilink regex runs. The YAML frontmatter is already addressed upstream; fenced / inline code are the main holes.
- Resolver: build
validTargets as a union of {relativePath sans .md, basename, frontmatter.title, slugify(frontmatter.title), any declared aliases}; compare extracted target against all of them using a normalization function (lowercase, collapse whitespace, unify —/-).
- Docs: if wikilinks by slug remain a blessed form, note it explicitly; but title-based resolution is what every existing Obsidian-vault user expects and what OpenClaw's own
formatWikiLink alias rendering implies.
Related
Markdown-awareness in the extractor is the root-cause fix that subsumes the per-tag approach.
Reproduction
- In a bridge-mode vault, bridge a session transcript that contains the string
[[reply_to_current]] literally in assistant output.
- Create
sources/example-配置清单.md with frontmatter title: Example 配置清单.
- In another page, link it with
[[Example 配置清单]].
- Run
openclaw wiki lint.
Both lines will appear as Broken wikilink target ….
Acceptance criteria
openclaw wiki lint does not flag [[…]] that sits inside a fenced code block or inline code span.
openclaw wiki lint resolves [[<title>]] when any indexed page's frontmatter title equals the target (normalization policy documented).
- Vaults upgrading from the current implementation stop seeing false-positive
Broken wikilink target for OpenClaw directive tags that appear in bridged transcripts, without requiring a tag-specific allowlist.
Environment
- OpenClaw: 2026.4.22 (00bd2cf), macOS 15.7.3
- Plugin:
dist/extensions/memory-wiki (bundled)
- Vault: bridge mode, Obsidian render mode, 150 pages
Summary
openclaw wiki lintproduces two classes of false/unfixable "Broken wikilink target" warnings that are rooted in the wikilink extractor and link resolver implementations themselves, not in vault content. After a live vault audit (~150 pages, 84 warnings), roughly all warnings fall into these two buckets:[[...]]inside prose/code/transcripts is extracted as a wikilink target, even when it is clearly documentation syntax, an OpenClaw directive tag, or a quoted transcript.title— natural-title wikilinks like[[Codex harness plugin 配置清单]]can never resolve, because the resolver'svalidTargetsset only contains post-slugification forms.These are upstream bugs in the memory-wiki plugin, independent of #64696 (which proposes tag-specific sanitization for
[[reply_to_*]]). The fix scope proposed below targets the root causes, which would also cover #64696 without per-tag bandaids.Installed version:
openclaw 2026.4.22(commit00bd2cf).Evidence
Class 1 — parser false positives on literal
[[...]]Sample warnings from
Wiki/reports/lint.md:Broken wikilink target `tts:text`.Broken wikilink target `reply_to:<id>`.Broken wikilink target `reply_to_current`.Broken wikilink target `wikilinks`.Broken wikilink target `...`.Concrete example —
reply_to_currentoccurs 8 times in this one bridged source page, always in plain prose inside transcript text, not as a real wikilink:These are literal OpenClaw reply directives that were captured verbatim when the session transcript was bridged into the vault. Similar patterns occur for
[[tts:text]],[[reply_to:<id>]], and for markdown meta-discussions where users literally write[[wikilinks]]or[[...]]as documentation syntax.[[Omitted long matching line]](system truncation hint) also gets extracted.Class 2 — resolver cannot match wikilinks written by natural title
All four of the following are real, on-disk, indexed source pages whose frontmatter
titleexactly matches the[[...]]target — but lint flags them as broken:[[Codex harness plugin 配置清单]]Wiki/sources/codex-harness-plugin-配置清单.md(bridged fromOpenClaw/GPT 5 系列/Codex harness plugin 配置清单.md)Codex harness plugin 配置清单[[OpenClaw Agent 体系深度分析 — openclaw-agent-system]]Wiki/sources/openclaw-agent-体系深度分析.mdOpenClaw Agent 体系深度分析[[深度解析 OpenClaw Prompt Context Harness]]Wiki/sources/深度解析-openclaw-prompt-context-harness.md(verified on-disk)深度解析 OpenClaw Prompt Context Harness[[OpenClaw × Claude Code × Codex 共享 Memory 方案]]×charactersOpenClaw × Claude Code × Codex 共享 Memory 方案Frontmatter of the first target, verified via
head:Users naturally write
[[Codex harness plugin 配置清单]]. The resolver never matches, because itsvalidTargetsset only containssources/codex-harness-plugin-配置清单andcodex-harness-plugin-配置清单— the slugified forms.Root cause (verified in installed source)
1. Parser is not markdown-aware
/opt/homebrew/lib/node_modules/openclaw/dist/cli-BF_4kd_o.js:The regex is run directly against the raw document minus only the
openclaw:wiki:relatedmanaged block. It does not skip:`)Any document that talks about OpenClaw directives, Obsidian wikilink syntax, or session transcripts will emit spurious targets. Known Issue
tts-parser-markdown-blind(our internal tracker) describes the exact same class of bug in the TTS directive parser — this is the wiki parser's sibling.2. Resolver only knows slugified paths
Same bundle, lines ~2286–2300:
validTargetsnever containspage.title, so[[<natural title>]]is guaranteed to miss whenever the stored file has been slugified (which is the default for ingested Chinese-title content, any filename with special characters like×, or long-title files).formatWikiLink()emits Obsidian-style[[slug|Title]]aliases, which the extractor correctly strips via its(?:\|[^\]]+)?group — but anything the user or Librarian writes as[[Title]]bare is unresolvable.Expected behavior
[[...]]tokens that appear inside:…and~~~)`…`)page.title(case-insensitive, or case-sensitive + normalized whitespace)[[Codex harness plugin 配置清单]]and[[codex-harness-plugin-配置清单]]resolve to the same page)Proposed fix scope
searchablebefore the wikilink regex runs. The YAML frontmatter is already addressed upstream; fenced / inline code are the main holes.validTargetsas a union of{relativePath sans .md, basename, frontmatter.title, slugify(frontmatter.title), any declared aliases}; compare extracted target against all of them using a normalization function (lowercase, collapse whitespace, unify—/-).formatWikiLinkalias rendering implies.Related
reply_to_current,reply_to:<id>) at render time. That is a narrower fix for Class 1 and does not address:[[tts:text]],[[embed …]],[[media …]], etc.)[[wikilinks]]Markdown-awareness in the extractor is the root-cause fix that subsumes the per-tag approach.
Reproduction
[[reply_to_current]]literally in assistant output.sources/example-配置清单.mdwith frontmattertitle: Example 配置清单.[[Example 配置清单]].openclaw wiki lint.Both lines will appear as
Broken wikilink target ….Acceptance criteria
openclaw wiki lintdoes not flag[[…]]that sits inside a fenced code block or inline code span.openclaw wiki lintresolves[[<title>]]when any indexed page's frontmattertitleequals the target (normalization policy documented).Broken wikilink targetfor OpenClaw directive tags that appear in bridged transcripts, without requiring a tag-specific allowlist.Environment
dist/extensions/memory-wiki(bundled)