Skip to content

Draft: isolated macOS onboarding and multi-account QA experience - #393

Draft
cyq1017 wants to merge 13 commits into
onboarding-multi-account-v2from
qa/onboarding-experience
Draft

Draft: isolated macOS onboarding and multi-account QA experience#393
cyq1017 wants to merge 13 commits into
onboarding-multi-account-v2from
qa/onboarding-experience

Conversation

@cyq1017

@cyq1017 cyq1017 commented Jul 28, 2026

Copy link
Copy Markdown

请先审核,暂不要合并

这是一组用于合作者体验和评审的 macOS QA 改动,基于
onboarding-multi-account-v2。它不是发布候选版本,也不代表首次启动、
多账户、真实额度采集或生产安全已经完成验收。

我们为什么这样做

我们近期讨论的 CLIPulse 主线是:

  • 首次启动时让用户理解并选择自己实际订阅的 Coding Agent、套餐与账户;
  • 同一服务商支持 Personal / Work 等多个账户,避免额度和提醒串号;
  • 在继续讨论产品边界、首页信息密度和后续功能前,让团队先体验真实 UI;
  • 团队体验时不能读取或修改任何人的生产偏好、Keychain、Helper、StoreKit
    或 Supabase 状态。

因此本 PR 没有再做一套静态设计稿,而是在现有 macOS UI 上增加一个独立、
可重复体验的 CLIPulse QA 运行环境。

本 PR 做了什么

  • 新增 CLIPulse QA Xcode scheme 和 Debug QA configuration;
  • 使用独立 app/helper bundle ID、ad-hoc 本地签名和固定 QA home;
  • 为 QA runtime 建立 fail-closed capability contract;
  • 隔离偏好设置和 Keychain namespace;
  • 阻止 QA 模式触发生产 telemetry、StoreKit、Helper、Widget、Supabase、
    live collector 和相关持久化副作用;
  • 注入不含凭据的固定示例账户:
    • Codex Personal / Work
    • Claude Personal / Work
    • Gemini Personal
  • 完成本地模式后进入现有 demo dashboard,便于连续体验;
  • 增加 QA runtime、seed、cloud configuration、side-effect policy 等测试;
  • 增加人工体验清单:
    docs/qa/macos-onboarding-multi-account-checklist.md

关键设计取舍

  1. 复用真实 UI,不做另一套 mock app。
    这样合作者看到的导航、首次启动和多账户交互更接近后续产品。
  2. QA 与 production 用显式 capability contract 隔离。
    不是到处添加松散的 if isQA;条件不满足时进入 quarantine/fail-closed。
  3. 只 seed 元数据,不 seed credential。
    示例数据没有 API key、cookie、真实 account ID 或生产同步 owner。
  4. 本 PR 叠在 onboarding-multi-account-v2 上。
    它是该功能分支的安全体验层,不应直接对 main 审核或合并。

如何体验

  1. Xcode 打开 CLI Pulse Bar/CLI Pulse Bar.xcodeproj
  2. 选择 CLIPulse QA scheme;
  3. destination 选择 My Mac
  4. 确认 Run arguments:
    • CFFIXED_USER_HOME=/private/tmp/clipulse-qa-home
    • CLIPULSE_QA_RESET_ON_LAUNCH=0
  5. 运行后点击 macOS 菜单栏中的 CLIPulse 图标;
  6. docs/qa/macos-onboarding-multi-account-checklist.md 体验并记录问题。

请勿在 QA app 输入真实邮箱、密码、OTP、API key、cookie 或服务商凭据。

本次推送前验证

  • git diff --check origin/onboarding-multi-account-v2...HEAD:通过;
  • gitleaks 扫描 13 个提交、约 150.69 KB:未发现泄漏;
  • QA/隔离/订阅/Widget 定向 Swift 测试:87 tests,0 failures;
  • 本地 macOS QA app 曾完成 ad-hoc build 和启动检查。

构建仍会显示仓库现有的 Swift 6 concurrency warnings。本 PR 不把这些 warning
视为已解决,也不据此声称 release readiness。

本 PR 没有验证

  • 真实 Codex、Claude、Gemini 额度、token 或费用准确性;
  • Supabase 登录、云同步、pairing 或生产 backend;
  • 生产 Keychain access group、App Group 或正式签名行为;
  • Helper 安装、IPC、开机启动;
  • StoreKit 购买、恢复与 entitlement;
  • iOS、watchOS、Widgets、Live Activities;
  • 通知送达、模型晴雨表、额度重置预报;
  • notarization、TestFlight、App Store 或正式发布。

希望合作者重点审核

  • 首次启动的信息量、套餐/账户选择顺序是否合理;
  • Personal / Work 多账户的识别和控制是否清楚;
  • Local Only 与 Cloud Sync 的边界是否足够明确;
  • QA runtime 的 fail-closed 与副作用隔离是否可信;
  • 哪些信息应该留在首页,哪些应该进入二级页面;
  • 下一阶段应该先修产品体验,还是先补真实 provider/account 验证。

请把结论分为:

  • 必须修复后才能继续;
  • 产品边界需要共同决定;
  • 可以作为后续迭代;
  • 仅 QA harness 问题。

@JasonYeYuhe

Copy link
Copy Markdown
Collaborator

你好 @cyq1017 👋 —— 这条不是 review 意见,是一个合并前必须先解决的编号冲突,提前告诉你免得你后面白改。

问题

这个分支里的 backend/supabase/migrate_v0.70_provider_accounts.sql,和 main 上已有的 migrate_v0.70_device_app_version.sql 撞了同一个编号

关键在于:main 那个已经跑在生产库上了(devices.app_version + devices.collector_status,7 月 27 日 apply)。所以不是"谁先谁后"的问题 —— 生产已经认了那个 v0.70。

两个不同的迁移共用一个编号,会毁掉"到底哪些跑过"这个唯一记录:以后问"v0.70 跑了吗",答案变成"哪个 v0.70?"。而 Postgres 两个都能正常 apply,不会报任何错 —— 所以这个问题通常要到几个月后出事故时才被发现,那是最不想遇到无法回答的问题的时刻。

需要你做的

把你这个改名成 migrate_v0.72_provider_accounts.sql(main 上 v0.71 也占了),同时更新:

  • backend/supabase/tests/migrate_v0.70_provider_accounts.test.sql
  • backend/supabase/tests/migrate_v0.70_provider_accounts.concurrent.sh
  • 文件内注释里提到 v0.70 的地方

顺带一提

#394 加了 scripts/check_migration_numbers.sh + 一个 CI job,以后这类撞号会直接让构建变红,不用靠人眼。合并后你这条分支的 CI 会红,改完编号就绿。

那个 PR 还新增了 CLAUDE.md(Claude Code 会在会话开始时自动加载,之前仓里只有 AGENTS.md,所以 Claude 每次都是空着开工的),里面写了这条规则:编号绝不复用,包括只存在于未合并分支上的编号 —— 并行开发时两个会话各自去取"下一个可用编号",正好就是这个坑。

另外提醒一件事

这个分支基于的 main 已经往前走了不少 —— 昨天合了 #387 #388 #389 #390 #391 #392,其中 #388#392 大改了 DataRefreshManagerAppStateProviderCollector(新增了 readiness 协议要求,120 个采集器都受影响)。你这边也动了这几个文件,rebase 时冲突面积会比较大,越早处理越省事。

你的 PR 正文写了「请先审核,暂不要合并」,所以我没有合它,只是把编号这件事先说一声。

JasonYeYuhe added a commit that referenced this pull request Jul 29, 2026
…394)

`main` carries `migrate_v0.70_device_app_version.sql`, already applied to
production. PR #393 independently added `migrate_v0.70_provider_accounts.sql`.
Different schema, same number, neither author in a position to know.

Two migrations sharing a number destroys the only record of what has actually
run: "did v0.70 run?" becomes "which v0.70?". Postgres applies both without
complaint, so the question only gets asked months later, during an incident.

Three layers, because the first two are advice and advice gets missed:

- `scripts/check_migration_numbers.sh` — fails on any duplicate, names both
  files, and prints the next free number. Verified both ways: passes on `main`
  (71 migrations), and reddens with exit 1 when the real #393 collision is
  reproduced locally.
- Wired into swift-ci as its own job, next to the helper guards. The
  container-touch guard sat unwired for months and caught three real holes the
  first time anyone ran it — a guard nothing calls is not a guard.
- Written into AGENTS.md (Codex et al.) and a new CLAUDE.md (Claude Code loads
  it automatically at session start; the repo only had AGENTS.md, so Claude
  sessions were starting blind). CLAUDE.md points at AGENTS.md as the single
  source of truth rather than forking the guidance.

The rule as documented: never reuse a number, **including one only used on an
unmerged branch** — parallel work is normal here, and two sessions each taking
"the next number" is precisely the failure. If your branch collides with one
that has landed on `main`, renumber yours; `main`'s has usually already run
against production.

The guard's own find/xargs pipelines use `-print0`/`-0`: the repo path contains
a space, and the first version cheerfully reported a file named "cli".

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants