diff --git a/CHANGELOG.md b/CHANGELOG.md index bee3256740a..23178bcd48d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ Docs: https://docs.openclaw.ai ### Fixes +- Memory Wiki: accept relative Markdown links that include the `.md` suffix during broken-wikilink validation, avoiding false positives for native render-mode links. Thanks @Kenneth8128. - Plugins/CLI: cache plugin CLI registration entries per command program so completion state generation does not repeat the full plugin sweep in one invocation. Thanks @ScientificProgrammer. - Plugins: reuse gateway-bindable plugin loader cache entries for later default-mode loads without serving default-built registries to gateway-bound requests, reducing repeated plugin registration during dispatch. Refs #61756. Thanks @DmitryPogodaev. - Gateway/secrets: include the caught error message in `secrets.reload` and `secrets.resolve` warning logs while keeping RPC errors generic, so operators can diagnose reload and permission failures. Thanks @davidangularme. diff --git a/extensions/memory-wiki/src/lint.test.ts b/extensions/memory-wiki/src/lint.test.ts index 6ab2aad31ca..35d1f5c9602 100644 --- a/extensions/memory-wiki/src/lint.test.ts +++ b/extensions/memory-wiki/src/lint.test.ts @@ -8,6 +8,48 @@ import { createMemoryWikiTestHarness } from "./test-helpers.js"; const { createVault } = createMemoryWikiTestHarness(); describe("lintMemoryWikiVault", () => { + it("accepts native markdown links that include the relative .md target", async () => { + const { rootDir, config } = await createVault({ + prefix: "memory-wiki-lint-native-links-", + config: { + vault: { renderMode: "native" }, + }, + }); + await Promise.all( + ["entities", "sources"].map((dir) => fs.mkdir(path.join(rootDir, dir), { recursive: true })), + ); + + await fs.writeFile( + path.join(rootDir, "sources", "alpha.md"), + renderWikiMarkdown({ + frontmatter: { + pageType: "source", + id: "source.alpha", + title: "Alpha Source", + }, + body: "# Alpha Source\n", + }), + "utf8", + ); + await fs.writeFile( + path.join(rootDir, "entities", "alpha.md"), + renderWikiMarkdown({ + frontmatter: { + pageType: "entity", + id: "entity.alpha", + title: "Alpha", + sourceIds: ["source.alpha"], + }, + body: "# Alpha\n\n[Alpha Source](sources/alpha.md)\n", + }), + "utf8", + ); + + const result = await lintMemoryWikiVault(config); + + expect(result.issues.filter((issue) => issue.code === "broken-wikilink")).toEqual([]); + }); + it("detects duplicate ids, provenance gaps, contradictions, and open questions", async () => { const { rootDir, config } = await createVault({ prefix: "memory-wiki-lint-", diff --git a/extensions/memory-wiki/src/lint.ts b/extensions/memory-wiki/src/lint.ts index 263d7285923..2361362000c 100644 --- a/extensions/memory-wiki/src/lint.ts +++ b/extensions/memory-wiki/src/lint.ts @@ -54,6 +54,7 @@ function collectBrokenLinkIssues(pages: WikiPageSummary[]): MemoryWikiLintIssue[ const validTargets = new Set(); for (const page of pages) { const withoutExtension = page.relativePath.replace(/\.md$/i, ""); + validTargets.add(page.relativePath); validTargets.add(withoutExtension); validTargets.add(path.basename(withoutExtension)); }