Why: v0.2.0 is the hard prerequisite for RDM shared work, and the release checklist referenced a stale SurfaceVersion and tag message. Evidence: SELF - scope lines are tied to merged Backend PRs (#66-#110); Backend #110 CI success; UI composite run 1369 shows 14 files/103 tests. Impact: Adds docs/records/2026-10-09-base-v0.2.0-release.md and points the compat policy and the EXT-1 proposal at the actual 2.5.0-experimental line. Tag creation and push stay with the owner (dual-key rule). Refs: Dev feature/base-v020-release; Backend #110
49 lines
4.2 KiB
Markdown
49 lines
4.2 KiB
Markdown
# EXT-1:进程内命令处理器与 owner 作用域宿主句柄(最小集)
|
||
|
||
状态:**实施中(2026-10-05)**;owner:weichen;主任务:Dev 仓 `feature/ext-1-inproc-handler`(任务卡即本提案的申请卡)。
|
||
撰写日期:2026-10-05。配套:[扩展面兼容与演进](2026-10-01-extension-compat-policy.md)、[基座路线图修正](2026-10-01-base-extension-roadmap.md)、V1.2 实施推进方案(批注 1 最小/完整集划分)。
|
||
|
||
## 1. 申请卡(compat-policy §6 四要素)
|
||
|
||
- **场景**:Agent-System-RDM 的 `rdm.ingest` 等命令经四入口(button/card/slash/chat)分发到 `cmdbus.Dispatch` 时被以 `no host handler bound` 拒绝——`Registry.AddCommand` 与 manifest `provides.commands` 只注册规格不绑处理器;进程内插件同时没有任何 owner 凭证与基座服务端回调身份(H4)。
|
||
- **希望符号**:`pkg/extension` 新增 `Request` / `Handler` / `Host`(owner 作用域宿主句柄最小集)与 `Registry.AddCommandHandler(spec, h)`;基座侧配套 `cmdbus.Bus.RegisterPluginCommand`。
|
||
- **为何现有注册点组合不出来**:`RegisterPluginCommands` 仅登记 spec;`HostClient` 走 sidecar HTTP 且需要进程内不可得的 host token;owner 作用域必须由基座在分发时构造,插件无法自造。
|
||
- **兼容**:只加符号与方法,不改既有路径语义;`SurfaceVersion` 保持 `2.0.0-experimental`,实验窗口内的接口调整以本提案为记录。
|
||
(2026-10-09 注:此后 EXT-8/9/11/12 与执行原语硬开关按 compat-policy 逐次加法升级,v0.2.0 发版时为 `2.5.0-experimental`,见 [v0.2.0 发版记录](../records/2026-10-09-base-v0.2.0-release.md)。)
|
||
|
||
## 2. 公开面变更(surface.txt 12 → 15 项)
|
||
|
||
`pkg/extension` 新增导出符号 `Handler`、`Host`、`Request`(见 `host.go`);`Registry` 接口追加 `AddCommandHandler` 方法(方法不计入快照)。
|
||
|
||
**依赖变化**:根包自此 import `agent-system-core` 类型(`KnowledgeDoc`/`RetrievalHit`/`Artifact`/`ID`),此前为零外部依赖。声明式 Go 插件的 `go.mod` 需按 compat-policy §4 模板同时 require+replace `agent-system-core`。
|
||
|
||
## 3. Host 接口(最小集)
|
||
|
||
```
|
||
PluginID() / Owner()
|
||
KVPut / KVGet // 按 pluginID+owner 隔离
|
||
Audit(action, target, evidence) // owner 名下审计事件,Actor=plugin:<id>
|
||
Complete(ctx, prompt) // 经基座 LLM 路由(owner 模型配置生效)
|
||
KnowledgeSearch(ctx, projectID, text, topK)
|
||
KnowledgeWrite(ctx, docs, embed) // Owner 强制改写为本次分发 owner;Source 空则补 plugin:<id>;
|
||
// embed=false 只写全文,embed=true 建向量(失败降级纯全文)
|
||
TaskCreate / TaskUpdate // 后台任务台账(执行体由下游自跑)
|
||
ArtifactGet / ArtifactContent // 工件只读(R1-3 ingest 读原件)
|
||
```
|
||
|
||
artifacts **写入**属完整集,R1-7 前再评估(V1.2 批注 1)。
|
||
|
||
## 4. 基座实现要点
|
||
|
||
- `cmdbus.Bus.RegisterPluginCommand(spec, h)`:登记规格(SourcePlugin)+ 绑定处理器;高危命令的内联确认卡拦截位于 handler 查找之前,插件命令天然覆盖。
|
||
- `internal/app.hostcaps`:聚合 store/检索管线/LLM 路由,同一实现同时服务 hostapi.Server 闭包与进程内 `inprocHost`(批注 1:复用 owner 作用域函数,不新造句柄)。
|
||
- `inprocHost` 每次分发按 `req.Owner` 新建,所有 store 调用以该 owner 为第一参数。
|
||
- `rag.Pipeline.IndexChunks` 自 `IndexDocument` 抽出:写全文(回填 ID)后建向量,embed 失败降级语义不变。
|
||
|
||
## 5. 验证
|
||
|
||
- cmdbus:处理器被 Dispatch 调用返回 committed;仅登记规格仍 rejected(no host handler bound);高危插件命令先确认卡后执行。
|
||
- internal/app(组合根级):两 owner 各分发一次,审计/知识/KV/任务台账各落自己 owner 名下(D8 烟测的单元级前置);`provider=hash` 档 `KnowledgeWrite(embed=true)` 写出向量行且 Owner/Source 被强制改写。
|
||
- `examples/downstream-rdm` 增加 `rdm.ping` 处理器示范(读工件元数据 + 写审计)。
|
||
- 权威验证源:CI 在 PR HEAD 上 `make test` + `make build`(.gitea/workflows/ci.yaml)。
|