Skip to content

feat(wiki): expose auto-fix in UI + Reset Log + handle orphan_page#1123

Open
toy0116 wants to merge 1 commit into
Tencent:mainfrom
toy0116:pr/wiki-auto-fix-button
Open

feat(wiki): expose auto-fix in UI + Reset Log + handle orphan_page#1123
toy0116 wants to merge 1 commit into
Tencent:mainfrom
toy0116:pr/wiki-auto-fix-button

Conversation

@toy0116
Copy link
Copy Markdown
Contributor

@toy0116 toy0116 commented May 3, 2026

Closes five separate operator workflow gaps in wiki maintenance, all of which forced manual SQL or manual curl workarounds.

1. Frontend never wired up a control for /wiki/auto-fix

The endpoint was already implemented; only operators with bearer tokens could reach it.

Adds a "Tidy" button in the wiki sidebar header (next to the search input). On click, shows a confirmation dialog explaining what tidy will do, then POSTs to /wiki/auto-fix and toasts the fixed-issue count. Refreshes stats / pages / graph on success. Reuses the existing DialogPlugin / MessagePlugin pattern.

(Initial label was "Structural Fix" / "结构修复"; renamed to "Tidy" / "整理" because the action is closer to garbage collection — archive orphans, strip stale refs, repair broken links — rather than content fixing. Friendlier label, less likely to scare operators.)

2. auto-fix skipped orphan_page issues

The lint rule reported orphan pages (no inbound links) but unconditionally set AutoFixable=false, and the AutoFix switch had no orphan_page case. So even when the UI calls /auto-fix, genuinely abandoned pages survived.

Splits the orphan_page lint rule into two flavors based on source_refs:

  • in_links empty AND source_refs empty: genuinely abandoned — no document backing AND no inbound reference. Mark AutoFixable=true. Description: "abandoned, safe to archive".

  • in_links empty BUT source_refs non-empty: may be a brand-new entity awaiting cross-linking from sibling pages in this batch — auto-archiving would race against wiki ingest. Keep AutoFixable=false (warning only).

Adds case LintIssueOrphanPage to AutoFix. Defensively re-checks both len(InLinks) == 0 && len(SourceRefs) == 0 since concurrent wiki ingest can add either between lint and fix passes. Skips index/log pages.

3. Index page stayed stale after fixes

AutoFix called only RebuildLinks, which refreshes inbound/ outbound link metadata but never re-generates the Index page directory. Right after archiving an orphan, operators saw the Index still listing it.

Calls RebuildIndexPage after a successful fix (fixed > 0), so the Index directory page reflects the new state immediately.

4. Sidebar still showed archived pages

loadPages in the wiki browser called listWikiPages with no status parameter; the repository's filter only applies when the parameter is non-empty, so archived pages were included by default. Operators archive a page (intentionally hide-but-retain) and it still showed up everywhere.

Pass status: 'published' in the default sidebar query.

5. No way to reset the Wiki Operation Log

The log page (page_type=log) is intentionally append-only — a chronological record of every ingest/retract/dedup decision, useful for audit. But operators doing a KB-level reset (delete all docs, re-upload from clean state) typically also want a clean log. The only path was manual SQL.

New backend endpoint POST /wiki/log/reset clears the log content back to its empty template (preserving the page row, which is a global page like index). Frontend adds a second "Reset Log" button next to "Tidy" in the sidebar toolbar, styled theme=warning, with a strong-warning confirmation dialog noting irreversibility.

i18n

All new keys added across zh-CN, en-US, ko-KR, ru-RU: structuralFix (renamed contents), structuralFixTooltip, structuralFixConfirmTitle, structuralFixConfirmBody, structuralFixDone, structuralFixNothing, structuralFixFailed, resetLog, resetLogTooltip, resetLogConfirmTitle, resetLogConfirmBody, resetLogConfirm, resetLogDone, resetLogFailed.

Reproduce / verify

Before:
SQL-plant a wiki page with source_refs=[] and in_links=[]
POST /wiki/auto-fix → response: {"fixed": 0}
Page survives indefinitely; only manual SQL or DELETE removes
it. Index page keeps listing entries from already-deleted
documents. Sidebar shows everything including archived pages.
No way to reset the Wiki Operation Log without SQL.

After:
Same setup
Click "Tidy" in UI → confirmation → confirm → toast: "Tidied 1
item" → page disappears from sidebar → Index page regenerates
without the archived/deleted entries.
OR: POST /wiki/auto-fix → response: {"fixed": 1, "message":
"Auto-fixed 1 issues"}.

Click "Reset Log" → confirmation → confirm → toast "Wiki log
reset" → log page shows empty template.

Pull Request

描述 (Description)

变更类型 (Type of Change)

  • 🐛 Bug 修复 (Bug fix)
  • ✨ 新功能 (New feature)
  • 💥 破坏性变更 (Breaking change)
  • 📚 文档更新 (Documentation update)
  • 🎨 代码重构 (Code refactoring)
  • ⚡ 性能优化 (Performance improvement)
  • 🧪 测试相关 (Test related)
  • 🔧 配置变更 (Configuration change)
  • 🐳 Docker 相关 (Docker related)
  • 🎨 前端 UI/UX (Frontend UI/UX)

影响范围 (Scope)

  • 后端 API (Backend API)
  • 前端界面 (Frontend UI)
  • 数据库 (Database)
  • 文档解析服务 (Document Reader Service)
  • MCP 服务器 (MCP Server)
  • Docker 配置 (Docker Configuration)
  • 配置文件 (Configuration)
  • 其他 (Other):

测试 (Testing)

  • 单元测试 (Unit tests)
  • 集成测试 (Integration tests)
  • 手动测试 (Manual testing)
  • 前端测试 (Frontend testing)
  • API 测试 (API testing)

测试步骤 (Test Steps)

检查清单 (Checklist)

  • 代码遵循项目的编码规范
  • 已进行自我代码审查
  • 代码变更已添加适当的注释
  • 相关文档已更新
  • 变更不会产生新的警告
  • 已添加测试用例证明修复有效或功能正常
  • 新功能和变更已更新到相关文档
  • 破坏性变更已在描述中明确说明

相关 Issue

Fixes #

截图/录屏 (Screenshots/Recordings)

数据库迁移 (Database Migration)

  • 需要数据库迁移
  • 不需要数据库迁移

配置变更 (Configuration Changes)

部署说明 (Deployment Notes)

其他信息 (Additional Information)

Closes five separate operator workflow gaps in wiki maintenance, all
of which forced manual SQL or manual `curl` workarounds.

## 1. Frontend never wired up a control for `/wiki/auto-fix`

The endpoint was already implemented; only operators with bearer
tokens could reach it.

Adds a "Tidy" button in the wiki sidebar header (next to the search
input). On click, shows a confirmation dialog explaining what tidy
will do, then `POST`s to `/wiki/auto-fix` and toasts the fixed-issue
count. Refreshes stats / pages / graph on success. Reuses the
existing `DialogPlugin` / `MessagePlugin` pattern.

(Initial label was "Structural Fix" / "结构修复"; renamed to "Tidy"
/ "整理" because the action is closer to garbage collection — archive
orphans, strip stale refs, repair broken links — rather than
content fixing. Friendlier label, less likely to scare operators.)

## 2. `auto-fix` skipped `orphan_page` issues

The lint rule reported orphan pages (no inbound links) but
unconditionally set `AutoFixable=false`, and the `AutoFix` switch
had no `orphan_page` case. So even when the UI calls `/auto-fix`,
genuinely abandoned pages survived.

Splits the `orphan_page` lint rule into two flavors based on
`source_refs`:

  - `in_links empty AND source_refs empty`:
      genuinely abandoned — no document backing AND no inbound
      reference. Mark `AutoFixable=true`. Description: "abandoned,
      safe to archive".

  - `in_links empty BUT source_refs non-empty`:
      may be a brand-new entity awaiting cross-linking from sibling
      pages in this batch — auto-archiving would race against wiki
      ingest. Keep `AutoFixable=false` (warning only).

Adds `case LintIssueOrphanPage` to `AutoFix`. Defensively re-checks
both `len(InLinks) == 0 && len(SourceRefs) == 0` since concurrent
wiki ingest can add either between lint and fix passes. Skips
index/log pages.

## 3. Index page stayed stale after fixes

`AutoFix` called only `RebuildLinks`, which refreshes inbound/
outbound link metadata but never re-generates the Index page
directory. Right after archiving an orphan, operators saw the Index
still listing it.

Calls `RebuildIndexPage` after a successful fix (`fixed > 0`), so
the Index directory page reflects the new state immediately.

## 4. Sidebar still showed archived pages

`loadPages` in the wiki browser called `listWikiPages` with no
`status` parameter; the repository's filter only applies when the
parameter is non-empty, so archived pages were included by default.
Operators archive a page (intentionally hide-but-retain) and it
still showed up everywhere.

Pass `status: 'published'` in the default sidebar query.

## 5. No way to reset the Wiki Operation Log

The log page (`page_type=log`) is intentionally append-only — a
chronological record of every ingest/retract/dedup decision, useful
for audit. But operators doing a KB-level reset (delete all docs,
re-upload from clean state) typically also want a clean log. The
only path was manual SQL.

New backend endpoint `POST /wiki/log/reset` clears the log content
back to its empty template (preserving the page row, which is a
global page like index). Frontend adds a second "Reset Log" button
next to "Tidy" in the sidebar toolbar, styled `theme=warning`,
with a strong-warning confirmation dialog noting irreversibility.

## i18n

All new keys added across `zh-CN`, `en-US`, `ko-KR`, `ru-RU`:
`structuralFix` (renamed contents), `structuralFixTooltip`,
`structuralFixConfirmTitle`, `structuralFixConfirmBody`,
`structuralFixDone`, `structuralFixNothing`, `structuralFixFailed`,
`resetLog`, `resetLogTooltip`, `resetLogConfirmTitle`,
`resetLogConfirmBody`, `resetLogConfirm`, `resetLogDone`,
`resetLogFailed`.

## Reproduce / verify

  Before:
    SQL-plant a wiki page with source_refs=[] and in_links=[]
    POST /wiki/auto-fix → response: {"fixed": 0}
    Page survives indefinitely; only manual SQL or DELETE removes
    it. Index page keeps listing entries from already-deleted
    documents. Sidebar shows everything including archived pages.
    No way to reset the Wiki Operation Log without SQL.

  After:
    Same setup
    Click "Tidy" in UI → confirmation → confirm → toast: "Tidied 1
    item" → page disappears from sidebar → Index page regenerates
    without the archived/deleted entries.
    OR: POST /wiki/auto-fix → response: {"fixed": 1, "message":
    "Auto-fixed 1 issues"}.

    Click "Reset Log" → confirmation → confirm → toast "Wiki log
    reset" → log page shows empty template.
Sign up for free to 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.

1 participant