feat(wiki): expose auto-fix in UI + Reset Log + handle orphan_page#1123
Open
toy0116 wants to merge 1 commit into
Open
feat(wiki): expose auto-fix in UI + Reset Log + handle orphan_page#1123toy0116 wants to merge 1 commit into
toy0116 wants to merge 1 commit into
Conversation
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes five separate operator workflow gaps in wiki maintenance, all of which forced manual SQL or manual
curlworkarounds.1. Frontend never wired up a control for
/wiki/auto-fixThe 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-fixand toasts the fixed-issue count. Refreshes stats / pages / graph on success. Reuses the existingDialogPlugin/MessagePluginpattern.(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-fixskippedorphan_pageissuesThe lint rule reported orphan pages (no inbound links) but unconditionally set
AutoFixable=false, and theAutoFixswitch had noorphan_pagecase. So even when the UI calls/auto-fix, genuinely abandoned pages survived.Splits the
orphan_pagelint rule into two flavors based onsource_refs:in_links empty AND source_refs empty: genuinely abandoned — no document backing AND no inbound reference. MarkAutoFixable=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. KeepAutoFixable=false(warning only).Adds
case LintIssueOrphanPagetoAutoFix. Defensively re-checks bothlen(InLinks) == 0 && len(SourceRefs) == 0since concurrent wiki ingest can add either between lint and fix passes. Skips index/log pages.3. Index page stayed stale after fixes
AutoFixcalled onlyRebuildLinks, 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
RebuildIndexPageafter a successful fix (fixed > 0), so the Index directory page reflects the new state immediately.4. Sidebar still showed archived pages
loadPagesin the wiki browser calledlistWikiPageswith nostatusparameter; 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/resetclears 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, styledtheme=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"}.
Pull Request
描述 (Description)
变更类型 (Type of Change)
影响范围 (Scope)
测试 (Testing)
测试步骤 (Test Steps)
检查清单 (Checklist)
相关 Issue
Fixes #
截图/录屏 (Screenshots/Recordings)
数据库迁移 (Database Migration)
配置变更 (Configuration Changes)
部署说明 (Deployment Notes)
其他信息 (Additional Information)