Files
homeagent-sdk/tools/hmapdev/templates
JianFeeeee 678b9cf90c feat(hmapdev): 同 stage 多 handler 默认合并 + 注册期告警
## 修的是真实事故(2026-10-18)

模板里原来是:

	stageHandlers[string(stage)] = handler   // stage 名为键,后者覆盖前者

有人写了两次同 stage 注册:

	RegisterStage(BeforeToolcall, 权限门)   ← 被下一条覆盖
	RegisterStage(BeforeToolcall, 切状态)   ← 实际生效

后果不只是状态不切换 —— **权限门被静默关掉了**(那几版 QQ 插件里
任何人发消息都能调任何工具)。而内核侧日志显示 `2 handlers [qq qq]`,
看起来完全正常 —— 这是最难查的一类 bug,我为它白烧了十几轮。

## 处置(按用户要求:告警 + 默认合并)

	禁止重复 → 存量插件可能直接起不来(它们的重复常是本意)
	静默覆盖 → 就是当前 bug
	默认合并 → 两件事都做,且告警让开发者知道该优化写法 ← 选这个

合并语义三条:

 1. **按注册顺序链式执行**(先注册的先跑)
 2. **prev 返回 error 就中止**(与内核 RunStage 一致:权限门拒了
    就不该再切状态)
 3. **留痕**:注册期打 log.Printf 告警,开发者在插件启动时就能看见

★ 重复注册**不再**上报 stage.register:内核已经登记过一条,再报一条
会让它记两条 handler 而实际只派发一次 —— 那正是
`2 handlers [qq qq]` 假象的来源。

## 为什么改模板而不是 SDK

用户明确要求「工具链对同stage多handler注册给出告警」。模板是生成
proc_main 的地方,也就是 map 覆盖实际发生的地方;在源头拦,告警
直接出现在**插件启动日志**里。

## 判据(5 条,变异 3/3 咬)

 · 有"已存在"判断(不是无条件赋值)
 · 链式调用 prev(合并后旧 handler 不丢)
 · prev 出错中止
 · **告警是代码行**(跳过注释再找)+ 给出行动建议
 · `if dup` 分支内不含 stage.register

## 判据第一版是假绿

裸 `strings.Contains(body, "重复注册")` 把**注释里的解释**也算进去了,
于是删掉 log.Printf 后判据照样通过(变异不咬,实测)。
改成逐行跳过注释再找 log.Printf。这不是第一次栽在
「注释里有、代码里没有」上。
2026-10-18 15:28:07 +08:00
..

# {{.Plg.Name}}

{{.Plg.Description}}

## Build

```bash
plugindev build
```

## Install

Upload the `.hmap` file through the Plugin Manager API:

```bash
curl -X POST http://localhost:8080/api/v1/plugins \
  -H "Content-Type: application/octet-stream" \
  --data-binary @dist/<name_en_snake>_linux_amd64.hmap
```

## Lifecycle

- `RegisterStopHandler` — runs on every stop (including reload/disable), before `Stop()`.
- `RegisterOnRemoveHandler` — runs **only on uninstall (remove)**, after `Stop()`; clean up the plugin's own data files here. Reload/disable do NOT trigger it. See the onRemove demo in `main.go`.