GA-P0-7 (t_dd64345a): 退役裸路由 /api/v1/feedback 写点(曾写旧 not_useful_count)

- server.go: 删 mux.HandleFunc("/api/v1/feedback", api.Feedback) 注册
- core.go: 删 Feedback handler(按 useful 写 useful_count/not_useful_count)
- 回归守卫 server_route_guard_test.go: 断言裸路由不注册 + 4 子路由在
- tests/integration_test.sh: 反馈改走 /api/v1/feedback/useful
- README.md: 裸路由文档改为拆分后 4 子路由

AC2 证伪无调用方:grep 'api/v1/feedback"' 仅命中自身注册行(现已删)。
AC3 退废后 not_useful_count 仅剩 schema/struct 向后兼容声明、[DEPRECATED] IncrementNotUseful(无路由调用)、迁移工具读、注释。
This commit is contained in:
小唯
2026-10-12 21:38:01 +08:00
parent 66d8e32bc6
commit e900e4073f
5 changed files with 48 additions and 33 deletions
+4 -1
View File
@@ -426,7 +426,10 @@ python3 -c "from plugins.memory.zhiyi import HermesZhiYiMemoryProvider; \
| POST | `/api/v1/recall` | 语义检索(支持 mode=hybrid\|keyword\|semantic) |
| POST | `/api/v1/batch-commit` | 批量提交 |
| GET | `/api/v1/memories` | 列出记忆(分页) |
| POST | `/api/v1/feedback` | 反馈(useful / not-useful / deprecate) |
| POST | `/api/v1/feedback/useful` | 标记记忆有用(GA-P0-1 写 human_useful) |
| POST | `/api/v1/feedback/not-useful` | 标记记忆无用(写 human_not_useful_count) |
| POST | `/api/v1/feedback/deprecate` | 标记过时 |
| POST | `/api/v1/feedback/correct` | 提交修正 |
### 统计
+3 -28
View File
@@ -558,34 +558,9 @@ func (a *API) Recall(w http.ResponseWriter, r *http.Request) {
}
}
// POST /api/v1/feedback — 用户反馈记忆是否有用,同时更新 useful_count/not_useful_count
func (a *API) Feedback(w http.ResponseWriter, r *http.Request) {
var req struct {
MemoryID string `json:"memory_id"`
Useful bool `json:"useful"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
respondError(w, 400, "invalid body")
return
}
if req.MemoryID == "" {
respondError(w, 400, "memory_id required")
return
}
field := "useful_count"
val := map[string]interface{}{"$inc": 1}
if !req.Useful {
field = "not_useful_count"
}
err := a.LanceDB.Update("memories", req.MemoryID, map[string]any{
field: val,
})
if err != nil {
respondError(w, 500, "feedback update failed: "+err.Error())
return
}
respond(w, 200, map[string]string{"status": "ok"})
}
// GA-P0-7 (t_dd64345a):裸 POST /api/v1/feedback handler 已删除——它按 useful 布尔写
// useful_count / not_useful_count(后者是 P0-1 拆分的旧混写列)。反馈统一走
// feedback.go 的 /api/v1/feedback/{useful,not-useful,deprecate,correct}(写 human_not_useful_count)。
// POST /api/v1/recall/debug — recall 诊断端点(优化),返回各阶段耗时和状态
func (a *API) RecallDebug(w http.ResponseWriter, r *http.Request) {
+2 -1
View File
@@ -382,7 +382,8 @@ func NewServer() http.Handler {
})
mux.HandleFunc("/api/v1/recall", api.Recall)
mux.HandleFunc("/api/v1/recall/debug", api.RecallDebug)
mux.HandleFunc("/api/v1/feedback", api.Feedback)
// GA-P0-7 (t_dd64345a):裸 /api/v1/feedback 已退役——其 handler 曾写旧字段 not_useful_count。
// 反馈统一走 /api/v1/feedback/{useful,not-useful,deprecate,correct}(feedback.go,写拆分后新字段)。
mux.HandleFunc("/api/v1/bootstrap", api.Bootstrap)
mux.HandleFunc("/api/v1/stats", api.Stats)
mux.HandleFunc("/api/v1/batch-commit", api.BatchCommit)
@@ -0,0 +1,37 @@
package api
import (
"os"
"strings"
"testing"
)
// GA-P0-7 (t_dd64345a):回归守卫 —— 裸路由 /api/v1/feedback 已退役。
// 它的 handler(core.go Feedback,已删)曾按 useful 布尔写旧字段 not_useful_count
// (P0-1 t_718d8707 已拆分为 human_not_useful_count / dedup_downweight_count)。
// 谁若重新注册这个裸路由(旧字段随之复活),本测试必须红。
func TestNoBareFeedbackRoute(t *testing.T) {
src, err := os.ReadFile("server.go")
if err != nil {
t.Fatalf("read server.go: %v", err)
}
s := string(src)
// 裸路由注册必须不存在(精确匹配 server.go:385 的旧行)。
bare := `mux.HandleFunc("/api/v1/feedback", api.Feedback)`
if strings.Contains(s, bare) {
t.Fatalf("裸 /api/v1/feedback 路由被重新注册——其 handler 写旧字段 not_useful_count(GA-P0-1);请改用 /api/v1/feedback/{useful,not-useful,deprecate,correct}")
}
// 新拆分后的子路由必须在(反馈统一走它们,写 human_not_useful_count 等新字段)。
for _, sub := range []string{
`"/api/v1/feedback/useful"`,
`"/api/v1/feedback/not-useful"`,
`"/api/v1/feedback/deprecate"`,
`"/api/v1/feedback/correct"`,
} {
if !strings.Contains(s, sub) {
t.Fatalf("期望子路由 %s 已注册,但 server.go 中缺失", sub)
}
}
}
+2 -3
View File
@@ -221,9 +221,8 @@ test_commit_recall_feedback() {
if [[ -n "$memory_id" ]]; then
log_info "步骤3: 反馈 (feedback)"
local feedback_resp
feedback_resp=$(api_post "/api/v1/feedback" "{
\"memory_id\": \"${memory_id}\",
\"useful\": true
feedback_resp=$(api_post "/api/v1/feedback/useful" "{
\"memory_id\": \"${memory_id}\"
}")
log_info "feedback 响应: $feedback_resp"