Skip to content

fix(memory-wiki): ignore wikilink-like text in code spans during lint#97977

Closed
hanZeng-08 wants to merge 2 commits into
openclaw:mainfrom
hanZeng-08:fix/97945-wikilink-extractor-markdown-aware
Closed

fix(memory-wiki): ignore wikilink-like text in code spans during lint#97977
hanZeng-08 wants to merge 2 commits into
openclaw:mainfrom
hanZeng-08:fix/97945-wikilink-extractor-markdown-aware

Conversation

@hanZeng-08

@hanZeng-08 hanZeng-08 commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Fixes #97945
Reopens #70986 (Class 1 only)

What Problem This Solves

Fixes an issue where openclaw wiki lint reports false-positive Broken wikilink target warnings for [[...]] patterns that appear inside fenced code blocks and inline code spans. Real vaults with Scala/bash examples or bridged session transcripts see hundreds of spurious warnings, making the lint report noisy and hiding genuine link issues.

Why This Change Was Made

The wikilink extractor ran its regex against the raw Markdown body after removing only the managed related-links block. It did not exclude code spans, so literal syntax like Future[Option[User]], [[ "$x" == "y" ]], or [[reply_to_current]] was extracted as a link target.

The fix strips fenced code blocks (line-by-line, supporting backtick and tilde fences of any length, including bare fences without an info string) and inline code spans (including multi-backtick forms) before extraction. This is safer than a single broad regex because it preserves real wikilinks that sit between two separate code blocks and handles malformed unclosed fences conservatively.

User Impact

Users running openclaw wiki lint on vaults containing code examples or bridged transcripts will see far fewer false Broken wikilink target warnings. Genuine broken wikilinks in prose continue to be reported.

Evidence

Environment: Linux, Node v22.23.1, pnpm 11.2.2, OpenClaw 2026.5.28, worktree SHA 1052652

Unit tests

$ pnpm test extensions/memory-wiki/src/lint.test.ts
 Test Files  1 passed (1)
      Tests  9 passed (9)

Real behavior proof

Test vault at /tmp/test-wiki-vault:

  • sources/code-example.md contains bash [[ "$name" == "Alice" ]], Scala Future[Option[User]], and inline code [[ "$str" == "test" ]] inside fenced code blocks / inline code spans.
  • entities/alpha.md contains one genuine prose broken wikilink [[real-link]].

Configuration (/tmp/openclaw-wiki-proof.json) enables memory-wiki and points it at the test vault:

{
  "plugins": {
    "entries": {
      "memory-wiki": {
        "enabled": true,
        "config": {
          "vault": { "path": "/tmp/test-wiki-vault", "renderMode": "obsidian" }
        }
      }
    }
  }
}

Command run on both old (main) and patched (fix/...) builds:

OPENCLAW_CONFIG_PATH=/tmp/openclaw-wiki-proof.json ./node_modules/.bin/openclaw wiki lint --json

Before fix (current main)

{
  "issueCount": 5,
  "issues": [
    { "code": "stale-page", "path": "entities/alpha.md", ... },
    { "code": "broken-wikilink", "path": "entities/alpha.md", "message": "Broken wikilink target `real-link`." },
    { "code": "stale-page", "path": "sources/code-example.md", ... },
    { "code": "broken-wikilink", "path": "sources/code-example.md", "message": "Broken wikilink target `\"$name\" == \"Alice\"`." },
    { "code": "broken-wikilink", "path": "sources/code-example.md", "message": "Broken wikilink target `\"$str\" == \"test\"`." }
  ]
}

Two of the three broken-wikilink warnings are false positives originating from code spans.

After fix (this branch)

{
  "issueCount": 3,
  "issues": [
    { "code": "stale-page", "path": "entities/alpha.md", ... },
    { "code": "broken-wikilink", "path": "entities/alpha.md", "message": "Broken wikilink target `real-link`." },
    { "code": "stale-page", "path": "sources/code-example.md", ... }
  ]
}

The code-span false positives are gone; the genuine prose broken link remains.

Lint/format clean

$ ./node_modules/.bin/oxlint extensions/memory-wiki/src/markdown.ts extensions/memory-wiki/src/lint.test.ts
Found 0 warnings and 0 errors.

$ pnpm format:check extensions/memory-wiki/src/markdown.ts extensions/memory-wiki/src/lint.test.ts
All matched files use the correct format.

Summary

What problem does this PR solve? The wikilink extractor treats Markdown code spans as prose, producing false-positive broken-link warnings.
Why does this matter now? Real vaults are cluttered with spurious warnings, reducing trust in wiki lint.
What is the intended outcome? Only genuine prose wikilinks are evaluated.
What is intentionally out of scope? Title-based resolver matching (Class 2 in #70986) and markdown-link handling are not changed.
What does success look like? The new regression tests fail before the fix and pass after; the CLI no longer reports code-span false positives.
What should reviewers focus on? Correctness of the line-by-line fence scanner, handling of bare fences and unclosed fences, and whether multi-backtick inline code support is worthwhile.

Fix classification: Root-cause fix
Root cause: extractWikiLinks runs OBSIDIAN_LINK_PATTERN over the full Markdown body without excluding code spans.
Why this is root-cause fix: It stops invalid targets from being extracted in the first place, rather than filtering them later.

Linked context

Closes #97945
Related #70986 (reopens the markdown-awareness part only)
Was this requested by a maintainer or owner? No direct maintainer request; follows user-reported issue.

Tests and validation

  • pnpm test extensions/memory-wiki/src/lint.test.ts passes (9/9)
  • ./node_modules/.bin/oxlint extensions/memory-wiki/src/markdown.ts extensions/memory-wiki/src/lint.test.ts reports 0 warnings/errors
  • pnpm format:check extensions/memory-wiki/src/markdown.ts extensions/memory-wiki/src/lint.test.ts passes
  • Negative control verified: the new test fails on the old extractor with 5 false positives
  • CLI behavior proof: openclaw wiki lint --json on a synthetic vault shows code-span false positives eliminated

Risk checklist

Did user-visible behavior change? Yes — openclaw wiki lint now reports fewer false-positive broken wikilinks for code spans.
Did config, environment, or migration behavior change? No.
Did security, auth, secrets, network, or tool execution behavior change? No.
What is the highest-risk area? The fence scanner could mis-handle unusual fence lengths or content that looks like a fence inside a code block. The regression tests cover common cases, bare fences, and inter-block preservation.
How is that risk mitigated? The scanner requires the closing fence to use the same character and be at least as long as the opening fence (CommonMark convention). Unclosed fences are handled conservatively so real links after them are not lost.

Current review state

Ready for ClawSweeper re-review. Next action: @clawsweeper re-review.

The wikilink extractor ran OBSIDIAN_LINK_PATTERN against raw markdown,
so [[...]] inside fenced code blocks and inline code spans were reported
as broken wikilinks. Strip fenced blocks (line-by-line, matching backtick
and tilde fences of any length) and inline code spans before extraction.

Fixes openclaw#97945
@clawsweeper

clawsweeper Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs changes before merge. Reviewed June 29, 2026, 10:45 PM ET / 02:45 UTC.

Summary
This PR masks fenced code blocks and inline code before Memory Wiki wikilink extraction and adds lint regression tests for code-origin broken-link false positives.

PR surface: Source +50, Tests +131. Total +181 across 2 files.

Reproducibility: yes. Current main extracts wikilinks after removing only the related block, and the PR body plus a read-only regex probe show both the original false positives and the new inline-span false negative.

Review metrics: none identified.

Stored data model
Persistent data-model change detected: serialized state: extensions/memory-wiki/src/lint.test.ts, unknown-data-model-change: extensions/memory-wiki/src/lint.test.ts, unknown-data-model-change: extensions/memory-wiki/src/markdown.ts, vector/embedding metadata: extensions/memory-wiki/src/lint.test.ts, vector/embedding metadata: extensions/memory-wiki/src/markdown.ts. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #97945
Summary: This PR is a candidate fix for the active Memory Wiki fenced-code and inline-code wikilink extraction false-positive issue; sibling PRs target the same canonical bug, while older reports also include resolver-side work.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🦪 silver shellfish
Proof: 🦞 diamond lobster
Patch quality: 🦪 silver shellfish
Result: blocked by patch quality or review findings.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P2] Fix inline-code masking so prose links between two inline code spans survive extraction.
  • [P2] Add focused regression coverage for that false-negative case.

Risk before merge

  • [P1] Merging as-is can suppress genuine broken-wikilink diagnostics when prose links sit between two inline code spans.
  • [P1] Several open PRs target the same canonical issue, so maintainers should pick one landing path after the inline masking defect is fixed.

Maintainer options:

  1. Repair inline span masking (recommended)
    Replace the inline-code regex with a scanner or equivalent parser that masks each code span independently and add a regression test for a real wikilink between two spans.
  2. Adopt a sibling fix
    If maintainers prefer another open branch, close or rebase this PR only after that branch proves the same user behavior without the inline-span false negative.
Copy recommended automerge instruction
@clawsweeper automerge

Special instructions:
Fix the Memory Wiki inline-code masking so it strips each inline code span independently, and add regression coverage for a real wikilink between two inline code spans; keep the change scoped to extensions/memory-wiki/src/markdown.ts and colocated Memory Wiki tests.

Next step before merge

  • [P2] A narrow automated repair can replace the faulty inline-code regex with independent span masking and add the missing regression test.

Security
Cleared: No concrete security or supply-chain issue was found; the diff is limited to Memory Wiki markdown parsing and colocated tests.

Review findings

  • [P2] Preserve links between inline code spans — extensions/memory-wiki/src/markdown.ts:117
Review details

Best possible solution:

Keep the fix at the Memory Wiki extraction boundary, but replace the inline-code regex with span-by-span masking and add regression coverage for real wikilinks between inline code spans before choosing a landing branch.

Do we have a high-confidence way to reproduce the issue?

Yes. Current main extracts wikilinks after removing only the related block, and the PR body plus a read-only regex probe show both the original false positives and the new inline-span false negative.

Is this the best way to solve the issue?

No, not as submitted. The Memory Wiki extraction boundary is the right fix location, but the inline-code masking must preserve real prose wikilinks between adjacent inline code spans.

Full review comments:

  • [P2] Preserve links between inline code spans — extensions/memory-wiki/src/markdown.ts:117
    The new regex can match from the first inline-code delimiter through the next inline-code span. For text like `code` [[missing]] `more`, the replacement removes the real wikilink between spans, so broken-wikilink is never emitted; mask each code span independently and cover this case before merge.
    Confidence: 0.93

Overall correctness: patch is incorrect
Overall confidence: 0.91

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 54b09580f61b.

Label changes

Label changes:

  • add merge-risk: 🚨 other: The patch can hide genuine broken-link lint diagnostics for wiki prose placed between inline code spans.
  • add rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦞 diamond lobster and patch quality is 🦪 silver shellfish.
  • add status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (live_output): The PR body includes copied before/after openclaw wiki lint --json output showing code-origin false positives removed while a genuine prose broken link still reports.
  • remove rating: 🐚 platinum hermit: Current PR rating is rating: 🦪 silver shellfish, so this older rating label is no longer current.
  • remove status: 👀 ready for maintainer look: Current PR status label is status: ⏳ waiting on author.

Label justifications:

  • P2: This is a bounded bundled Memory Wiki lint bug with real diagnostic impact but limited plugin blast radius.
  • merge-risk: 🚨 other: The patch can hide genuine broken-link lint diagnostics for wiki prose placed between inline code spans.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦞 diamond lobster and patch quality is 🦪 silver shellfish.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (live_output): The PR body includes copied before/after openclaw wiki lint --json output showing code-origin false positives removed while a genuine prose broken link still reports.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes copied before/after openclaw wiki lint --json output showing code-origin false positives removed while a genuine prose broken link still reports.
Evidence reviewed

PR surface:

Source +50, Tests +131. Total +181 across 2 files.

View PR surface stats
Area Files Added Removed Net
Source 1 51 1 +50
Tests 1 131 0 +131
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 2 182 1 +181

Acceptance criteria:

  • [P1] node scripts/run-vitest.mjs extensions/memory-wiki/src/markdown.test.ts extensions/memory-wiki/src/lint.test.ts.
  • [P1] git diff --check.

What I checked:

  • Repository policy: Root AGENTS.md and extensions/AGENTS.md were read; the bundled-plugin boundary, high-confidence review, proof, and best-fix requirements apply. (AGENTS.md:20, 54b09580f61b)
  • Current main extractor: Current main builds searchable markdown by removing only the managed related block, then runs Obsidian and Markdown link regexes over the remaining body. (extensions/memory-wiki/src/markdown.ts:389, 54b09580f61b)
  • Lint warning path: collectBrokenLinkIssues turns unmatched extracted linkTargets into user-visible broken-wikilink warnings. (extensions/memory-wiki/src/lint.ts:68, 54b09580f61b)
  • Patch inline masking: PR head adds INLINE_CODE_PATTERN and applies it before extraction. (extensions/memory-wiki/src/markdown.ts:117, eb71b9fcdaff)
  • False-negative probe: A read-only Node probe using the PR regex turned 'code [[missing-between-code-spans]] more and [[missing-after-code]]' into only '[[missing-after-code]]', proving the real link between inline spans is dropped. (extensions/memory-wiki/src/markdown.ts:117, eb71b9fcdaff)
  • Contributor proof: The PR body includes copied before/after openclaw wiki lint --json output showing code-origin false positives removed while a genuine prose broken link remains. (eb71b9fcdaff)

Likely related people:

  • vincentkoc: Git history shows Vincent Koc introduced the Memory Wiki ingest/compile/lint pipeline and later expanded adjacent lint behavior on the same files. (role: feature introducer and area contributor; confidence: high; commits: 516a43f9f28c, 9ce4abfe558e, 44fd8b0d6e38; files: extensions/memory-wiki/src/markdown.ts, extensions/memory-wiki/src/lint.ts, extensions/memory-wiki/src/lint.test.ts)
  • steipete: Git history shows Peter Steinberger made nearby Memory Wiki helper and test refactors on the affected markdown and lint surfaces. (role: recent adjacent area contributor; confidence: medium; commits: dffa88f39615, d0e53a35295a, 59eb291c6e1c; files: extensions/memory-wiki/src/markdown.ts, extensions/memory-wiki/src/lint.ts, extensions/memory-wiki/src/lint.test.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. labels Jun 30, 2026
The wikilink extractor ran OBSIDIAN_LINK_PATTERN against raw markdown,
so [[...]] inside fenced code blocks and inline code spans were reported
as broken wikilinks. Strip fenced blocks (line-by-line, matching backtick
and tilde fences of any length, including bare fences) and inline code
spans before extraction.

Fixes openclaw#97945
@hanZeng-08

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jun 30, 2026
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Jun 30, 2026
@hanZeng-08

Copy link
Copy Markdown
Contributor Author

Hi @steipete @vincentkoc, ClawSweeper re-reviewed and marked this PR as the canonical landing path for #97945; the competing PR #97987 was closed as superseded. Could you please approve the pending workflows and review when convenient? Thanks!

@vincentkoc

Copy link
Copy Markdown
Member

Thanks for working this through. I’m closing this because the #97945 memory-wiki wikilink false-positive issue has already been fixed on main by the canonical PR #97954, merged as c896718.

This branch now overlaps that landed implementation, so keeping it open would just create duplicate cleanup churn. If there is still a distinct markdown edge case not covered by main, please reopen it as a focused follow-up against current main.

@vincentkoc vincentkoc closed this Jul 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

extensions: memory-wiki merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. size: S status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

memory-wiki lint: wikilink extractor still not markdown-aware — fenced code false positives (reopening #70986)

2 participants