fix: staticcheck 24 条存量全部清零(含 4 个真实缺陷)

staticcheck 门接入时把存量设为基线 24 条,本次全部清掉,基线改为 0。

## 生产代码里的真实缺陷(4 个)

### ① memory/fusion.go —— BFS 的 depth 参数形同虚设

    for d := 1; d <= depth; d++ {
        neighbors, _ := g.NeighbourBlocks(seed.BlockID)   // ← 永远是 seed
        ...
        break                                             // ← 只跑一轮
    }

三处叠加:循环体末尾无条件 `break`;每层传的还是 `seed.BlockID`;
于是 depth=2 与 depth=3 召回结果**完全一样**。

staticcheck SA4008("变量在循环条件里从不改变")正是从这里报出来的 ——
它看出来 `d` 除了打分没有参与寻址。

改成真正的逐层 BFS(frontier 推进到上一层新发现的节点)。实测:

    depth=1 → 2 个  [节点0 节点1]
    depth=2 → 3 个  [节点0 节点1 节点2]      ← 修复前停在这里
    depth=3 → 4 个  [节点0 节点1 节点2 节点3]

补判据 `TestBFS召回_层深真实生效`:必须用**链**(n0-n1-n2-n3),
星型在 depth=1 就能召回全部叶子、断不出有没有走深。
变异(改回单层)⇒ 实测红:`★ depth=2 召回 2 个,期望 3`。

### ② nlp/extractor.go —— subjRels/objRels 只写不读

两个切片被 append 了 4 处,但**从未被读取**。三元组的关系类型来自
`relLabel := result.Tokens[vi]`,置信度来自 `result.DepRels[si]`,
与这两个切片无关。删除。

### ③ plugins/cmd/plugin.go —— 配置解析失败会把上限写成 0

    if n, err := fmt.Sscanf(s, "%d", &p.maxOutput); err == nil && n > 0 {
    }   // ← 空分支

直接 Sscanf 到 &p.maxOutput:解析失败时它可能已被写成 0 或部分值,
而空分支无法回滚 ⇒ 配置写错一个字符就把输出上限变成 0
(下游 `maxLen := p.maxOutput` 直接拿它算截断长度)。
改为解析到临时变量、失败时保持默认并记日志。

### ④ cmd/homed/bootstrap.go —— 空的 else 分支

`if err != nil { log } else { }` —— 删掉 else。

## 测试判据里的真实缺陷(3 个)

### ⑤ stop_semantics_test —— 短路求值让第二次调用从不执行

    if !a.sched.consumeCancel() || !a.sched.consumeCancel()

第一次返回 true 时第二次**根本不会执行**,于是"两条配额都可消费"
这条断言实际只测了一次。拆成两次独立调用(两处同型)。

### ⑥ seq/store_test —— 永假断言

    if maxCallDepth != maxCallDepth { t.Fatal("maxCallDepth 不稳定") }

自己跟自己比,从诞生起就不可能失败。改成显式读两次比较。

### ⑦ pluginhost/catalog_test —— typed-nil 守卫永假

    var nb *kstate.SyncBus
    var iface kstate.SyncState = nb
    if iface == nil { t.Skip(...) }        // ← 恒 false

把 typed-nil 装进接口后,接口的 (type, value) 二元组都不为 nil。
这道前置守卫**从未生效** —— 而这正是该判据要演示的陷阱本身。
改用 `reflect.ValueOf(iface).IsNil()`。

## 其余(写法/冗余,无行为变化)

  agent.go / context.go / toolresult_store_test / apply_regression_test
    空 if 块(注释移到真实分支上方)

  codec_chunkfast_golden_test   未使用的三个返回值 + 空 if
  scheduler_critical/stack_test  `if _, _ = f(); true { }` → 直接调用
  overflow_test / upgrade_test   变量被整体覆盖,首次赋值未使用
  dense_test                     m[string(x)] 替代临时变量
  lex_rules_test                 range over string 而非 []rune(string)

## 验证

    staticcheck -checks 'SA4*,SA5*,SA6*,SA9*'   0 条(基线 24 → 0)
    go build ./...                              PASS
    go vet ./...                                PASS
    gofmt -l                                    干净
    go test ./... -count=1                      65 包全过,0 FAIL
    干净检出(worktree)                         build + memory/nlp/core 全绿
This commit is contained in:
JianFeeeee
2026-11-04 19:49:21 +08:00
parent 77e38360a8
commit 892247946a
20 changed files with 191 additions and 78 deletions

View File

@ -179,9 +179,8 @@ func splitDimFromVal(seg string) (dim, val string) {
// 纯数字、百分比、版本、时长、日期、比率。
func valueHints(seg string) []string {
var hints []string
r := []rune(seg)
hasDigit := false
for _, c := range r {
for _, c := range seg {
if c >= '0' && c <= '9' {
hasDigit = true
break

View File

@ -648,31 +648,50 @@ func (g *GraphDB) RecallBlocksFusedBFS(q BlockRecallQuery, query string, depth i
if appended >= bfsExpansionBudget {
break
}
// ★ 真正逐层 BFS(2026-11-04 修)。
//
// 原实现是 `for d := 1; d <= depth; d++ { ...; break }` ——
// 循环体末尾无条件 break,所以 d 循环**只执行一次**;而且
// NeighbourBlocks 始终传 `seed.BlockID`,每层取的都是同一批直接邻居。
//
// 后果两层:
// ① depth 参数形同虚设,永远不会走到第 2 层
// ② staticcheck SA4008「循环变量在条件里从不改变」—— 这正是它的价值:
// 它看出来了 `d` 除了打分没有参与寻址
//
// 现在 frontier 逐层推进:第 d 层从第 d-1 层新发现的节点继续。
frontier := []MemoryBlock{{ID: seed.BlockID, Text: seed.Text}}
for d := 1; d <= depth; d++ {
neighbors, err := g.NeighbourBlocks(seed.BlockID)
if err != nil {
// 联想失败不该让整次召回失败 —— 主路结果仍然有用。
break
}
for _, nb := range neighbors {
if seen[nb.ID] {
continue
var next []MemoryBlock
for _, cur := range frontier {
neighbors, err := g.NeighbourBlocks(cur.ID)
if err != nil {
// 联想失败不该让整次召回失败 —— 主路结果仍然有用。
break
}
seen[nb.ID] = true
if appended >= bfsExpansionBudget {
return hits, arb, nil
for _, nb := range neighbors {
if seen[nb.ID] {
continue
}
seen[nb.ID] = true
if appended >= bfsExpansionBudget {
return hits, arb, nil
}
hits = append(hits, FusedHit{
BlockID: nb.ID,
Text: nb.Text,
Score: base / float64(1+d),
Why: []string{"联想:" + cur.Text + " → " + nb.Text +
fmt.Sprintf("(%d 层)", d)},
})
appended++
next = append(next, nb)
}
hits = append(hits, FusedHit{
BlockID: nb.ID,
Text: nb.Text,
Score: base / float64(1+d),
Why: []string{"联想:" + seed.Text + " → " + nb.Text +
fmt.Sprintf("(%d 层)", d)},
})
appended++
}
// 只展开一层 —— 下一轮 d 由新追加的节点继续。
break
if len(next) == 0 {
break // 该层无新节点 ⇒ 再深也没有
}
frontier = next
}
}
return hits, arb, nil

View File

@ -247,3 +247,73 @@ func TestSymbolScore_目标词能匹配到对应块(t *testing.T) {
}
}
}
// TestBFS召回_层深真实生效 钉住 depth 参数真的有语义。
//
// ## 守的是什么(2026-11-04 修的实测缺陷)
//
// 原实现:
//
// for d := 1; d <= depth; d++ {
// neighbors, _ := g.NeighbourBlocks(seed.BlockID) // ← 永远是 seed
// ...
// break // ← 只跑一轮
// }
//
// 三个问题叠在一起:
//
// ① 循环体末尾无条件 break ⇒ d 循环只执行一次
// ② NeighbourBlocks 每层传的还是 seed.BlockID ⇒ 第 2 层取的是同一批邻居
// ③ 于是 depth 参数**形同虚设**:传 2 和传 3 召回结果完全一样
//
// staticcheck 的 SA4008("variable in loop condition never changes")
// 正是从这里报出来的 —— 它看出来 `d` 除了打分没有参与寻址。
//
// ## 判据为什么必须是"链"而不是"星型"
//
// 星型(一个中心连 N 个叶子)在 depth=1 就能召回全部叶子,第 2 层没有新节点
// ⇒ 断不出"有没有真的走深"。必须是链:n0-n1-n2-n3,depth=d 恰好召回 d+1 个。
func TestBFS召回_层深真实生效(t *testing.T) {
g := newTestGraph(t)
defer func() { _ = g.Close() }()
// 造一条 4 节点链:n0 → n1 → n2 → n3
for i := 0; i < 4; i++ {
id := fmt.Sprintf("n%d", i)
if err := g.PutMemoryBlocks([]MemoryBlock{{
ID: id, Modality: BlockText, Text: fmt.Sprintf("链节点%d", i),
Vector: []float64{1, 0}, Fingerprint: "fp1",
}}); err != nil {
t.Fatal(err)
}
if i > 0 {
if err := g.AddRelationBlockEdge(fmt.Sprintf("n%d", i-1), id, "next",
RelationEdgeData{SessionID: "s", Status: EdgeActive}); err != nil {
t.Fatal(err)
}
}
}
q := BlockRecallQuery{Vector: []float64{1, 0}, TopK: 1, MinScore: -1}
got := map[int]int{}
for _, d := range []int{1, 2, 3} {
hits, _, err := g.RecallBlocksFusedBFS(q, "链节点0", d)
if err != nil {
t.Fatalf("depth=%d: %v", d, err)
}
got[d] = len(hits)
}
// depth=d 应召回命中(1) + d 层邻居 = d+1 个。
for _, d := range []int{1, 2, 3} {
if got[d] != d+1 {
t.Fatalf("★ depth=%d 召回 %d 个,期望 %d ——\n"+
"说明 BFS 没有真的逐层推进(depth 参数形同虚设)。\n"+
"实测各层: %v", d, got[d], d+1, got)
}
}
// 交叉验证:不同 depth 必须给出**不同**结果,否则参数无意义。
if got[1] == got[3] {
t.Fatalf("★ depth=1 与 depth=3 召回数相同(%d)—— depth 没生效", got[1])
}
}