dev-manager-tauri/docs/ai-context/agent-button-system.md
lanrtop 8e13bb4cf5 docs(dev-variables/contract): 记录测试账户边界与验收证据
同步 scoped MCP、Tauri DTO 契约及 V8–V11 验收状态;V7 客户端限制与人工终验继续保留。
2026-09-28 01:46:19 +09:00

208 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
version: 1.1.0
updated: 2026-09-26
usage: 炼境 agent 按钮体系的完整设计文档,供 Claude 理解体系全貌和设计意图;也是分发给子项目的方针来源
---
# Agent 按钮体系
> 炼境的核心设计理念:让 AI agent 具备无人值守执行能力的工程基础设施。
## 核心命题
> 功能只有一份实现,但有两种投影:UI 按钮是给人的,agent 按钮是同一个功能给 AI agent 的投影。
> 当 agent 按钮完备,验证环路就能在 agent 内部闭合,人不再是执行链的瓶颈。
## 双投影设计
```
功能本体(单一实现)
├── UI 按钮 → 人操作
└── agent 按钮 → agent 调用
├── 可发现(agent 知道它存在)
├── 可调用(结构化接口)
└── 边界清晰(调的是同一条路径,不是捷径)
```
"调同一条路径"是关键:agent 走的验证路径和人走的一致,终验才有意义。
## 分工重构
没有 agent 按钮时,人卡在验证环节,成为执行链瓶颈:
```
人定目标 → agent执行 → 人验证 → 人反馈 → ...(人是瓶颈)
```
有了 agent 按钮后,中间的验证环路在 agent 内部闭合:
```
人定目标 → agent执行 → agent自验(走agent按钮) → 人终验
```
人只保留两件事:
- **需求澄清**(目标定义权)
- **目标验收**(终验权)
**人在目标层,agent 在执行层,层间边界清晰,各自自洽。**
## 四层体系
### 意图层 — AGENTS.md
声明方针 + agent 按钮清单。agent 进来第一件事:知道这个项目有哪些 agent 按钮可以调用。
### 执行层 — agent 按钮本体
按项目类型就近选择载体:
| 项目类型 | agent 按钮载体 |
|---------|---------------|
| Web 服务 | HTTP API(前端按钮与 curl 调同一 endpoint,天然双投影) |
| CLI/脚本 | 命令与 npm scripts |
| 桌面应用 | 测试直接调用 command 函数 |
| UI 呈现层 | Playwright(最后手段,仅关键路径) |
### 验证层 — acceptance + 可执行断言
acceptance 是 agent 自验的唯一判断依据,必须是可执行断言:
```
❌ "功能正常运行"(描述性,agent 无法执行)
❌ "代码正确"(主观,无可执行路径)
✅ "pnpm typecheck 无报错"
✅ "cargo test 通过(src-tauri/)"
✅ "MCP tool list_projects 返回新增项目名"
✅ "pnpm test import-project 全绿"
```
最小结构:`<可执行命令>` + `<通过标准>` = 一条合格的 acceptance。
验证层的触发机制,按优先级(模型无关性递减):
| 机制 | 触发时机 | 模型无关 |
|------|---------|---------|
| git hooks(lefthook) | commit 时 | ✅ 最强 |
| CI/CD(Gitea Actions) | push 后 | ✅ |
| .claude/settings.json hooks | Claude Code 专属 | ❌ |
| AGENTS.md 约定 | 靠 agent 主动调用 | 语言约束 |
> `.claude/settings.json` hooks 是 Claude Code 专属的,Cursor / Qwen 等其他工具不会读这个文件。模型无关的验证层靠 git hooks + CI,不能靠 Claude 专属配置。
### 持久层 — 目标持久化
让 agent 跨会话续接,不靠对话记忆:
- 炼境项目:蓝图(`.blueprint/`)
- 子项目完整接入:随炼境分发的蓝图规范
- 子项目最小接入:`.agent/task.md`
蓝图在体系里的三个角色:
1. **目标的结构化载体** — 把自然语言目标翻译成带 acceptance 的可执行任务卡
2. **跨会话共享状态** — agent 跨对话续接的记忆
3. **自验的判断依据** — acceptance 字段告诉 agent "走到什么状态算通过"
## 消费者驱动验证
普通应用的验证在自身边界内,一个角色(实现者)够用。
当产品的产出要被"圈外"消费时(工具、平台、SDK、炼境这类跨 APP 产品),验证必须出圈,天然产生两个角色:
```
实现者角色 → "我跑通了"(项目内部视角)
消费者角色 → "你的产出我真的能用"(圈外消费视角)
```
两个角色博弈,才能覆盖完整目标。
**判断是否需要双角色**:你的产出,有没有圈外消费者?
| 产品类型 | 消费者在哪 | 需要几个角色 |
|---------|-----------|------------|
| 普通业务应用 | 圈内(用户即使用者) | 1 个 |
| SDK / 工具 / 平台 | 圈外(其他项目) | 2 个 |
| 炼境 | 圈外(被管理的子项目) | 2 个 |
> **验证边界要跟着目标边界走,不是跟着实现边界走。**
炼境的双角色示例:
- 实现者角色:炼境开发角度(导入新项目、跑通接入包分发流程)
- 消费者角色:被管理项目角度(接入包能否真的在子项目里用起来)
## 本地 Agent 控制面的稳定边界
炼境对 Codex、Claude 等客户端提供同一份本地能力本体,客户端插件与 UI 只是不同投影:
- MCP 仅监听 IPv4 loopback `127.0.0.1`,不以 Agent 易用性为由暴露到局域网。
- 项目使用 `/mcp/projects/<project_id>` scoped endpoint;服务端以连接 scope 为准,拒绝跨项目参数和全局管理写工具。旧 `/mcp` 仅用于兼容迁移,不扩展新写能力。
- readiness 分为 `configured → reachable → handshake → tools_ready → reload_required`。配置存在不等于当前任务已加载;停在哪层,就只修哪一层。
- `.lian-jing/context.json` 是项目身份唯一来源;Skill 和插件不复制项目身份、Gitea 凭证或 MCP 实现。
- Windows 登录自启动只服务正式安装版,默认关闭且由用户主动启用;debug 和 `target/release` 直接运行明确拒绝注册。single-instance 继续保证同一时间只有一个炼境实例。
- 日常开发优先运行 `pnpm tauri dev`,Agent 直接消费同一 loopback MCP;正式安装包只在安装、自启动、升级或发布里程碑做一次验收,不作为每次提交的前置条件。
- 开发炼境前先从托盘完全退出正式安装版;不得把正式版与 `pnpm tauri dev` 并行运行。single-instance 是运行时兜底,不替代这一开发约定。
- updater 是独立的发布能力,不属于自启动或 readiness 的完成条件。
这套 scope 是单用户本机的误操作隔离,不是多租户认证。威胁模型变化前,不向项目配置写持久 token。
项目开发变量是明确、有限的例外:Codex 项目配置只保存本机 helper 命令和项目 ID digest,随机 bearer 留在 Windows Credential Manager;helper 在连接时向 Codex 提供认证头。普通 scoped MCP 工具继续兼容无认证调用,但 `read_project_dev_variable` 与 `read_project_test_account` 在服务端验证该项目的 bearer,跨项目、全局 `/mcp`、无认证及错误认证均拒绝。同一 Windows 用户的恶意进程仍可能读取该用户可访问的凭证,本机制不声称提供同用户进程隔离;其他 Agent 客户端未验证前不承诺同等取值能力。
## 项目资源与凭证代办边界
项目开发变量由 Agent 在 scoped MCP 中登记名称和用途,人通过对应项目 UI 明确填写、修改或撤销。测试登录前 Agent 先查询非秘密需求状态:已有测试账户卡就复用;没有才以 `register_project_test_account` 登记稳定名称、目标系统、非生产环境和用途,不能通过 MCP 提交账号或密码。用户在同一张卡一次填写账号与密码;两字段作为一份结构化值原子写入 Windows Credential Manager,SQLite 仅保存非秘密元数据与随机引用。常态列表只报告待填写/已配置;`read_project_test_account` 经项目级认证后返回单张卡的账号与密码,旧的 `read_project_dev_variable` 仅返回标量,双方不能跨类型取值。结果会进入 Agent 会话,因此只允许非生产、低权限、可重置的开发数据;不替代子项目运行时 `.env` 注入,也不改变下述 Gitea/API Key 代办边界。
`get_project_resource_status(project_id)` 是同一项目绑定上的只读 MCP/Tauri 投影,只报告 Gitea PR 与 webhook 的 `configured`、`pending_migration`、`not_configured`、`unavailable` 或 `needs_repair` 及非秘密来源。旧 SQLite 凭证未迁移时只报告 `pending_migration`,不提前宣称可执行;scoped MCP 连接拒绝跨项目参数;状态不含原始凭证、凭证引用、仓库 URL 或连接串。`configured` 仅表示本机代办凭证就绪,不代表远端 Gitea、CI 或部署已验证。
Gitea PR 继续使用既有 `create_pull_request` 有界操作;Windows 本机代办凭证由 Credential Manager 保护,SQLite 只存引用及非秘密元数据。旧值在显式操作时,先在数据库同目录以 SQLite `VACUUM INTO` 生成 `dev-manager.pre-credential-migration.db`,校验完整性和当前旧值确在备份中,再按写入、读取校验、事务切换引用并清除旧列的顺序迁移;备份不可用或失败则保留旧值并报告 `needs_repair`。此备份可能含历史明文,须按原数据库同等敏感级别保护,不能因当前列清空就宣称历史明文已消失。普通 Gitea/API Key DTO 不带原始值;人的 API Key 查看与复制仍通过本机 Tauri 的显式 reveal,MCP 不暴露该入口。Gitea Actions secrets、项目运行时密钥与服务器凭证仍留在各自原用途位置;炼境不提供 `get_secret` 或任意 SSH、SQL、HTTP、部署代理。同一 Windows 用户下的进程隔离不是本方案提供的安全保证。
## production 交付观测边界
项目可自主管理 `.lian-jing/capabilities.yaml` 的 `delivery.targets.production`,声明 Gitea Actions 的**精确 status context** 与公开 HTTP JSON 版本探针。炼境只读该声明;接入包不生成或覆盖项目的 production 配置。探针不接受 URL 凭证、认证头、查询参数、非 HTTP(S) 协议或本机/内网地址;连接时过滤域名解析出的私网地址,不走环境代理、不跟随重定向,并限制请求时间与响应大小。
`get_delivery_status` 分别采集 Gitea 默认分支目标 SHA 的部署过程证据和当前服务报告的运行 SHA。只有部署 context 成功、探针健康、两个完整 SHA 相等时才报告 `deployed`。`failed` 保留实际运行版本;部署成功但版本不一致才报告 `drifted`;本次提交的部署 job 被跳过时报告 `skipped` 并保留运行 SHA,不把文档类提交误报为漂移。缺失/不可达证据明确降级。该状态仅是技术交付观测,不替代业务测试、上线决策,也不赋予炼境部署、回滚、SSH 或数据库写权限。
## 三条设计原则
辩证结论,缺一会让体系在现实中碎裂。
### 原则一:无人值守 ≠ 消灭人工介入
人工介入是设计内的降级路径,不是体系失败。体系的目标是把人从"执行路径"移到"降级路径"。
**自验失败降级约定**:
- 失败 2 次内:自行修正,继续自验
- 失败 3 次:停止执行,输出以下内容后等待人工介入:
1. 失败原因(具体报错或不通过的断言)
2. 已尝试的修正路径
3. 需要人决策的具体问题
### 原则二:框架由炼境保证,内容由子项目填
炼境能分发的是结构(AGENTS.md 模板、蓝图规范、lefthook、CI 配置),不能替子项目实现 agent 按钮。
分发的最高价值物是 **acceptance 写法规范**——让子项目知道怎么写才算可执行断言,而不是描述性语句。
### 原则三:acceptance 是体系的核心关节
体系其他部分都能降级,acceptance 不能将就。acceptance 写得可执行,自验才是真自验;写得模糊,整个环路是假闭合,无人值守名存实亡。
## 炼境自己的 Agent 按钮清单
| 能力 | 调用方式 | 通过标准 |
|------|---------|---------|
| TypeScript 类型检查 | `pnpm typecheck` | 无输出,exit 0 |
| 前端单元测试 | `pnpm test` | exit 0,无 FAILED |
| Rust 单元测试 | `cargo test`(src-tauri/ 目录) | 无 FAILED |
| MCP 工具调用 | 见 `src-tauri/src/mcp_tools.rs` 工具列表 | 返回 JSON,无 error 字段 |
| 蓝图状态读取 | 读 `.blueprint/manifest.yaml` | 文件可解析,字段完整 |
| 蓝图状态更新 | 编辑 `.blueprint/modules/<id>.md` | 文件写入成功,格式合法 |
## 分发给子项目的方案
接入包只有一档,要么接,要么不接。
```
接入包
├── AGENTS.md 模板 ← 含方针 + 按钮清单占位 + 降级约定
├── .blueprint/CONVENTIONS.md ← 含 acceptance 写法规范 + 蓝图工作流
├── lefthook.yml ← git hooks(模型无关验证层)
└── .gitea/workflows/ci.yml ← CI/CD(模型无关验证层)
```
子项目接入后需要自己填入:
- AGENTS.md 里 agent 按钮清单的具体命令和通过标准
- 任务卡 acceptance 字段的可执行断言
> 没有蓝图就没有飞轮数据,炼境对该项目的感知断链。不接入蓝图的项目不应通过炼境分发接入包,直接使用 AGENTS.md 开放规范即可。