From a7fbbfd6f974631eadebc6effca8ce7982592786 Mon Sep 17 00:00:00 2001
From: ax_rd <ax_rd@aisim.cn>
Date: Thu, 03 Sep 2026 12:51:40 +0800
Subject: [PATCH] fix: explore 段落命中两级回退(原词→展开词)+ expandKeywords 去重 + HardBudget 接入

---
 internal/index/sqlite.go |   31 ++++++++++++++++++++++++++++++-
 1 files changed, 30 insertions(+), 1 deletions(-)

diff --git a/internal/index/sqlite.go b/internal/index/sqlite.go
index 06a02b3..77cbb56 100644
--- a/internal/index/sqlite.go
+++ b/internal/index/sqlite.go
@@ -93,7 +93,7 @@
 
 // ClearData 清空数据(重建前调用)
 func (s *Store) ClearData() error {
-	_, err := s.db.Exec("DELETE FROM edges; DELETE FROM nodes;")
+	_, err := s.db.Exec("DELETE FROM edges; DELETE FROM nodes; DELETE FROM unresolved_links;")
 	return err
 }
 
@@ -126,6 +126,17 @@
 	return err
 }
 
+// InsertUnresolved 悬空链接入表(幂等:同 from_node+link_text 不重复插)
+func (s *Store) InsertUnresolved(fromNode int64, linkText, nameTail string) error {
+	_, err := s.db.Exec(`
+		INSERT INTO unresolved_links (from_node, link_text, name_tail, status)
+		SELECT ?, ?, ?, 'pending'
+		WHERE NOT EXISTS (
+			SELECT 1 FROM unresolved_links WHERE from_node = ? AND link_text = ?)`,
+		fromNode, linkText, nameTail, fromNode, linkText)
+	return err
+}
+
 // FileStat 索引中的文件指纹
 type FileStat struct {
 	Path        string
@@ -276,6 +287,24 @@
 	return links, nil
 }
 
+// GetUnresolvedLinks 某文档的悬空链接文本列表
+func (s *Store) GetUnresolvedLinks(path string) ([]string, error) {
+	rows, err := s.db.Query(`
+		SELECT u.link_text FROM unresolved_links u
+		JOIN nodes n ON n.id = u.from_node WHERE n.path = ?`, path)
+	if err != nil {
+		return nil, err
+	}
+	defer rows.Close()
+	var links []string
+	for rows.Next() {
+		var l string
+		rows.Scan(&l)
+		links = append(links, l)
+	}
+	return links, rows.Err()
+}
+
 // NodeInfo 节点基本信息(用于 GC)
 type NodeInfo struct {
 	ID   int64

--
Gitblit v1.10.0