首页
/ 为 LobeHub Acceptance 编写项目级验收适配层:`.agents/acceptance/PROJECT.md` 设计规范与完整模板

为 LobeHub Acceptance 编写项目级验收适配层:`.agents/acceptance/PROJECT.md` 设计规范与完整模板

2026-09-07 23:50:10作者:宣海椒Queenly

本指南讲解 LobeHub 内置 acceptance(端到端验收)技能中“项目层(project layer)”的设计与落地方法:一个与被测仓库解耦的验收 Agent,如何通过提交在仓库根目录 .agents/acceptance/PROJECT.md 中的适配器,安全、确定地启动服务、登录认证、探测状态并完成证据采集。读完本文你将掌握项目适配器的目录结构、六个固定章节的编写骨架、可直接复制的模板、首次引导(bootstrap)流程、漂移维护规则以及通用层与项目层两份“生活日志”的分工原则。

为什么需要一层“项目适配器”

LobeHub 的 acceptance 技能(版本见 SKILL.md 头部 frontmatter,当前为 0.3.0)是一个与具体项目无关的通用端到端验证工具:由 Builder Agent 负责"编写或发现计划 → 选择验证面(CLI / Web / Electron / Native / iOS)→ 逐条捕获证据 → 发布 round → 自查覆盖率"这条链路。

但"如何启动和停止被测服务、需要哪些端口与服务、认证如何工作、产品暴露哪些界面(surface)、如何一键跳入应用指定状态"——这些每个仓库都不一样,也绝不应该被技能用"猜测"的方式去推断。项目适配器(per-project adapter)正是为解决这一矛盾而生:所有项目特有细节都被收进仓库根目录的 .agents/acceptance/PROJECT.md,技能读取它,但从不猜测项目的命令

技能自身的职责与仓库的职责因此被切分为两层,这是整个设计的第一原则(见 SKILL.md 的 "Read the project layer first"):

拥有者 回答的问题
项目层(.agents/acceptance/ 被验证的仓库 how this repository is run:启动/停止命令、端口、服务、认证、surface、探针
通用层(acceptance 技能) LobeHub builtin skill what a valid round is:计划、证据、报告、round 不可变规则、硬性约束

当两者对**“如何运行”有分歧时,项目层获胜;当两者对“什么构成一个有效 round”**有分歧时,本技能(通用层)获胜。运行前两层都必须读取;不得在 PROJECT.md 已回答的启动命令、端口、认证流程上自行发明。若出现分歧,应当在运行过程中直接修复适配器,而不是绕过它。

这段"契约在技能、流程在仓库、双方互不复述"的边界,在 acceptance/index.ts 的实现注释中有更明确的表述:这一拆分取代了原先仓库内置的 agent-testing 技能——契约留在此处,仓库的流程留在彼处。配套测试 index.test.ts 也专门断言了 "routes to the project layer before touching an environment"(触及环境前先路由到项目层),验证技能正文必须包含 .agents/acceptance/PROCESS.md 与指向本适配器文档的链接。

.agents/acceptance/ 目录结构与入库约定

适配器所在的仓库目录布局如下:

<repo>/.agents/acceptance/        # 提交入库 —— 适配器与项目日志是团队资产
├── PROJECT.md                    # 适配器:命令、端口、服务、认证、界面
├── PROCESS.md                    # 可选:项目的运行流程(审批门禁、清理、发布)
├── common-mistakes.md            # 项目层生活日志(可写)
├── probe-mock-patterns.md        # 项目层生活日志(可写)
├── references/                   # 可选:项目自有的 how-to
└── scripts/                      # 可选:项目环境 / 探针 / 截图脚本

.agents/acceptance/ 必须提交入库(committed)——适配器与项目生活日志是被团队成员共享、受版本控制的资产;PROJECT.md 还可以引用 .agents/acceptance/scripts/ 或仓库任意位置的脚本。

与适配器相反,每次运行产生的报告产物不入库。原适配器文档称之为报告输出目录 .records/:报告是单次运行的临时产物,被发布到 LobeHub Acceptance 而不是提交。在当前 CLI 实现中,这些产物实际落在自动自我忽略的 .acceptances/ 目录下(见 acceptanceDir.ts):ensureAcceptanceDirIgnored.acceptances/ 内部写入一个内容为 *.gitignore,使整棵产物树(result.jsonreport.md、证据截图与 GIF 等二进制)永远不进入 git 历史,同时也绝不改写项目自身的根 .gitignore;每次 round 按 YYYYMMDD-HHMMSS-<slug> 在主题分组下分配不可变子目录(acceptanceDir.ts)。该实现注释明确指出:这与"物化技能需提交"是刻意相反的决策——技能是可供评审的团队资产,应提交;产物不是,不应提交(acceptanceDir.ts)。

PROCESS.md:可选的项目自有运行流程

一个会自我验证的仓库,往往不只是需要分享命令——它可能还要求:

  • 触碰环境前的审批门禁(approval gate);
  • 一套清理纪律(teardown discipline);
  • 明确的发布目标
  • 约定的报告目录规范

这些与命令无关、但决定"这一次运行怎么执行"的约定,放在适配器旁边的 .agents/acceptance/PROCESS.md 中。只要该文件存在,它就拥有运行流程的所有权,而 acceptance 技能只负责提供验收契约(plan、evidence、report、round)。关于"运行方式"两者冲突时以项目层为准;关于"什么是有效 round"则以技能为准。

PROJECT.md 的固定六段式骨架

PROJECT.md 永远按如下顺序包含六个章节。技能会按编号引用章节(PROJECT.md §2§3……),因此编号顺序必须保持不变:

  1. Project summary(项目概要) — 产品是什么;与测试相关的仓库布局(哪个包承载服务器、Web 应用、桌面壳、CLI)。
  2. Environment(环境) — 如何启动/停止开发环境;必需服务(数据库、缓存、队列、对象存储)及各自启动方式;如何检测"已在运行"以免一次运行覆盖用户的服务器;环境与端口如何解析(优先使用项目自身的 env 解析命令,绝不硬编码端口表)。
  3. Auth(认证) — 测试账号、种子(seeding)命令、以及按界面区分的登录态状态检查(每个界面一条命令回答"我在这个界面是否已登录?")。
  4. Surfaces(界面) — CLI / Web / Electron 哪些适用;对每个适用的界面给出:启动命令、基础 URL/端口、agent-browser 会话名(Web/Electron)、由哪些探针脚本驱动。
  5. Project probes & quick navigation(项目探针与快速导航) — 进入应用状态的快捷路径:认证探针、当前路由探针、进行中操作探针,以及 goto <route> 快速导航与值得跳转的路由清单。这是项目侧"状态自省助手"的等价物;技能用它取代手写的 store-eval 片段。
  6. Known constraints(已知约束) — 通用门禁在运行前必须知道的任何事项:某条代码路径的硬性前置服务(例如"Agent 运行需要队列服务处于启动状态")、需要各自独立安装的独立子包、仅支持 macOS 的界面,或任何一次运行必须遵守的仓库特有注意事项。

可直接复制的 PROJECT.md 模板

以下为官方模板全文,可直接作为编写起点(占位符 <...> 需按项目实际替换,不适用的界面章节删除):

# PROJECT.md — acceptance adapter for <project name>

## 1. Project summary

<One paragraph: what the product is. Then the repo layout that matters for testing —
which directory/package is the server, the web app, the desktop shell, the CLI.>

## 2. Environment

- **Start dev server:** `<command>` (base URL: `<url>`, port: `<port>`)
- **Stop dev server:** `<command>` (must stop only what this run started)
- **Required services:** <db / cache / queue / object store — with the start command
  for each, or "none">
- **Already-running detection:** `<health-check command>` — how to tell the server is
  up before starting another one.
- **Env / port resolution:** `<command or file>` — the source of truth for ports and
  URLs. Do NOT hard-code a port table; read it here.

## 3. Auth

- **Test account(s):** <how to obtain — seeded, fixture, or a real login>
- **Seeding command:** `<command>` (or "n/a")
- **Per-surface status check:**
  - CLI: `<command>` — signed-in when <...>
  - Web: `<command>` — signed-in when <...>
  - Electron: `<command>` — signed-in when <...>

## 4. Surfaces

<For each surface that applies. Delete the ones that don't.>

### CLI

- Invocation: `<how the CLI is run — from source or built binary>`
- Auth: <see §3 CLI>
- Standalone install: `<command>` or "covered by root install"

### Web

- Launch: `<dev server command>` (from §2)
- Base URL: `<url>`
- agent-browser session: `<session name>`

### Electron

- Launch: `<start command>` — CDP port `<port>`
- Stop: `<command>`
- Login persistence: <how login survives across runs>

## 5. Project probes & quick navigation

- Auth probe: `<command>` → `{ isSignedIn, userId }`
- Route probe: `<command>` → current route
- Operations probe: `<command>` → running operations
- Quick navigation: `<command> goto <route>`
- Routes worth jumping to: <list>

## 6. Known constraints

- <e.g. "agent runs require the queue service (§2) up, or the run dies before any
  real work">
- <e.g. "the desktop and CLI packages are standalone — install inside each">
- <e.g. "OS-capture surfaces are macOS-only">

几个值得注意的实操要点:

  • 第 2 节的端口解析强调"读,不要写":端口的唯一事实来源应指向项目自身的 env 解析命令或文件,而不是在适配器里维护一份会漂移的端口表。
  • 第 3 节的每界面登录态检查必须是一条可执行命令,输出能明确回答"该界面是否已登录",这是 Web/Electron 每次截图前认证门禁(auth gate)的前提(详见 auth-web.md)。
  • 第 5 节的探针(probe)是技能替代自写 store-eval 的标准手段:为认证、当前路由、运行中操作各准备一条命令,并提供 goto <route> 快速导航。探针脚本可放在 .agents/acceptance/scripts/ 或仓库任意位置。
  • 第 6 节把"通用门禁运行前必须知道的事"显式化:例如 macOS-only 的 OS 捕获面、需要独立安装的桌面/CLI 子包等,防止技能在错误的平台上做无效验证。

首次引导(First-run bootstrap):先建适配器,再跑任何验证

当仓库中不存在 .agents/acceptance/PROJECT.md 时,验收 Agent 必须在做任何其他事情之前先把它构建出来,流程分四步:

  1. 探索仓库。 阅读能揭示项目如何运行的信号:package.json scripts、README、CI 工作流(.github/workflows/**)、Makefile / Justfiledocker-compose*.yml / compose.yaml.env.example,以及任何现成的测试/开发文档。记录 dev-server 命令、所需服务、端口、认证方案与存在的界面。
  2. 按上述骨架起草 PROJECT.md,用探索结果填满每一节。对不确定的值,明确标注为猜测(guess),而不是凭空编造一条命令。
  3. 提交用户确认。 把草稿展示给用户并请求确认或修正——尤其是启动/停止命令、必需服务与认证路径。不得针对未经确认的适配器启动 dev server 或编写测试步骤。
  4. 仅在获得批准后写入 .agents/acceptance/PROJECT.md;若该目录不存在则先创建。

一个重要边界:lh acceptance install 只负责把技能文件放到 .agents/skills/acceptance/,它不做任何仓库探索。 适配器草稿需要模型参与,因此正是"第一次验证运行"这个环节完成 PROJECT.md 的引导初始化。

源码侧的 install 语义

lh acceptance install 的实现印证了上述边界(acceptanceRun.ts):

  • 它通过服务端 verify.getSkillBundle 拉取最新技能包,把 SKILL.md 与全部 resource 文件写入 <cwd>/.agents/skills/acceptance/——这是一个物化产物(materialized artifact),通过重新安装来更新、从不手工编辑,且应当提交(安装过程不会为它写入任何 ignore 条目)。
  • 已有文件存在且未传 --force 时跳过;acceptance update 语义上等价于显式 --force 强制刷新,并会删除旧 bundle 中已不存在(重命名/拆分后)的陈旧引用文件,防止旧引用继续被发现。
  • 安装同时会 linkHarnessSkills 建立各 harness 目录(如 .claude/skills)指向 .agents/skills 的相对符号链接(见 skillWiring.ts),并播种 .acceptances/.gitignore,使从未运行过的仓库在首次截图时也不会产生未跟踪噪音。
  • 只有安装技能文件这一个职责——安装完成后不会触发任何 repo 探索或 PROJECT.md 生成。

漂移规则:把适配器当作生活日志维护

把适配器当作一份持续更新的生活日志(living log):当运行中观察到的现实与之背离时(端口迁移、启动命令变化、某个服务变为必需),应当在运行过程中就地修复 PROJECT.md,而不是静默绕开它。这样下一次运行不必重新发现同一处漂移

这套"运行中修正文档"的纪律与技能正文中 "fix a divergence in the adapter during the run instead of working around it" 的规则一脉相承(SKILL.md):仓库被验证得越多,适配器越准确,后续运行的成本就越低。

两层生活日志(living logs)与单向保密规则

技能同时维护两层 common-mistakes.mdprobe-mock-patterns.md,但两者的性质完全不同:

文件位置 可写性 更新方式
通用层(generic layer) 技能源内 references/common-mistakes.mdreferences/probe-mock-patterns.md(本仓库路径为 references/ 只读 向技能源提交 PR
项目层(project layer) 仓库内 .agents/acceptance/common-mistakes.md.agents/acceptance/probe-mock-patterns.md 可写 运行中直接追加记录

原因在于:安装在消费者仓库里的通用层副本是从技能源物化而来的,对它的任何就地编辑都会在下次技能更新时丢失,因此必须通过 PR 修改技能源。而项目层是唯一允许一次运行记录项目特有经验教训的地方。运行时 Agent 会读取两层日志,但只写项目层(技能正文要求:Record new project-specific learnings in the project layer only)。技能的两份通用日志在注入方式上也与适配器不同——common-mistakes.md 需在每次标记 pass 前完整阅读其 Checklist;probe-mock-patterns.md 按标题索引只抽取本轮需要的条目(SKILL.md)。

当某条项目层记录被证明与具体产品无关时,可以将其通用化(genericize)——删掉所有项目特有名词——后通过 PR 上提(promote)到上游通用层。

这里有一条单向保密规则(Confidentiality runs one way):任何涉及项目包名、路由、schema、环境变量、服务名或业务逻辑的内容,必须留在项目层;只有把项目名词全部移除后读起来依然成立的规则,才允许被提升到通用层。这保证了通用层技能在任意仓库间流通时,不会携带任何一个具体项目的内部信息。

结语:契约与实现的边界是这套体系的核心

.agents/acceptance/PROJECT.md 的六段骨架、PROCESS.md 的运行流程所有权、首次引导的四步流程,到运行时"就地修复而非绕开漂移"的维护纪律,再到两层生活日志的单向保密规则——acceptance 项目适配层的核心思想始终一致:技能负责"什么样的验证是有效的",仓库负责"这个仓库怎么跑",二者各司其职、互不复述,项目细节永远收敛在仓库侧的可写层中。这使同一个验收技能可以被安全地复用到任意仓库,同时让每个仓库的验证行为精确、确定且可被团队评审与版本化。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.13 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
529
593
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
915
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.35 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
515
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388