Commit Graph

15 Commits

Author SHA1 Message Date
f256098c9f refactor: 全面改名为 HologramAgent + 提示词技术内容下沉到 skill/工具描述 + 修 21 处乱码
## ① 全面改名 HomeAgent → HologramAgent

仓库已改名,但代码与文档里仍有大量旧名。本次按"用户能看到的优先"全量替换:

- 用户可见:登录页标题/页脚、默认人格第一句、CLI 状态输出、启动日志、
  plugin_install 的工具描述、AI 图片插件的 User-Agent
- 文档与脚本:README、assets/docs、docs/zh、deploy/*.sh、.github/workflows
- 鸿蒙工程:cmd/ohos/HomeAgent → cmd/ohos/HologramAgent(git mv)
  目录内的 module/app 描述同步;**证书路径原样保留**
  (default_HomeAgent_xxx.cer/p7b/p12 是签名材料的实际文件名,改了会找不到证书)
- 插件元数据:plugin.json 的 author

★ 必须保持原样的两处(改了会坏):
  · legacySeededPromptSignature = "你是 HomeAgent 的看板娘「小宅」…"
    —— 那是识别历史播种人格卡的**原文锚点**,改了就识别不出旧数据
  · 公开 SDK 的 ProxyAuthHomeAgent = "homeagent"
    —— 那是 SDK 契约里的值,属独立仓库,本仓不改

## ② 修 21 处乱码(U+FFFD)

这些是历史编辑留下的编码破坏,全在注释里,例如:
  「赌注重下���遍」→「赌注重下一遍」
  「「不��滤」」  →「「不过滤」」
  「**待��退场**」→「**待退场**」

★ 保留 providers/chineseclip/tokenizer.go 里的 2 处:那是**故意**用
  U+FFFD 演示"非法 UTF-8 字节被归一成 U+FFFD",不是乱码。

## ③ 提示词技术内容下沉(用户:技术性内容应该收敛到 skill 与 -help 中)

实测系统提示词 2309 字,其中两段几乎全是**模型无法据以行动的实现细节**:

  【工具执行顺序】1272 字(ParallelSafe 声明、批内降级、batchRunnable 判据…)
  【三层记忆】   1069 字(L1/L2/L3 编号、消费式删除、向量空间、指纹…)

收敛后 **2309 → 1723 字(-25%)**,保留的全是"模型据此做什么不同的事":

  工具顺序:默认并行 / 不要依赖先后 / 同通道保序 / 写类工具可能串行
  三层记忆:时序里能看最近 / doc_query 把历史事件按原始时间戳插回时序 /
           关系用 memory_recall / 成文知识用 knowledge_search

判断口径写进判据:新加一段提示词前先问"模型会据此做什么不同的事",
答不上来就该进 skill 或工具描述。

## 判据

prompt_memory_test.go 新增 2 条:
- TestSystemPromptHasNoImplementationJargon
  黑名单:ParallelSafe / batchRunnable / 消费式 / DenseCosine / fingerprint /
  向量空间 / 批内降级 / 自激
- TestSystemPromptStaysCompact:上限 2000 字(当前 1723)

变异:把 "ParallelSafe 声明、批内降级" 加回工具顺序段 ⇒ 第一条立刻红。

## 验证

- go build ./... / go vet ./... 干净
- go test ./... -count=1:58 包 0 失败
- make check-client-versions:客户端与内核版本一致
2026-10-22 20:49:44 +08:00
a3ab6e5cfa docs(deploy): SDK 镜像仓示例统一为 hologramagentsdk
upload_assets.py docstring 与 docs/git-branching.md 的上传示例里,SDK 仓
仍写 homeagent-sdk;按已定口径(SDK 仓名 hologramagentsdk,gitcode/GitHub
两侧均 200 实测)统一,避免与 sdk-docs 线合并后出现两种说法。

纯注释/文档改动,零代码逻辑变更。
2026-10-21 20:18:30 +08:00
ffe9bc2cff refactor(ci,docs): gitcode 镜像仓改名 HomeAgent→HologramAgent,定义点取值对齐
gitcode 侧镜像仓已完成改名,旧名 HomeAgent 变成 301 跳转,真仓是
HologramAgent。dbb787a 里三处 GC_REPO 定义点仍取旧名(命中 301),本批只
改取值与说明,**不改变 dbb787a 已建立的「每个文件恰一个定义点」结构**,
不引入任何新字面量。

实测(2026-10-21 20:1x,直连不带代理,非推测):
  $ curl -s -o /dev/null -w '%{http_code}' https://gitcode.com/JianFeeeee/<repo>

  HologramAgent     → 200  ← 当前取值
  HomeAgent         → 301  ← 旧名,跳转到 HologramAgent
  homeagent-sdk     → 200(SDK 仓,另一对象)
  hologramagentsdk  → 200(SDK 仓,另一对象)
  homeagentsdk      → 404
  HologramAgent-sdk → 404

「301 不是另一个仓,就是同一仓改名」的判定依据:两个地址 `git ls-remote`
得到的 refs 列表 md5 相同(同一组分支与 SHA),且 curl 页面 title 一致。

三个定义点(各文件恰好 1 处,消费点全部走变量,本次只改这三行的取值):
1. .github/workflows/ci.yml   job sync-gitcode-main 的 env.GC_REPO
2. .github/workflows/release.yml job sync-gitcode   的 env.GC_REPO
3. deploy/scripts/upload_assets.py 的 os.environ.get("GITCODE_REPO", ...) 默认值
消费点未动:ci.yml 2 处、release.yml 4 处命令行,仍全部是 ${GC_REPO}。

注释同步改准(原来把 301 的仓写成「200 ← 当前用这个」,是错的):
- 两个 workflow 的取值依据清单换成上面六个仓的现状,注明实测时间与 curl 命令
- 明确 HomeAgent = 301 跳转、HologramAgent = 当前取值
- 「以后再改名只改这三行」的说明保留

docs/zh/ci-cd-runbook.md 同步:
- 总览表 gitcode 镜像改为 HologramAgent(与主仓同名)
- 「当前取值」段与六仓实测表、301 判定依据
- API 侧口径也改准:/api/v5/repos/JianFeeeee/{HomeAgent,HologramAgent}
  不带 token 均 400(需鉴权,非仓不存在);/releases/tags/v1.3.13
  两名字均 200 且响应体一致。旧文档写「HologramAgent→404 是死链」已不成立。
- §3.3 curl 验活地址、§3.4 手工上传示例的 GITCODE_REPO 同步为新值

判据(正向 14 项 + 变异 11 条,全部实跑):
- 两个 workflow yaml.safe_load 解析通过;每个 env.GC_REPO 恰好 1 处
- 三处定义点取值完全一致(P4);消费点计数 ci=2/release=4(P6)
- P8 改为「不带 -L 的 200」:这正是本次误判的根因——之前用 curl -L 测,
  301 跟随后也是 200,把「旧名跳转」误读成「旧名是真仓、新名 404」
- 变异 M11「三处一致改回旧名 HomeAgent」只被 P8 抓住(P4 仍绿),
  证明该判据能单独区分「一致但指向 301 旧名」
- 所有 step run 块过 bash -n(30 个 run 块,0 错)
- gitcode 作 import host 残留 0;工作区无 .go/.lua/go.mod/go.sum 变更

零代码改动:packaging_test.go 里「禁止历史模块路径」的反向断言未动,
third_party 未动,systemd 相关行未动。
2026-10-21 20:15:41 +08:00
dbb787a658 refactor(ci,docs): gitcode 镜像仓名收为单一定义点,取值 HomeAgent(实测 200)
gitcode 镜像目标仓名此前在 3 个文件里各写死多份字面量,改名时要遍改且极
易漏(漏一处 = 一个静默死链,而且失败面在 release 里只有一格)。本批只做
「收成单点」,不改任何取值、不碰代码。

三个定义点(每个文件恰好 1 处,消费点全部走变量):
1. .github/workflows/ci.yml → job `sync-gitcode-main` 的 env.GC_REPO:232
   消费点 2 处命令行:git ls-remote 探测、git push main。
2. .github/workflows/release.yml → job `sync-gitcode` 的 env.GC_REPO:375
   消费点 4 处命令行:git ls-remote 探测、push tag、POST /releases、
   upload_assets.py 的 GITCODE_REPO 传入。
   (两个 workflow 是独立文件,不能共享 env,故各自一处定义。)
3. deploy/scripts/upload_assets.py → os.environ.get("GITCODE_REPO", ...) 默认值。
   手工跑脚本时的兜底,与两个 workflow 同值。

为什么取值 JianFeeeee/HomeAgent 而不是 HologramAgent:
GitHub 主仓已改名 HologramAgent,但 **gitcode 侧镜像仓没有跟着改名**。
curl 直连实测(2026-10-21):
  https://gitcode.com/JianFeeeee/HomeAgent      → 200   ← 当前取值
  https://gitcode.com/JianFeeeee/HologramAgent  → 404
指向 HologramAgent 会让每次发版/推 main 都在镜像同步这步红掉,且国内镜像
停止更新。

两个 job 的失败面不同(容易搞混,此处写明):
- release.yml 的 sync-gitcode:needs [prepare, publish]。探测 exit 1 ⇒
  **只红「镜像同步」这一格**;GitHub 侧 release 产物已经发出去了。
- ci.yml 的 sync-gitcode-main:needs [go, race, cross, gui, csrc, docs] 全绿
  后才跑。探测 exit 1 ⇒ **main 的整条 CI 红**(不是一格)。
所以仓名写错的真实后果是「必红一格 + 国内镜像不更新」,不是「发不出包」。

何时切回 HologramAgent:等 gitcode 上把镜像仓真正改名/新建成功、
https://gitcode.com/JianFeeeee/HologramAgent 返回 200 之后,
**只改上面这三行**即可,两个 workflow 的消费点与 runbook 均无需再动。

docs/zh/ci-cd-runbook.md 同步三节:单点化表格(定义处/消费点)、当前取值与
200/404 实测依据、两个 job 的失败面差异;并把 §3.4 的 curl 验活地址与
upload_assets 手工调用示例同步到 HomeAgent(原写法是已 404 的死链)。

判据(含变异,全部实跑):
- 两个 workflow 可被 yaml.safe_load 解析;每个 jobs[..].env.GC_REPO 恰好 1 处
- 每个 step 的 run 块抽出来喂 bash -n,全部无语法错
- 可执行形态里的 gitcode 目标仓名不含 HologramAgent(注释行豁免)
- 变异:把任一 GC_REPO 定义改回 HologramAgent、或把某消费点还原成字面量,
  判据均报红
- 零代码改动:git status 无 .go/.lua/go.mod/go.sum;go build ./... 通过
2026-10-21 19:55:59 +08:00
ee2b7d7bac fix(docs,site): 回退上一批错误口径 —— SDK 仓名与站点域名改回实际活链
上一批(37b8c26 / 228fae2)把文档与站点里的 SDK 仓名统一改成了
`JianFeeeee/HologramAgent-sdk`、把站点域名改成了 `*.hologramagent.jianfgit.xyz`,
前提「本机无外网、无法验证」是错的。实测外网通畅,两处改动都是真实死链,本批全部回退。

## 一、SDK 仓名 HologramAgent-sdk → homeagentsdk(104 处)

| 文件 | 处数 |
|---|---|
| site/index.html | 23 |
| README.md | 7 |
| README_EN.md | 7 |
| assets/docs/zh/PLUGIN_DEV.md | 29 |
| assets/docs/en/PLUGIN_DEV.md | 29 |
| assets/docs/zh/OVERVIEW.md | 2 |
| assets/docs/en/OVERVIEW.md | 2 |
| docs/git-branching.md | 2 |
| docs/zh/ci-cd-runbook.md | 3 |
| **合计** | **104** |

含 `.git` 形态与 `cd homeagentsdk` 目录名。PLUGIN_DEV.md 里原本就是
`import "github.com/JianFeeeee/homeagentsdk/sdk"` 的两处示例(zh 253/448、en 255/455)
与 6a 前基线逐行 diff 无差异,未被改动成第三种形态。

## 二、站点域名 hologramagent.jianfgit.xyz → homeagent.jianfgit.xyz(15 处)

| 文件 | 处数 |
|---|---|
| README.md | 4 |
| README_EN.md | 4 |
| docs/zh/deploy-runbook.md | 2 |
| deploy/scripts/deploy-sdk-site.sh | 5 |
| **合计** | **15** |

deploy-sdk-site.sh 只改探活/注释里的域名,nginx 语义(SNI 透传、
server_name → root 的链路描述)未变。

## 三、明确未动

- go.mod 两行、third_party/homeagent-sdk 路径、internal/**/*.go 的 import —— 零改动
- deploy/scripts/upload_assets.py:23 默认值 `JianFeeeee/HologramAgent` 保留(主仓确已改名)
- cmd/gui/package.json homepage 保留 HologramAgent(GitHub 200)
- docs/git-branching.md:420 的 GITCODE_REPO 改为 `JianFeeeee/homeagent-sdk`:
  gitcode 上只有 homeagent-sdk(200) 与 HomeAgent(200),HologramAgent-sdk 与
  HologramAgent 在 gitcode 均为 404

## 四、实测证据(curl -L -o /dev/null -m 25 -w '%{http_code}')

GitHub 侧(经 http://127.0.0.1:7890 出口):

    200  https://github.com/JianFeeeee/homeagentsdk          ← 回退目标,活链
    200  https://github.com/JianFeeeee/HologramAgent         ← 主仓,确已改名
    404  https://github.com/JianFeeeee/HologramAgent-sdk     ← 上一批写成这个,死链
    404  https://github.com/JianFeeeee/homeagent-sdk         ← 不是这个名字
    200  https://github.com/JianFeeeee/HomeAgent             ← 301 → HologramAgent

深链抽查(回退后全部 200):

    200  .../homeagentsdk/tree/main/example/weather
    200  .../homeagentsdk/tree/main/example/plugindev
    200  .../homeagentsdk/tree/main/example/luademo
    200  .../homeagentsdk/blob/main/LICENSE
    200  .../homeagentsdk/tree/v1.1.0

站点域名(直连,不走代理):

    200  https://sdk.homeagent.jianfgit.xyz/                ← 回退目标,已部署
    200  https://introduce.homeagent.jianfgit.xyz/
    200  https://sdk.homeagent.jianfgit.xyz/llms.txt
    200  https://sdk.homeagent.jianfgit.xyz/llms-full.txt
    404  https://sdk.hologramagent.jianfgit.xyz/            ← 上一批写成这个,未部署

新子域 404 的原因不是网络:证书是 CN=*.jianfgit.xyz 通配符可用,
但 nginx 里没有 hologramagent 的 server_name,站点根本没部署。

gitcode 侧(决定 §三 那行的连字符形态):

    200  https://gitcode.com/JianFeeeee/homeagent-sdk
    200  https://gitcode.com/JianFeeeee/HomeAgent
    404  https://gitcode.com/JianFeeeee/HologramAgent-sdk
    404  https://gitcode.com/JianFeeeee/HologramAgent

## 五、验收

1. 全仓 `HologramAgent-sdk` 计数 = 0(.md/.html/.py/.sh/.yml/.yaml/.txt/.json/.go/.mod/.sum)
2. 全仓 `hologramagent.jianfgit.xyz` 计数 = 0
3. site/index.html 23 条 SDK 链接全指向 homeagentsdk,0 条指向 HologramAgent-sdk
4. curl -L 三条必测均 200(见 §四)
5. `TMPDIR=/home/newqqagent/tmpbuild6 go build ./...` 退出码 0
   (/tmp 已 98% 满,用独立 TMPDIR 避开 No space left on device)
6. git status 干净;11 个改动文件全为 .md/.html/.sh,零 .go 改动
2026-10-21 19:36:53 +08:00
228fae252d fix(docs): 回退 PLUGIN_DEV 的 SDK import 示例,并修正 upload_assets/gui homepage 的仓名
上一批 37b8c26 把文档里 4 处 Go import 示例改成了
`github.com/JianFeeeee/HologramAgent-sdk/sdk`,但该 module 路径并不存在:
主仓 go.mod:16 仍是 `github.com/JianFeeeee/homeagentsdk v0.9.2`,:46 replace
目标未变,third_party/homeagent-sdk/go.mod 首行仍是
`module github.com/JianFeeeee/homeagentsdk`,GitHub 上 HologramAgent-sdk
与 hologramagentsdk 均 404。照着文档抄这行 import 会直接 module not found,
比不改更坏。本次回退成真实可编译的 homeagentsdk。

改动:
- assets/docs/{zh,en}/PLUGIN_DEV.md 各 2 处(zh:253、448;en:255、455)
  import 路径回退为 github.com/JianFeeeee/homeagentsdk/sdk。该行附近未加任何
  「已改名」说明——等 SDK 仓真改名、主仓 go.mod 与第三方 module 一起改时
  再统一处理,属另一批。全仓已无 HologramAgent-sdk/sdk 形态。
- deploy/scripts/upload_assets.py:8、:23 默认目标仓
  JianFeeeee/HomeAgent → JianFeeeee/HologramAgent(主仓确已改名,HomeAgent
  在 GitHub 上 301)。:8 括号里「SDK 仓传 JianFeeeee/homeagent-sdk」按要求保留。
- cmd/gui/package.json:5 homepage 元数据同步为 HologramAgent;该文件仅此
  1 行变更,name/author/description 等其它字段未动。

保留不动(已获确认属正确形态):
- go.mod 两行与 deploy/packaging/package-linux.sh 六处 homeagentsdk
  (必须与 go.mod 逐字一致)
- internal/**/*.go 的 74 处真实依赖 import
- deploy/packaging/packaging_test.go:99,101 对 gitcode.com/JianFeeeee/HomeAgent
  的反向断言(它断言 build.sh 不得使用历史路径)
- internal/plugins/webui 三处注释里的 homeagent.jianfgit.xyz(历史实测记录)
- cd HologramAgent-sdk / clone ...HologramAgent-sdk.git(操作指令目录名与 URL,
  非 import 路径)

判据:7 条正向(含「文档 import 路径必须与 go.mod 的 SDK module 同源」);
变异 4 次均按预期报红——分别还原 zh:253 import、upload_assets.py:23 默认值、
gui homepage、以及把 packaging_test.go 反向断言那两行也改名。
go build ./... 通过,go test ./deploy/packaging/ 通过。
2026-10-21 19:25:05 +08:00
37b8c26675 refactor(docs): 批6a 清理介绍站与文档的旧仓名/旧链接
改名 HomeAgent → HologramAgent 后,介绍站与仓内文档仍指向旧仓地址、旧站点
域名,点击即 404 / 落回旧站。本批只动文档与静态站,代码零改动。

映射(严格按主管给定的唯一权威口径):
- github.com/JianFeeeee/HomeAgent → .../HologramAgent(含 /blob /releases /tree)
- github.com/JianFeeeee/homeagentsdk → .../HologramAgent-sdk
- introduce.homeagent.jianfgit.xyz → introduce.hologramagent.jianfgit.xyz
- sdk.homeagent.jianfgit.xyz → sdk.hologramagent.jianfgit.xyz
- 品牌名/链接文本 homeagent-sdk → HologramAgent-sdk(含 `cd homeagent-sdk`
  克隆后的本地目录名,跟随新仓名)

改动面(12 个文件,138 行,纯替换无逻辑变更):
- site/index.html 36 处:13 处主仓链接 + 23 处 SDK 仓链接(22 个 example/
  与 LICENSE、仓库首页)
- README.md / README_EN.md 各 12 处(9 处 URL + 3 处链接文本)
- assets/docs/{zh,en}/PLUGIN_DEV.md 各 34 处、OVERVIEW.md 各 2 处
- docs/zh/ci-cd-runbook.md 9 处、docs/zh/deploy-runbook.md 2 处(站点域名)
- deploy/scripts/deploy-sdk-site.sh 5 处(注释里的 server_name + 3 处 curl
  探活地址,否则改完站脚本仍在验旧域名)
- docs/git-branching.md 2 处、assets/skills/commondev-discipline/SKILL.md 1 处
  (gitcode module 路径)

刻意不动(动了会坏):
- 真实目录 third_party/homeagent-sdk(只改 URL 里的 homeagentsdk)
- go.mod 的 module / replace、所有 .go import(module 仍是
  github.com/JianFeeeee/HologramAgent,SDK 仍 homeagentsdk)
- deploy/packaging/package-linux.sh 里的 `replace github.com/JianFeeeee/
  homeagentsdk` 与 clone URL —— 它必须与未改动的 go.mod 逐字一致,属代码非文档
- 数据目录 ~/.homeagent、二进制 homed、产物名 hologramagent_*、
  插件名 homeagent-mail-bridge
- systemd 相关行(homeagent.service / systemctl / journalctl)—— 待上级确认,
  本批不动,清单见汇报
- docs/api/*.md(首行「请勿手改」,生成型)

判据(含变异验证):
- 三条旧串 grep 全仓清零;third_party/homeagent-sdk 目录仍在
- site/index.html 标签配平(HEAD/WORK 双跑)+ section 数 13→13 未减
- 变异:分别还原 deploy-sdk-site.sh:206、site/index.html:3041、README.md:243、
  ci-cd-runbook.md:11 各一处,以及删一个 </footer>,判据均按预期报红
- go build ./... 通过(仅把 TMPDIR 指到 /var/tmp 规避 /tmp tmpfs 满,仓内文件无关)

未执行任何线上动作:不 push、不开 PR、不重命名 GitHub 仓。注意 SDK 仓在
GitHub 侧目前仍叫 homeagentsdk,本批把文档指向 HologramAgent-sdk 是「改名
在路上」,该仓改名完成前这批 SDK 链接会 404。
2026-10-21 19:22:02 +08:00
67d0d90888 refactor(deploy): Windows 安装器与 WSL 引导脚本改名,并修两处跨脚本不同源
installer.nsi / install-via-wsl.ps1:产品名、输出名
HologramAgent_v*_win64.exe、GUI 目录 hologram-gui-win32-x64、快捷方式、
自启注册表项、HOMEAGENT_* → HOLOGRAM_*(安装器写、setup.sh 读,必须同改)、
WSL 内数据目录 /var/lib/hologram 与 hologramagent.service。

package-windows.sh 两处顺带修:
 1. GUI payload 目录名**不假设上游已改名**。它由 Makefile:331
    (GUI_BINARY=homeagent-gui)或 build.sh 的 electron-builder
    (productName=HomeAgent)产出,两者都归别的批;而 .nsi 现在期望
    hologram-gui-win32-x64。直接改引用会让 Windows 包以
    "[FAIL] 需要 GUI payload" 挂掉(或者更糟:有人放宽检查,安装器
    File 一个不存在的目录)。改成找到哪个用哪个、统一 stage 成 .nsi 期望名。
 2. 版本号解析与 package-linux.sh/build.sh 同源。原先直接
    `git describe --tags`,无 tag 分支上拿到的是分支名,于是拼出的
    DEB_GLOB 永远找不到包 —— 报错信息看起来像"Linux 包没打出来",
    真因是版本号被解析成分支名。现改为「形如 vX.Y.Z 才采用,否则回退
    meta.Version」,并加数字开头守卫。

deploy/scripts/deploy.sh:单元文件名与 systemctl 提示改成 hologramagent。
(deploy-plan.sh 不动:它的 SVC 指的是**本机正在跑的那个**旧单元,
 归部署 runbook;deploy-sdk-site.sh 的域名归批 5;upload_assets.py 的
 仓库名归批 4。)
2026-10-21 13:21:12 +08:00
a68d6a428c feat: 模块化内核(编译期依赖图定序)+ 密钥防火墙 + 插件三态生命周期 (#10)
* feat(kernel): 模块化内核 + 编译期依赖图定序

把单体 init 序列拆成「模块自声明依赖 + 编译期生成依赖图 + 运行期只读图」。

## 为什么

原 cmd/homed/main.go 里 17 步 init 是**手写顺序**,依赖关系只存在于
注释和人脑里。实测踩到的坑(见 docs/zh/kernel-modularization-design.md):
 · nlp.defaultParser 被 initONNXParser 写、被 distiller 读,两者相距 60 行,
   只靠 ticker 10min 才没炸(隐式依赖,无声明)
 · 加一个模块要人肉找"该插在哪",插错的表现是运行期 nil 解引用
 · 关停是 defer ks.CloseAll(),而热更新路径 os.Exit(42) **跳过 defer**
   ⇒ docStore/distiller/textMem 的 flush 全部丢失(每次热更新都发生)

## 怎么改

- internal/kernelboot/:KernelState(一个结构体收全部包级共享变量,字段
  nil 安全)、Module 接口、graphfile(依赖图编解码 + 与二进制 hash 对账)、
  scheduler(按 BFS 层并行 Init)、syncbus(层边界写通知)、
  lifecycle(Quiesce/Resume 可逆伪关机,区别于一次性 CloseAll)
- internal/kernelmod/<name>/:每个模块一个文件夹,Requires/Provides 自声明;
  all/all.go 是唯一的 import 清单(Go 循环导入约束)
- cmd/homed-depgraph:编译期生成依赖图,Makefile 注入 digest
- 运行期只**读**图,不计算顺序(顺序是编译期决定的,源码里没有中央清单)

## 判据

kernelboot 8 条 + 图失败模式 7 条(全部拒绝并给准确错误)+ 模块目录数
与注册表一致性。变异测试 15/15 咬住,含:
 · 删掉 AddCloser 的锁 → -race 报数据竞争
 · Scheduler 同批跑去重 → 203 vs 200
 · 图 hash 不匹配 → 拒绝启动

## 顺带修的缺陷

热更新路径漏调模块关闭 ⇒ 显式 stopKernelModules(),并用 AST 判据钉住
"必须在 os.Exit 之前"(字符串检查在本仓已骗过我三次)。

实测:冷启动 1630ms(5 层/17 模块,原 17 步串行);生产 22 插件全部建链。

* feat(security): 密钥防火墙 + 配置加密 + close 纪律

## 密钥防火墙

模型只见别名、不见明文;插件工具调用入口(StageHost.ExecuteTool)做入向
回填。三维能力:
 · 出向:工具输出里的密钥被替换成 [[secret:name]] 别名后才进上下文
 · 入向:模型传别名,入口处填回真值(插件完全无感知)
 · 存储:config.db 里不存明文(0644 的库可读),敏感值独立 0600 文件

模式库「宁漏勿误伤」:宁可漏掉一次替换,也不把正常文本误当密钥。

## 配置加密

- internal/security/{codec,key,keyring,store,global}.go:AES-256-GCM,
  enc:v1: 前缀,密钥轮换(OldKeys 解码 + 新钥加密)
- harden.go:数据目录权限收紧
- embedded.go:支持内嵌主密钥(可选,仍保留外部 key 文件路径)
- EncryptExistingSecrets / AuditSecrets:启动时幂等迁移 + 审计

## close 纪律(用户明确要求:只要调 close 就要有前置检查)

internal/safeclose:Safe / SafeFunc。全仓 37 处裸 close(chan) → 0。
关键教训(都写进注释和判据):
 · `select { case <-ch: default: close(ch) }` **不是**并发安全的
   (两个 goroutine 可同时命中 default)—— healthcheck 原先是这种写法
 · `sync.Once` **不可重入**:X.Do(func(){ Safe(&X, ...) }) 会自锁,
   症状是 go test 直接挂住(3 个包 600s 超时),栈里只有嵌套的 Once.Do
 · map 里按请求持有的 channel(mcp/stdio.go、clawhubadapter/sidecar.go)
   改成 *pendingRPC 包装,每通道一个 once

## 判据

security 全量 + TestNoBareCloseOutsideSafeclose(AST 级扫描,含注释剥离)
+ TestNoNestedSelfOnceDeadlock(正则修正:\w+ 不匹配点号,捕获组要含 '.')。
变异 2/2 咬住。全量 52 包 ok。

* feat(plugin+deploy): 插件三态生命周期、数据目录迁移、发行包修复

## 插件三态生命周期(用户要求:自动启动 / 启用但不自动启动 / 禁用)

- Manifest 新增 requires_facilities / auto_start(*bool,用于区分
  "未声明"与"显式 false")
- plugin-host 模块(internal/kernelmod/pluginhost):用 kernelboot.Scheduler
  按依赖时机拉起,**不再手写两阶段**
- 运行态停启 StopPlugin/StartPlugin **可逆**:不写 disabled_plugins
  (不改用户决定)、不置 shuttingDown(之后还能加载)、会摘掉注册面
- 与 StopAll 的区别写进注释 —— StopAll 置 shuttingDown 后**永久无法加载**,
  那是进程退出用的,误用于"暂停"就是关了就死

## 数据目录迁移(伪关机 → 迁移 → 唤醒)

- kernelboot/lifecycle.go:Quiesce/Resume(可逆,区别于一次性 CloseAll),
  逆序暂停、逆序恢复、Pause 失败回滚
- kernelboot/migrate.go:BeginMigration/End 编排(先停插件 → 再停内核写者
  → 等在途归零)
- distiller/textmem 增 Pause/Resume 门(不是 cancel —— cancel 不可逆,
  恢复要重建整个对象)
- 模块 migration:体检 + 生成可执行迁移脚本

★ 迁移脚本的三个实测教训(都写成了判据):
 1. 无条件改 /etc/systemd/system ⇒ 演练把**生产** -data 改成了演练目录。
    加 --dry-run(零改动)+ 强制校验 systemd 当前 -data == OLD
 2. 本机没装 rsync,脚本在"服务已停、数据未搬"处硬失败 ⇒ cp -a 回退,
    并明确警告不保硬链接/ACL(生产 plugindev 有大量 git 硬链接)

## 发行包修复(全部经实测确认)

 1. package-linux.sh **完全漏打 depgraph.bin** ⇒ 内核 exit 1
    ("生产构建(内嵌 hash 非空)但读不到依赖图")
 2. build_homed 不走 Makefile ⇒ 单独修 Makefile 无效,必须同时生成图+注入
 3. build.sh 的 LDFLAGS 用**历史模块路径 gitcode.com** ⇒ -X 静默 no-op
    ⇒ --version 显示 unknown
 4. Makefile -ldflags 用**单引号** ⇒ 注入了字面 $GRAPH_HASH

## ★ build.sh 的版本号必须校验(真实事故)

原 `VERSION="$(git describe --tags --dirty)"`。无 tag 分支上它返回**分支名**
`backup/pre-identity-rewrite-20261005-51-g03d87a4e-dirty`,被注入 meta.Version
⇒ 插件握手判据 MajorVersion() 把整串当主版本 ⇒ **22 个子进程插件全部
握手失败**("主版本不匹配")。内核活着、systemd active、日志每条都像
插件的问题 —— 实际是发行包带着非法版本号。

修法:git describe 只在形如 vX.Y.Z 时采用,否则回退 meta.Version(权威源),
并对最终值做形态守卫。deploy/packaging/version_guard_test.go 3 条判据,
变异 2/2 咬住。

## deb 的 systemd unit 改为 guard 模式

ExecStart=/usr/bin/homed --role=guard --data /var/lib/homeagent
(worker exit 42 → guard 重拉,不经过 systemd、不计失败)
含 RestartSteps/RestartMaxDelaySec/TimeoutStopSec + 硬化
(NoNewPrivileges/ProtectSystem/ProtectHome/DevicePolicy/ReadWritePaths)。

## 其他

- internal/plugin/proc:非法 JSON 帧的报错**可定位**(内容摘要 + 可能原因 +
  修法)。生产实测 1038 条非法帧(插件往 stdout 打日志 = 污染协议通道)
- 示例插件 4 个 14 处 fmt.Printf → log.Printf
- hmapdev 模板同步修复;scaffold 判据剥离注释(模板注释里就含 fmt.Printf)

* chore: 收尾(主密钥轮换命令、IPC/知识库加固、SDK 对齐)

- cmd/homed-key-rotate:把 security 里的 RotateKey/RotateKeyFile/RekeySecrets
  串成一条**可执行**的运维路径。没有它,E-1 就只是库里的能力而不是
  "出事时能做的事",而轮换的价值恰恰在于能执行。
- cmd/homed:kmod_runtime(模块装配入口)、plugins_scheduled(failback
  白名单)、memcandidate、bootstrap_order_test / shutdown_flush_test
- internal/ipc、internal/devicebridge、internal/knowledge:配套加固
- third_party/homeagent-sdk/sdk:PluginMgrAPI 增三态能力(mgrStop/mgrStart/
  mgrIsRuntimeStopped)+ settings 对齐

判据:bootstrap_order_test(启动顺序不依赖手写序列)、
shutdown_flush_test(停机的两条路径必须对称 —— exit 42 会跳过 defer,
热更新路径下模块关闭/flush 曾全部丢失)。

* test(security): 测试夹具改用不可误认的占位值(修 push protection 拦截)

GitHub secret scanning 拦住了推送:三处测试夹具用了"看起来像真密钥"的
字面量:

  internal/security/prefilter_test.go:39
  internal/security/store_test.go:177
  internal/security/survey_test.go:20

它们全是**假密钥**(`AKIAIOSFODNN7EXAMPLE` 是 AWS 官方文档的标准示例,
其余是 `abcdefghij...` 这类可读占位符),但扫描器无法区分 —— 它只看形态。

★ 不绕过(不用 unblock URL、不加 allowlist):直接改夹具。
原因:一旦允许"假密钥可以通过",真密钥混进来时就没有最后一道门了。

改法:保留**模式库匹配所需的结构**,把可识别内容换成 FAKE:
  glpat-abcdefghijklmnopqrst       → glpat-FAKE-TEST-TOKEN-NOT-REAL
  sk-abcdefghij...012345           → sk-FAKE-TEST-KEY-NOT-REAL-0000000
  AKIAIOSFODNN7EXAMPLE             → AKIA0000FAKE0000TEST   (保持 20 字符)
  ASIAIOSFODNN7EXAMPLE             → ASIA0000FAKE0000TEST
  xoxb-123456789012-abcdefghijklmnop → xoxb-FAKE-TEST-TOKEN-NOT-REAL

★ 中途踩到一次:AWS 键的模式是 `\b(AKIA|ASIA)[0-9A-Z]{16}\b`(共 20 字符),
我第一次替换成 19 字符的 `AKIAFAKETESTKEY0000` ⇒ 模式匹配不上 ⇒
TestSurvey_WhatIsCaught / TestRecognizesCommonShapes /
TestPrefilterNeverBlocksRealMatches 三条当场变红。
判据正确地拒绝了"为了过扫描器而削弱覆盖"。

顺带核实:全仓 grep 无任何真实密钥泄漏。

* fix(packaging): package-linux.sh 的版本解析与 build.sh 统一

上一版只修了 build.sh,漏了 package-linux.sh —— 它仍只看 git describe:

  VERSION="${VERSION:-$(git describe --tags --dirty)}"

无 tag 分支上 git describe 返回**分支名**
(backup/pre-identity-rewrite-20261005-56-g98850e1),守卫会正确拒绝,
但要求人**手动传 VERSION** 才能打包。而 build.sh 早已能自动回退 meta.Version
⇒ 同一个版本,走 build.sh 打得出来、走 package-linux.sh 打不出来。

危害不只是"要手动传参":运维为了跑通会去掉守卫,而分支名一旦进
meta.Version 就是**插件协议主版本**的来源 ⇒ 22 个子进程插件全部握手失败
(这是真实发生过的事故,见 3efa4e5)。

修法:两个脚本用同一套规则(git describe 仅在 vX.Y.Z 形态时采用,
否则回退 meta.Version),并对最终值做形态守卫。

判据:TestBothPackagingScriptsShareVersionRules —— 逐个读两个脚本,
要求都能从 meta/meta.go 取权威版本、都校验 git describe 形态。
变异(把 package-linux.sh 改回旧规则)咬住并准确指出是哪个脚本。

实测:不传 VERSION 跑 package-linux.sh,输出
  [PKG] warn: git describe 给出非版本串(...),改用 meta.Version=1.4.0
  Version: 1.4.0

* fix(test): 跨仓判据在 CI 上应 skip 而非 fail(修 PR 双红)

CI 上 "Go build / vet / test" 与 "Build linux/amd64" 双红:

  --- FAIL: TestHmapdevTemplateImplementsAllPluginMgrMethods
      bridge_sync_test.go:170: 读模板: open
      ../../../third_party/homeagent-sdk/tools/hmapdev/templates/proc_main.go.tmpl:
      no such file or directory

## 根因:判据依赖了一个**被 gitignore 的路径**

`.gitignore:33` 有 `third_party/homeagent-sdk/tools/`(SDK 仓自治,本仓不跟踪)。
于是:
  · 本机(完整 SDK 检出)有该文件 ⇒ 判据通过
  · CI(只 checkout 本仓)没有该文件 ⇒ Fatalf ⇒ **必红**

我提交时只在本机跑测试、没看 CI,所以这个问题拖到 PR 才暴露。

## 修法

文件缺失时 `t.Skipf` 而不是 `t.Fatalf`。

★ 这不是"放弃检查":
  · 跨仓一致性由 **SDK 仓自己的判据**守着
    (tools/hmapdev/scaffold_stdout_test.go 等),那里才是模板的真实归属地
  · 本判据在本机开发时**仍然生效**(已验证:有文件时 PASS,缺文件时 SKIP)

## 验证

 · 本机(有文件)  → PASS(判据真跑)
 · 模拟 CI(移走 tools/)→ SKIP(不再 fail)
 · 全量 53 包 ok / 0 fail

## 顺带

同目录还有 e2e_template_test.go 也读 tools/,但它是 `//go:build` 门控的
e2e 判据,CI 默认不跑,无需处理。

---------

Co-authored-by: JianFeeeee <JianFeeeee@users.noreply.gitcode.com>
2026-10-17 19:18:24 +08:00
7901651946 chore: 根目录清理(第二轮)—— 移除过程文档、本机脚本、临时产物 (#3)
★ 上一轮清理被合并覆盖:GUI 分支含 DESKTOP-PET-NOTES.md /
SERVER-HANDOFF.md / GUI-PLAN.md,合并时取了我方版本,
但我方 main 已是 squash 产物 ⇒ 三个文件复活。
而我当时只核对了 benchmark.md 一个就宣布成功 —— 判断依据不足。

本轮逐个文件验证(不再抽样)。

删除(零代码引用)
  DESKTOP-PET-NOTES.md    外部产品(Coopanion)拆解笔记
  SERVER-HANDOFF.md       给服务端的待办清单,已过时
  napcat-design-dna.json  设计 DNA 数据
  tmp_jinabench.py        临时脚本
  tmp_benchmark/          临时跑分程序

归位(不是删)
  plan.md        → docs/zh/legacy-issues.md  (遗留问题清单,有价值)
  GUI-PLAN.md    → cmd/gui/GUI-PLAN.md      (含坐标换算/koffi 踩坑)
                   根目录那份与 cmd/gui/ 已有副本字节相同(285b84dd…),删前者
  deploy-plan.sh     → deploy/scripts/
  deploy-waiter.sh   → deploy/scripts/
  deploy-sdk-site.sh → deploy/scripts/

脱敏(deploy-plan.sh 与 deploy-sdk-site.sh 含本机路径)
  /home/newqqagent      → ${HA_DATA}
  /home/program/TrueAgent → ${REPO}
  /home/program         → ${HOME_DIR}

引用同步:27 处(docs/zh/deploy-runbook.md、toolcall-parallel-execution-plan.md、
scripts/capability-bench/PLAN.md、三个脚本自身的用法注释、ci.yml 注释)

根目录现状:仅 README.md / README_EN.md / LICENSE / Makefile /
go.mod / go.sum / .gitignore / .golangci.yml / .mailmap / .pi-lens.json

验证:go build ✅  三个 sh 的 bash -n ✅
     go test -short ./internal/... ./pkg/... ./cmd/... 全绿
     根目录文件清单逐个核对(10 项,全为门面/配置)

Co-authored-by: pi <pi@local>
2026-10-05 11:44:04 +08:00
e188296dab fix(release): .hmap 纳入发布产物白名单 + 路径解析
## 白名单(真问题)

`upload_assets.py` 的 ARTIFACT_SUFFIXES 只有 .tar.gz/.zip/.deb/.rpm/.pkg/_win64.exe,
**没有 .hmap** —— 即使插件包已经构建好放在 dist/ 下,上传时也会被静默跳过。
这正是「release 里一个插件包都没有」的直接原因之一。

补 `.hmap` 与 `SHA256SUMS.plugins`(插件包的汇总校验和,与内核包的 SHA256SUMS 分开,
避免混用)。实测 is_artifact() 现能正确识别两者、仍跳过 README.md。

## 测试路径解析

`HMAP_BUNDLE_DIR=dist/plugins` 这种相对仓根的写法原先会失败:测试的 cwd 是包目录
(internal/plugins/pluginmgr),相对路径解析到包内,报 "no such file or directory",
看起来像产物不存在。改为相对路径按仓根解析(向上找含 go.mod 的目录)。

实测三种调用都正确:相对路径、绝对路径、不设时 skip。
2026-09-20 09:07:33 +08:00
46ce92618c chore(version): 客户端版本与内核对齐(唯一事实源 internal/meta.Version)
此前三份版本号互不相干:内核 1.4.0、GUI 1.0.0、鸿蒙 1.1.1。手工各改各的
必然漂移,所以把「对齐」做成机械动作而不是约定:

- deploy/scripts/sync-client-versions.sh:从 internal/meta.Version 读版本,
  同步 cmd/gui/package.json 与鸿蒙 AppScope/app.json5(versionName +
  versionCode=X*1e6+Y*1e3+Z);--check 给 CI/Makefile 做漂移门禁。
- Makefile 新增 sync-client-versions / check-client-versions;build-cli 也注入
  LDFLAGS,waiter 与 homed 同版本。
- 鸿蒙:新增 common/AppVersion.ets,从 bundleManager 读安装包 versionName,
  BridgeProtocol/BridgeCaps 里两处硬编码 '1.1.1' 改为读它——版本只剩
  app.json5 一份,杜绝第二真相。
- waiter:`-version` 打印版本,启动横幅与设备桥 hello 的 version 字段
  直接引用 internal/meta,与内核天然同源。

对齐后:GUI 1.4.0 / 鸿蒙 1.4.0(1004000) / waiter 1.4.0 / 内核 1.4.0。
2026-09-15 11:03:26 +08:00
8e2b27f072 fix(release): upload_assets.py 按 go.mod 定位仓库根,不再数 dirname
脚本从 scripts/ 移到 deploy/scripts/ 后目录深度 1→2,而两层 dirname
是写死的,于是资产目录解析成 deploy/dist/release,上传直接
FileNotFoundError(v1.0.1 首次上传即因此失败)。

这与 v0.7.2 的 7f08f3c 把 package/ 移到 deploy/packaging/ 打断
build.sh 的 PROJECT_ROOT 是同一个坑:目录搬家没更新相对路径。改成
向上找 go.mod,以后脚本放哪都不会错。

顺带把两个静默失败改为显式报错:目录不存在、目录下无可识别产物
(原先前者抛裸 FileNotFoundError,后者会打出 ALL OK 却一个都没传)。
2026-09-04 10:34:51 +08:00
d043fed5ce docs: 文档与发布脚本同步到 v1.0.0 子进程架构
README/架构文档仍在描述 C ABI 动态库加载,与 v1.0.0 实际实现不符。
新用户按文档走会去做 -buildmode=c-shared,产物新内核根本不加载。

README.md / README_EN.md:
- 设计要点补子进程架构段(三面通信、崩溃自愈、真热重载)
- 代码结构 plugin/ 描述:.so 动态加载器 → 子进程加载器
- 项目状态补 v1.0.0 条目(6 类缺陷 + 实测数字),v0.9.0 标注 ABI 已退场
- 新增「下载」章节:三变体对照 + 各平台包格式 + macOS 限制

assets/docs/{zh,en}/ARCHITECTURE.md:
- 四种加载方式表:外部 .so/C ABI → 外部子进程/握手+stdio JSON-RPC
- 加载流程改写为 exec.Command → 继承 fd → 握手 → init → start
- 内置 vs 外部对照表 7 行更新
- 新增「子进程插件的三个通信面」小节,含每个面的选择理由

assets/docs/{zh,en}/OVERVIEW.md:插件系统段落改写

deploy/ 发布脚本三处回归(v0.7.2 的 7f08f3c 把 package/ 移到
deploy/packaging/ 使目录深度 1→2,但没改相对路径,此后两个版本
的发布都没有二进制资产):
- build.sh:.syso 按目标平台 hide/restore(trap 兜底),恢复
  windows 目标的 CXX,arm64 刻意不带 CXX
- installer.nsi:5 处 ..\build → ..\..\build,PRODUCT_VERSION 可注入
  (原先硬编码 0.8.0)
- homeagent.spec:server 变体补装 waiter(control-server 声明了 CLI 却没装)

deploy/scripts/upload_assets.py:release 资产上传(两步签名 URL → OBS
PUT)。放 deploy/scripts/ 而非 scripts/,因为后者在 .gitignore 里。
支持 GITCODE_REPO/ASSET_DIR 环境变量以复用于 SDK 仓。
2026-09-03 19:26:17 +08:00
7f08f3ca09 v0.7.2: 根目录清理 + Agent 心跳重构 + 内嵌 ONNX 模型
- 根目录清理: branding/docs/knowledge -> assets/, package/tools/deploy -> deploy/
- meta.go: Version 0.7.2, SDKCompatibleVersion 语义改为最高兼容
- Makefile: 版本回退 0.7.2
- registry.go: 系统提示词改用 meta.Version 格式化
- Agent 心跳: reorgGraph 拆分为三个独立循环(archive/merge/review),各自可配间隔
- GraphDB: 新增 sentences 表 + 关系句子溯源 + ClearSentenceID + CleanupOrphanedSentences
- Knowledge: 支持词嵌入向量化器
- NLP 四阶段流水线: Parse -> Extract -> Verify -> Fuse + SentenceRef
- 移除远程 HTTP 解析器(remote_parser.go)
- 新增内嵌 ONNX 模型(vocab + dep_parser.onnx):
  +build onnxruntime: 全量 ONNX Runtime 推理
  !build onnxruntime: 内嵌词表规则式降级解析器
- config: core.agent.onnx_model_path 替代 dep_parser_url
2026-07-28 09:56:26 +08:00