Skip to content

[business-logic] hasMakeTarget does not exclude := variable assignments despite comment claiming it — test:=foo creates phantom make target -> false verification failure #941

Description

@topcheer

Bug(独立复核确认,严重程度:低)

internal/agent/verify_hint.go:330-345hasMakeTarget 的注释声明排除变量赋值:

// hasMakeTarget checks if a Makefile defines a target with the given name.
// Matches "target:" at the beginning of a line (after optional whitespace),
// but not in comments (lines starting with #) or variable assignments (=).

但实现只跳过 # 注释行,未排除赋值:

func hasMakeTarget(makefileContent, target string) bool {
    targetPrefix := target + ":"
    for _, line := range strings.Split(makefileContent, "\n") {
        trimmed := strings.TrimLeft(line, " \t")
        if strings.HasPrefix(trimmed, "#") {
            continue
        }
        if strings.HasPrefix(trimmed, targetPrefix) {  // "test:=foo" 以 "test:" 开头 → 命中
            return true
        }
    }
    return false
}

触发场景(复核实证)

Makefile 含无空格 := 赋值且变量名恰为目标名(小写裸名 test/ci/verify/build):

test:=foo
all:
	@echo build

现实概率评估

需要同时满足:小写裸目标名作变量名 + := 无空格写法——真实 Makefile 中罕见,故定级低。但这是注释意图与实现行为的直接矛盾(漏报注释声称的防护)。

修复方向

匹配后额外检查后续字符不是 =strings.HasPrefix(trimmed, targetPrefix) && !strings.HasPrefix(trimmed, target+"=")(同时覆盖 :=::=)。

附带发现(同函数族,死代码)

verifyCommandAvailable(verify_hint.go:302-328):第一个 switch 对 "bash","sh","source" 无条件 return true(311-313 行),导致其后 if primary == "bash" || primary == "sh" { fileExists(parts[1]) }(316-320 行)永不可达——与注释 "For scripts run via bash/sh, check the script path instead" 矛盾。无行为影响:bash 脚本缺失时 bash 自身 exit 127,被 verify.go:364 防御兜住。修复属代码卫生:删死代码或将 fileExists 检查并入 switch 之前。

独立复核:spawn subagent(主模型),Go 程序复制函数体实证 + make 实测 exit 码 + 对照组验证。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions