Paseo 项目 QA 指南:以“四问门槛“驱动多平台 Agent 编排产品的质量把关
2026/9/21 2:13:14 网站建设 项目流程

【免费下载链接】paseo

Orchestrate multiple coding agents from desktop and mobile

项目地址:https://gitcode.com/gh_mirrors/pa/paseo
点击查看免费下载

本文是 Paseo 仓库开发流程的核心质量规范(对应 docs/qa.md)。Paseo 是一个同时覆盖桌面端(macOS / Windows / Linux / Electron)与移动端(iOS / Android / Web)的多 Agent 编排产品,其质量体系围绕四个问题展开:功能是否真的好用、是否引入回归、是否覆盖所有受影响的平台、自动化测试是否真实有效。读完本文,你将掌握 Paseo 评审每一个 Pull Request 时使用的证据标准、平台覆盖矩阵、性能回归验证方法,以及"真实测试优先于 Mock"的自动化覆盖底线,并能直接落地到自己的变更提交中。

一、四问门槛:QA 是 Paseo 产品开发的最大瓶颈

Paseo 明确把 QA 视为产品开发的主要瓶颈,并为此设定了四条硬性门槛。每一个 Pull Request 都必须为它触及的问题提供证据,没有证据的 PR 会被直接关闭

  1. Does it work well?功能是否真正好用?
  2. Does it regress anything else?是否让其他功能回退?
  3. Was it tested on every platform it affects?是否在它影响到的每一个平台上测试过?
  4. Is there automated coverage, and is that coverage real?是否有自动化覆盖,且该覆盖是否真实有效?

这四问不是抽象口号,而是评审动作的判定标准:变更触及哪一问,就必须为该问提交对应证据。对于插件变更,还要先在 docs/plugins.md 中核对 SDK 导入边界,并把边界测试与两个运行时加载器(index.server.ts子进程与index.client.tsx客户端)一并纳入证据。

二、什么是"证据":可以被别人复核的东西

证据的定义是**"别人能看得见的东西"**,而不是你的自我声明。可接受的证据形式包括:

  • 你运行过的命令及其输出(原样粘贴)
  • 你新增的测试及其结果
  • 改动前后的截图
  • 交互过程录制的视频
  • 日志、请求、响应

规范要求按需脱敏、保留技术细节。特别值得注意的是:如果工作是 Agent 完成的,必须提交它的原始输出——因为摘要会丢失别人核验所需的关键细节。

三、第一问:Does it work well——能用但不流畅就不算完成

一个"能用"但卡顿、布局跳动或偏移两个像素的功能不算完成。对 UI 而言,这意味着视觉、交互和性能三方面都要匹配设计系统,设计基准是 docs/design.md。

最常见的两类问题被单独点名:

  • 布局漂移(Layout shift):内容随数据到达而跳动、徽章出现时行高变化、首次渲染时面板重排。要求观察慢网速和首屏加载时的表现,而不是只在一切预热之后检查。
  • 对齐(Alignment):元素对齐到"字形"而不是"触摸目标"。具体对齐规则见 docs/design.md 的第 8 节——行首图标、标题、尾部按钮标签必须落在同一导轨(rail)上,对齐的是墨迹而非内边距。

设计规范在仓库里有完整的落地实现:token 全部收敛在 packages/app/src/styles/theme.ts,按钮统一使用<Button>(packages/app/src/components/ui/button.tsx),状态徽章统一使用<StatusBadge>(packages/app/src/components/ui/status-badge.tsx)。QA 的第一问实际上要求你对照这些组件基线而非"手搓样式"来验收。

四、第二问:Does it regress anything else——组合式架构下的回归面

Paseo 天生是**可组合(composable)**的设计,这意味着你的改动旁边就是你没碰过的功能。规范给出的两个典型例子:

  • 改动 Agent 列表,会影响归档(archive)、子 Agent(subagents)和标签(tabs);
  • 改动 Git 操作,会影响 worktree 和检出流程(checkout flow)。

因此要求"打开周围的表面"逐一验证。性能也是回归的一部分:Paseo 是 Expo React Native 应用,不是套了原生壳的 Web 应用——你写的不是 CSS,样式解析方式不同,各平台的性能特征也不同。在桌面 dev build 里"秒开"的交互,在手机上可能明显变慢。

如果改动触及热路径——终端(terminal)、消息列表(message list)、Git 轮询(git polling)——必须提交改动前后的数字。终端流水线及其基准见 docs/terminal-performance.md,渲染器与 React 性能分析见 docs/development.md。

以终端热路径为例,docs/terminal-performance.md 给出了完整的测量手段,QA 报告可以直接引用:

  • Node-only 基准(快速迭代)npx tsx scripts/benchmark-terminal-latency.ts,启动隔离 daemon(全新PASEO_HOME、随机端口,绝不用 6767),测量回显延迟百分位、突发抖动与快照次数,结果写入/tmp/paseo-terminal-bench/
  • 浏览器性能 spec(用户感知路径)PASEO_TERMINAL_PERF_E2E=1门控下的 packages/app/e2e/browser/terminal-performance.spec.ts 与 terminal-keystroke-stress.spec.ts;
  • 生产观测:grepdaemon.log中的ws_runtime_metrics,读取eventLoopDelaybufferedAmount——eventLoopDelay是"daemon 是否繁忙"的 ground truth,其 p99/max 直接约束终端帧的最坏延迟。

五、第三问:Every platform it affects——平台覆盖矩阵

你的代码不只运行在你测试过的平台上。同一套应用会发布到iOS、Android、浏览器 Web,以及 macOS / Windows / Linux 上的 Electron,daemon 则运行在三大桌面操作系统外加 Docker。

规范不要求你拥有每一台设备,但要求你明确说出覆盖了什么。每个 PR 都应填写这张平台矩阵:

PlatformTestedNotes
iOS
Android
Web
Desktop macOS
Desktop Windows
Desktop Linux

合理范围内尽量安装环境:一台机器上的 iOS 模拟器 + Android 模拟器就能覆盖大部分平台差距,参见 docs/development.md 与 docs/android.md。

两个跨平台注意点:

  • 代码在哪里运行:平台门控规则见仓库根目录 CLAUDE.md 的 platform gating 一节。反复踩坑的领域各有专门文档:docs/hover.md(hover 在原生端不触发)、docs/unistyles.md(Unistyles 与 Reanimated 冲突)、docs/floating-panels.md(浮动面板与键盘布局)、docs/mobile-panels.md(移动端面板)、docs/expo-router.md(路由与启动恢复)。
  • 版本漂移:App 与 daemon 是独立发布的,版本会双向漂移(新 App 配旧 daemon、旧 App 配新 daemon 都会真实存在)。这套契约独立成文,见 docs/protocol-compatibility.md——协议层变更必须证明"六个月前的 App 仍能解析这个消息、六个月前的 daemon 仍能满足这个 App"。

从源码结构看,客户端能力由packages/client包统一声明(packages/client/src),App、CLI、插件继承这些默认值,这正是"每平台行为一致"的实现基础:能力检测只发生在一处,下游读取的都是干净形状。

六、第四问:Automated coverage that means something——测试只有在验证真实事物时才算数

测试只有在真实执行时才构成证据:

  • Bug 修复需要回归测试,且该测试必须因为报告的原因在旧代码上失败
  • 功能需要走用户或调用方实际使用的同一接口的测试;
  • Web 流程需要真实的 Playwright 运行,而不是 mock 出来的近似;
  • Agent provider 工作需要能判断"它成功了"的人对着真实 provider 手动验证——fixture 和 mock 只能证明 fixture 能解析,仅此而已。

"把行为 mock 掉、断言内部实现、或者能在坏代码上通过的测试"都是在宣称并不存在的覆盖。完整标准见 docs/testing.md(含如何在不冻结机器的情况下跑测试套件)。

6.1 测试只有两种形状

docs/testing.md 明确:仓库里每个测试只属于两种形态之一——

  1. 带端口与适配器的单元测试(unit tests with ports and adapters):生产代码通过注入接口接收真实世界依赖(DB、HTTP、CLI 进程、时钟、随机性、文件系统、其他模块),测试用与生产模块同目录的、类型化的内存 fake 来接线。禁止vi.mockvi.hoistedvi.spyOn自身导出、JSDOM、@testing-library组件挂载、RN 测试渲染器、全局猴子补丁与 fake-server fixtures。一旦需要其中任何一样,说明生产模块缺少端口——先修接缝,再对着 fake adapter 写测试。
  2. 真实端到端测试(real end-to-end):真实 daemon、真实网络、真实浏览器(App 代码用 Playwright),或真实隔离的服务器实例(daemon 代码)。没有 JSDOM,没有 mock 传输。

介于两者之间的东西——JSDOM 里的组件测试、mock 被测模块的 vitest 测试、断言私有状态的测试——被明确判定为"正在被淘汰的废料"。

6.2 测试文件后缀即分类

Vitest 按后缀识别测试归属,后缀决定了它属于哪个类别、在哪条流水线运行:

SuffixWhat it isWhere it runs
*.test.ts(x)单元测试——纯、快、无 daemonnpm run test:unit
*.posix.test.ts需要 POSIX 专属行为的单元测试单元测试,Windows 上跳过
*.browser.test.ts需要真实浏览器(DOM)的 App 测试npm run test:browser(Vitest browser 模式,Playwright provider,headless Chromium)
*.e2e.test.ts针对真实 daemon 的端到端测试npm run test:e2e
*.real.e2e.test.ts命中真实 provider(Claude/Codex/Copilot/OpenCode/Pi)的 E2E,需在packages/server/.env.test配置凭据npm run test:integration:real/test:e2e:real
*.local.e2e.test.ts需要本地专属资源的 E2Enpm run test:integration:local/test:e2e:local

浏览器 Playwright spec 位于 packages/app/e2e/browser/,桌面 Playwright 与真实 Electron E2E 位于 packages/desktop/e2e/,两套共享的 harness 代码在 packages/app/e2e/support/。App 侧命中真实 provider 的 spec 用*.real.spec.ts后缀,默认浏览器 project 会忽略该后缀,因此 CI 无需 provider 凭据也能全绿——真实 provider 冒烟测试必须放在*.real.e2e.test.ts,即使有环境变量保护也不能降级到*.test.ts

6.3 驱动真实 daemon:ad-hoc daemon 测试

"真实 daemon"如何落地?docs/ad-hoc-daemon-testing.md 提供了隔离进程内 daemon 测试 harness,不触碰 6767 端口的常驻 daemon。要点(仅供测试代码使用,产品启动路径必须走scripts/supervisor-entrypoint.ts):

import os from "node:os"; import path from "node:path"; import { mkdir, mkdtemp, rm } from "node:fs/promises"; import pino from "pino"; import { createPaseoDaemon } from "./bootstrap.js"; import { DaemonClient } from "./test-utils/daemon-client.js"; const logger = pino({ level: "warn" }); const paseoHomeRoot = await mkdtemp(path.join(os.tmpdir(), "paseo-test-")); const paseoHome = path.join(paseoHomeRoot, ".paseo"); await mkdir(paseoHome, { recursive: true }); const staticDir = await mkdtemp(path.join(os.tmpdir(), "paseo-static-")); const daemon = await createPaseoDaemon( { listen: "127.0.0.1:0", // OS 分配空闲端口 paseoHome, corsAllowedOrigins: [], hostnames: true, mcpEnabled: false, staticDir, mcpDebug: false, agentClients: {}, agentStoragePath: path.join(paseoHome, "agents"), relayEnabled: false, relayEndpoint: "relay.paseo.sh:443", appBaseUrl: "https://app.paseo.sh", }, logger, ); await daemon.start(); const target = daemon.getListenTarget(); const port = target!.type === "tcp" ? target!.port : null; const client = new DaemonClient({ url: `ws://127.0.0.1:${port}/ws`, appVersion: "0.1.70", }); await client.connect(); await client.fetchAgents({ subscribe: {} }); // ... do your testing ... await client.close(); await daemon.stop(); await rm(paseoHomeRoot, { recursive: true, force: true }); await rm(staticDir, { recursive: true, force: true });

运行方式:npx tsx packages/server/src/server/your-script.ts。常用测试工具位于 packages/server/src/test-utils/,如vitest-setup.ts统一加载.env.test并设置PASEO_SUPERVISED=0、禁用 Git/SSH 交互提示。

该文档还总结了多条实战 gotcha,写测试时可直接引用:

  1. appVersion 门控 provider 可见性:daemon 对未携带appVersion >= 0.1.45的客户端隐藏非 legacy provider(claude/codex/opencode 之外的),DaemonClient默认不发版本号,所以 ACP 类自定义 provider 在快照里不可见,必须显式传appVersion
  2. provider 快照是异步的:首次getProvidersSnapshot()大概率返回status: "loading",要轮询等待目标 provider 就绪;
  3. 多数操作前必须fetchAgents():缺了这次握手,get_providers_snapshot_request之类的消息会静默挂起;
  4. 永远用listen: "127.0.0.1:0":让 OS 分配端口,硬编码端口会与常驻 daemon 或其他测试冲突;
  5. 脚本必须放在packages/server/src/:测试工具通过 TypeScript 项目做相对导入;
  6. 失败也要清理:用 try/finally 保证 daemon 停止、临时目录删除;
  7. ACP provider 会拉起真实进程:probe 模型与模式需要二进制在 PATH 上,探测可能耗时 5–15 秒。

6.4 移动端测试:Agent Device 与 Maestro

移动端 QA 的主格式是Agent Device.ad脚本(docs/mobile-testing.md):Agent 交互式发现可用流程、保存成功命令,replay runner 在本地或 CI 执行同一份"打字计划"。录制流程的典型命令:

agent-device open sh.paseo.debug \ --platform ios \ --session terminal-author \ --save-script ./packages/app/e2e/mobile/agent-device/terminal.ios.ad agent-device snapshot -i --session terminal-author agent-device press 'id="workspace-header-menu-trigger"' --session terminal-author # Continue the flow and verify its result with wait/get/is/find. agent-device close --session terminal-author

运行整套移动套件:npm run test:e2e:mobile。最小的可读示例见 packages/app/e2e/mobile/agent-device/native-terminal-basic.ios.ad 与 native-terminal-basic.android.ad。遗留的 Maestro 流程在 packages/app/maestro/(含可复用子流程 packages/app/maestro/flows/),可通过agent-device test <path> --maestro执行其受支持子集作为迁移路径。移动端 QA 的核心主张与第四问完全一致:takeScreenshot是证据不是断言,断言必须用waitgetisfind;选择器优先基于稳定的 app ID(testID/nativeID),不要用文本匹配。

6.5 桌面端:浏览器捕获 harness 与打包冒烟

桌面端的真实-Electron 验证路径是浏览器捕获 harness(docs/browser-capture-harness.md),它验证单元测试看不到的 compositor 行为:驻留 automation<webview>的生产停车状态、停车 guest 可绘制且有可拷贝的视口帧、首次呈现前的 1280x800 逻辑像素默认值、capturePage与 CDP 全页截图在停车状态返回真实像素等。运行:

npm run capture-harness --workspace=@getpaseo/desktop

而打包后的桌面冒烟测试则是生产启动路径的外部观察者(docs/testing.md 的 Packaged desktop smoke 一节):harness 用隔离的 user data 与 daemon 状态启动打包应用,通过 Chromium 调试协议连接真实渲染器,要求同时满足"paseo://app/渲染器挂载进#root""沙箱 preload 暴露桌面桥""渲染器经正常启动 bootstrap 拉起全新桌面托管 daemon""打包 CLI 能查询该 daemon 并运行终端命令"。本地模拟:

PASEO_DESKTOP_SMOKE=1 \ PASEO_DESKTOP_SMOKE_ARTIFACT_DIR=/tmp/paseo-desktop-smoke \ npm run build:desktop -- --publish never --linux --x64 --dir

该冒烟测试有一个著名的历史教训:永远不要在 harness 里"修复"chrome-sandbox——旧版 unpacked 冒烟把它改成 4755 权限,掩盖了损坏的安装包。

七、PR 测试路由:按行为而非按包归属分配检查

PR 检查按"每个套件证明的行为"路由,配置文件是 .github/ci-paths.yml。原则是:包不继承其运行时消费者的全部测试套件——App 改动不跑 CLI 或 Electron 包装器测试,protocol 改动不跑每个 import 它的包。跨包静态兼容性属于typecheck;完整的集成覆盖在合入 main 之后及手动 CI 运行中执行。路由使用稳定的领域目录,浏览器改动选择必需的 Playwright shards,桌面改动选择既有的必需桌面任务;打包(Desktop Packages、Docker、Nix workflows)只在 main 上运行。

对 QA 的直接含义:你在 PR 里声明的证据要匹配路由到你的检查——改 App 就附上 App 的 Playwright spec 证据,改 daemon 就附上真实 daemon 的 E2E 证据,而不是用别的包的测试结果凑数。

八、本地运行建议:套件很重,不要冻住你的机器

仓库测试套件很重,批量运行会冻结机器(尤其多个 Agent 并行时)。docs/testing.md 给出明确的操作纪律:

  • 只跑你改过的文件:npx vitest run <path> --bail=1
  • 不要随意对整个 workspace 跑npm run test
  • 需要广泛扫描时重定向到文件再读:npx vitest run <path> --bail=1 > /tmp/test-output.txt 2>&1
  • 永远不要重跑另一个 Agent 已报绿的套件
  • 需要全量信心时推到 CI 看 GitHub Actions
  • 永远不要在本地跑完整 Playwright E2E 套件——交给 CI;只允许跑你改动或需要证明的定向 spec

这也是"确定性优先"的延伸:测试每次运行必须产生相同结果,不允许条件断言、时间/随机/网络抖动依赖、弱断言(toBeTruthytoBeDefined)。Flaky 测试是一个 bug——永不因为 flaky 而删除测试,而是找到方差来源(时间、随机、竞态、共享状态、非确定性输出、环境漂移)并修复它。Agent 认证交给 provider 自己处理,测试中不添加认证检查、环境变量门或条件跳过,认证失败就如实报告。

九、结语:QA 是一份证据文化

Paseo 的 QA 规范可以用一句话收束:质量把关不靠信任,靠可复核的证据。四条门槛中的每一条,都有对应的仓库内工具与文档可以落地——设计基线看 docs/design.md,热路径性能看 docs/terminal-performance.md,平台门控看根目录 CLAUDE.md,协议兼容看 docs/protocol-compatibility.md,测试标准看 docs/testing.md(含 ad-hoc daemon 测试 docs/ad-hoc-daemon-testing.md、移动端 docs/mobile-testing.md、桌面截图 harness docs/browser-capture-harness.md)。提交 PR 之前,逐条核对四问,附上别人能复核的证据——这就是 Paseo 的合格线。

【免费下载链接】paseo

Orchestrate multiple coding agents from desktop and mobile

项目地址:https://gitcode.com/gh_mirrors/pa/paseo
点击查看免费下载

相关推荐

上一篇:快速上手Stats系统监控工具:Homebrew一键安装终极指南
下一篇:攻克密钥管理难题:Vault RESTful API实战指南与最佳实践

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询