Two files, one repository
CarGuo/gsy_github_app_flutter ships 1 format across 4 indexed files. The question worth asking is whether the second one says anything the first does not.
| Dimension | Shared | Only in A | Only in B | Overlap |
|---|---|---|---|---|
| Sections | 1 | 5 | 0 | 17% |
| Commands | 1 | 9 | 0 | 10% |
| Section tags | 0 | 2 | 0 | 0% |
What each file covers
Sections
1 shared · 5 only in A · 0 only in B- − GSY GitHub App Flutter 协作说明
- − Review 规则
- − 工具选型(按可用性挑一条主路径 + 一条 fallback)
- − 真机验证专用 fixture(写死,不允许随手换)
- − 按功能分类的 fixture 表(2026-07-06 扩展)
- 允许 / 禁止的写操作清单
Commands
1 shared · 9 only in A · 0 only in B- − flutter pub get
- − dart run build_runner build --delete-conflicting-outputs
- − flutter gen-l10n
- − flutter build apk --release --target-platform=android-arm64 --no-shrink
- − flutter run
- − flutter install
- − flutter/flutter
- − flutter
- − dart-lang
- flutter analyze
Section tags
0 shared · 2 only in A · 0 only in B- − testing-strategy
- − git-pr
Line diff
CarGuo/gsy_github_app_flutter · AGENTS.md
@@ −1 @@
1# GSY GitHub App Flutter 协作说明
2
3这是一个 Flutter GitHub 客户端,同时也是带有教学展示性质的示例工程。
4不要假设整个仓库是单一架构风格。多种状态管理方案并存是当前设计现实,不是偶然脏代码。
5
6## 进入仓库后先读
7
8在进行非微小改动前,先读这些文件:
9
101. `README.md`
112. `docs/README.md`
123. `docs/00-overview/project-map.md`
134. `docs/00-overview/roadmap.md`
145. `docs/01-architecture/app-layering.md`
156. `docs/01-architecture/state-management-matrix.md`
16
17## 工作规则
18
19- 改动尽量限制在当前功能域,不要顺手做跨模块重构。
20- 非任务明确要求时,不要迁移状态管理框架。
21- 优先遵循目标模块现有模式,而不是引入新的全局规范。
22- 未经明确允许,不得为了满足需求擅自替换模块既有框架或状态实现,即使替换后看起来更简单。
23- `*.g.dart`、多语言生成文件、env 生成文件都视为生成产物;优先重新生成,不要手改。
24- 不要提交密钥。`lib/common/config/ignoreConfig.dart` 属于本地或 CI 环境材料。
25
26## 高风险目录
27
28- `lib/app.dart`:应用根装配、导航、全局报错、Redux 和 Riverpod 混合接线
29- `lib/common/net/`:共享网络栈、拦截器、GraphQL/REST 入口
30- `lib/common/repositories/`:功能数据访问边界
31- `lib/env/`:构建期环境配置和生成文件
32- `lib/common/localization/`:ARB 与多语言生成输出
33
34## 建议修改策略
35
36- 纯 UI 任务:优先只改页面或局部 widget,不碰全局状态
37- API 任务:同时检查 `common/net` 与对应 `common/repositories`
38- 状态任务:沿用该模块当前已有状态方案,除非任务明确要求迁移
39- 配置/构建任务:同步更新 `docs/03-runbooks/` 中的操作说明
40
41## Review 规则
42
43- 中等以上改动默认使用独立 reviewer 上下文
44- 每次非微小代码改动后,默认拉起新的 reviewer subagent 或新的干净上下文审查刚刚的修改
45- author 在通过一轮新的 reviewer subagent 审查前,不应直接宣告代码任务完成
46- reviewer 不应复用 author 的完整上下文历史
47- 先看 `docs/05-ai/review-harness.md`
48- reviewer 提示模板见 `docs/05-ai/prompts/reviewer-system.md`
49- `tool/ai/build_review_bundle.ps1` 只是可选辅助,不是主流程
50
51## 本地最小验证
52
53按改动范围选择最小验证集合:
54
55- `flutter pub get`
56- `dart run build_runner build --delete-conflicting-outputs`
57- `flutter gen-l10n`
58- `flutter analyze`
59- `flutter build apk --release --target-platform=android-arm64 --no-shrink`
60
61说明:
62
63- 改模型、env、注解生成代码时跑 `build_runner`
64- 改 ARB 或本地化输入时跑 `flutter gen-l10n`
65- 改 Android 构建、依赖或运行时关键路径时跑 APK 构建
66
67## 运行时冒烟验证(强制)
68
69**"能编译过 + 装机不崩" 不算测试通过。**
70任何涉及运行时行为(UI 渲染、事件解析、状态流转、网络分支、多语言文案)的改动,
71在宣告完成前,author 必须在真机或模拟器上跑通对应改动路径,
72并把真实证据(截图 / 文案 dump / 错误日志)**以文件形式产出并写清路径**,
73禁止只凭"app 启动了、日志没红"就报完成。
74
75强制的是**证据本身**,不是具体工具。工具链按可用性挑:
76
77### 工具选型(按可用性挑一条主路径 + 一条 fallback)
78
791. **主路径 — `mcp_dart`(debug 构建、DTD 在线时首选)**
80 - `dtd` → `listDtdUris` / `connect` 建立 DTD 连接
81 - `widget_inspector` → `get_widget_tree` / `get_selected_widget` 抓真实渲染出的 widget 树
82 - `get_runtime_errors` 拉 Dart 层异常(改动前后各拉一次)
83 - `flutter_driver_command` 只在工程已引入 `flutter_driver` / `integration_test`
84 并且 `main.dart` 里显式调用 `enableFlutterDriverExtension()` 时才可用。
85 本仓库目前**未引入这套依赖**,因此该子工具默认不可用,不得作为唯一验证手段。
86
872. **Fallback — `adb`(release 构建、DTD 掉线、driver 未启用时的一等公民)**
88 - `adb devices` 确认设备可见
89 - `adb shell input tap/swipe/text/keyevent` 驱动 UI
90 - `adb exec-out screencap -p > /tmp/xxx.png` 抓真实渲染截图
91 - `adb logcat -d -s flutter` 抓 Dart 侧输出
92 - **截图文件路径必须写进完成汇报**,reviewer 需要能拿到该路径复核。
93 - 反复用到的 tap 序列必须沉淀到 [`tool/ai/smoke/`](tool/ai/smoke/),
94 不允许把已经跑通的坐标序列扔在一次对话里就丢掉。
95
963. **Web / DevTools 类改动**:用 `integrated_browser` 走同样"操作 → 截图 → 抓日志"流程。
97
98### 强制流程
99
1001. `flutter run` 或已装机的 build 起到已连接设备。
101 **重要:装机一律用 `adb install -r <apk路径>`,禁止使用 `flutter install`。**
102 原因见下方"禁止行为"条目——`flutter install` 内部会先执行 `adb uninstall`,
103 把应用数据(含 SharedPreferences 里的 `TOKEN_KEY`)一并清空,等同强制登出,
104 会直接毁掉真机 fixture 状态。
1052. 按上表挑工具组合抓证据;`mcp_dart` 不可用时直接切 `adb`,不视为破例。
1063. 走一遍改动**直接覆盖**的路径(例:改了 PR timeline 事件行 → 真的进 PR 详情页把
107 timeline 滚一遍,抓到目标文案的截图或 `get_text` 输出)。
1084. 覆盖不到的分支(例:`base_ref_force_pushed` 真机上罕见)必须在完成汇报里
109 **显式列为已知缺口**,不能糊成"通过"。稀有分支覆盖率无法靠真机保证时,
110 优先考虑加模型层单测 + 真实 JSON fixture 补齐。
111
112### 分级要求(避免形式主义)
113
114| 改动类型 | 最低证据要求 |
115|---|---|
116| 纯模型 / 纯工具函数 | `flutter analyze` + 单测(若 test 目录已存在);无需截图 |
117| UI 渲染 / 文案 / 事件行 | 至少 1 张真机截图 + `get_runtime_errors` 或 `logcat` 空异常 |
118| 关键路径(登录 / 网络栈 / 根装配 / 状态边界) | 主路径截图 + 至少 1 个失败/边界分支的证据 |
119
120### 完成汇报三段式(必填)
121
122**看代码**:改了哪些文件、哪些函数、为什么这么改。
123**看编译**:`flutter analyze` / `build_runner` / `gen-l10n` 的产物结论。
124**看运行**:设备 id、所用工具组合(mcp_dart 或 adb)、**截图文件绝对路径**、
125`get_runtime_errors` 或 `logcat` 结果、无法覆盖的分支列表。
126
127三段任一缺失 = 任务未完成。
128
129### 禁止行为
130
131- ❌ 只跑 `flutter analyze` 就报"测试通过"
132- ❌ 把"app 启动到首页"当成本次功能验证
133- ❌ 让用户手动操作 UI 代替 author 自测(除非物理上无法自动化,且已说明原因)
134- ❌ 拿"日志里没 Exception"当作行为正确的证据
135- ❌ 只把截图放在自己上下文里而不写路径,导致 reviewer 拿不到证据
136- ❌ **使用 `flutter install` 装机**:该命令内部走 `adb uninstall <package>` +
137 `adb install`,会把 `/data/data/<pkg>/` 下所有数据(含 SharedPreferences 里的
138 `TOKEN_KEY`)一起抹掉,等同把用户从 fixture 账号强制登出。
139 正确姿势:`flutter build apk --release --target-platform=android-arm64 --no-shrink`
140 后走 `adb install -r <apk 路径>`(`-r` 表示 reinstall,保留 app 数据)。
141 历史教训:2026 装 discussions 冒烟版本时用了 `flutter install`,导致
142 CarSmallGuo 的 gho\_ token 从设备上被清空,reviewer 侧无法直接复核,属于
143 **author 责任事故**。此后但凡装机脚本 / 命令里出现 `flutter install`,
144 reviewer 一律直接打回。
145
146## 当前已知约束
147
148- 仓库既有 `test/`(纯 Dart 单测 + widget test)也有 `patrol_test/`(Patrol 集成测试脚手架,pubspec 中已引入 `patrol`);两条测试路径并存,按改动性质挑合适档次
149- CI 使用 GitHub Actions,当前偏重构建成功
150- 项目同时使用 Redux、Riverpod、Provider、Signals
151- OAuth 登录相关流程依赖本地 `ignoreConfig.dart`
152- **GSY 是 GitHub 的只读 + 评论客户端**,不承担写 PR / 提交 review / 建仓库这类"作者行为"。冒烟或回归时**禁止通过 gh cli 或 GitHub API 新建仓库、造 PR 或提交 review**去伪造证据,一律用既有仓库里的真实数据
153
154### 允许 / 禁止的写操作清单
155
156> 状态:作者已于 2026-07-06 拍板转正,正式约束。修改需在 PR 描述里显式提出并同步 `docs/00-overview/roadmap.md §4.1`。
157
158**允许(已在做且不打算收回)**:
159
160- Issue / Comment 上加/取消 reaction
161- Issue / PR / Discussion 下发评论
162- Notify 标记已读 / 标记 done / unsubscribe
163- 关注 / 取消关注仓库(star / watch 切换)
164- **PR review thread mark as resolved / unresolved(2026-07-06 新加)**:仅操作层,不做"未 resolved thread 计数"这类仪表盘
165- **编辑自己发的 issue body / comment 内容(2026-07-06 新加)**:服务端会按作者身份校验,不会误伤他人;范围**限编辑**,不含删除
166
167**明确禁止(越界的作者行为)**:
168
169- 新建仓库 / fork 仓库
170- 新建 issue / PR / discussion
171- 提交 / dismiss review
172- 合并 PR / close issue / lock conversation
173- 修改仓库设置 / 分支保护 / webhook / secret
174- 通过 gh cli 或 GitHub API 制造冒烟数据
175- **GitHub Actions workflow rerun / cancel(2026-07-06 拍板归入禁止)**:属于仓库运维行为,GSY 不介入;用户如需 rerun 请去 GitHub 官网或官方 app
176- **Projects V2 卡片移动 / 状态字段编辑(2026-07-06 拍板归入禁止)**:等同协作作者视角编辑,与只读 + 评论定位冲突;连 Projects V2 阅读也一并搁置
177- **删除自己发的 issue / comment**:即使 API 支持,也不做——避免"误删无法恢复"的用户投诉面
178
179**判断口径**:
180
181- 判断依据是"是否让 GSY 用户在 GitHub 上产生新数据 / 修改他人内容 / 触发仓库运维",不是"API 是不是 write endpoint"
182- 若未来需要新增一条允许项,需要在 PR 描述里显式提出,并同步更新本清单与 roadmap §4.1
183
184
185## 真机验证专用 fixture(写死,不允许随手换)
186
187以下 PR/仓库是真机冒烟脚本 `tool/ai/smoke/open_pr_timeline.sh` 默认命中的证据源。改动 timeline 相关代码时,优先复用它们;只有在明确覆盖不到时才另外找 PR。
188
189- **fixture 账号**:`CarSmallGuo`(当前 adb 设备与 gh cli 登录的账号,token 有 `repo` 权限但**只做读**)
190- **fixture 仓库**:`CarGuo/gsy_github_app_flutter`(GSY 主仓库自身)
191- **fixture PR**:
192 - `#938`:Copilot 提交的 `reviewed / state=commented`,body 788 字符,同时覆盖 `ready_for_review` / `review_requested` / `assigned` / `merged` / `closed` / 未知事件兜底等新事件类型
193 - 打开方式:`bash tool/ai/smoke/open_pr_timeline.sh`(默认参数即可)
194 - 期望截图证据:`/tmp/gsy_smoke_07_issue_detail_scrolled.png` 与随后一屏能同时看到"Copilot 提交了评审意见"这一行**和其下方灰底 body 卡片**
195 - 后续若需要 approved/changes_requested body 场景,请在 `CarGuo` 名下的其它 PR 里挑选并把 PR 号写回本段落,不要造 PR
196
197### 按功能分类的 fixture 表(2026-07-06 扩展)
198
199上面 fixture PR 只覆盖 PR timeline 一个场景。为了让**开新功能前先看有没有可用测试数据**(避免走到装机验证才发现 fixture 空——Discussions 就吃过这个亏),把 GSY 各功能域可用的真实数据源固化如下。变更本表需附带该行 API 探针的实测结果。
200
201**探针复核方式**:所有 `✅` 项都用 CarSmallGuo 的 gho\_ token 在 `2026-07-06` 实测过;每半年可用 [docs/00-overview/roadmap.md §3.5 探针结果快照](file:///d:/workspace/project/gsy_github_app_flutter/docs/00-overview/roadmap.md) 那批命令重跑一次防止过时。
202
203**Fixture 优先级**:主仓 [CarGuo/gsy_github_app_flutter](https://github.com/CarGuo/gsy_github_app_flutter) > CarGuo 其他仓库 > CarSmallGuo 数据 > 外部真实仓库(`flutter/flutter` / `defunkt` 等,**必须标注为"外部妥协项"**)。**禁止造数据**同 §允许 / 禁止的写操作清单。
204
205| 功能域 | 首选 fixture | 备注 |
206|---|---|---|
207| PR timeline 词典化事件 | 主仓 `#938` | 见上文,已固化 |
208| PR review thread(line-level comment) | 主仓 `#938`(2 条:`android/app/build.gradle` L41 / L84 by Copilot) | 探针实测 |
209| Issue assignee 挂件 | 主仓 `#938`(assignees=`CarGuo,Copilot`) | 主仓 issue 只有 #938 有 assignee,其余是 (none) |
210| Issue 长 timeline / 分页 | 主仓 [`#13`](https://github.com/CarGuo/gsy_github_app_flutter/issues/13) | README 明示"所有运行问题请点这里" |
211| Issue comment reactions | 主仓 [`#643`](https://github.com/CarGuo/gsy_github_app_flutter/issues/643) | README 里的"登录失败"高流量 issue |
212| Release 详情 / reactions | 主仓 `releases`(`8.0.0` 已在真机日志出现) | 本轮真机 `versionName 8.0.0` |
213| Compare 视图 | 主仓 `423c762...bf557aa`(本轮实际 commit) | |
214| Contributors / Stargazers / Watchers | 主仓(★15461) | |
215| Repo Language 分布 / Community Health | 主仓(Dart+Java+ObjC+Kotlin,含 LICENSE / README) | |
216| Repo Branches 切换 | 主仓多分支 | |
217| Repo Fork 网络事件流 | 主仓 `/networks/CarGuo/gsy_github_app_flutter/events` | |
218| Repo Milestones | ⚠️ **主仓无**(探针 count=0)→ 外部妥协项 `flutter/flutter` | |
219| Repo Topics chip | ⚠️ 需重跑探针 → 若空退到 `flutter/flutter` | |
220| User Pinned Repositories | CarGuo(GSYVideoPlayer / gsy\_github\_app\_flutter / GSYGithubAppCompose / GSYGithubAPP / GSYGithubAppKotlin / gsy\_flutter\_book) | 探针实测 6 个 pinned |
221| User 贡献日历 | CarGuo(活跃开发者 calendar 稠密) | |
222| User Following/Followers 交集 | CarGuo × CarSmallGuo | 天然双账号 |
223| User 公共 Gists | ⚠️ **CarGuo 无**(探针 count=0)→ 外部妥协项 `defunkt`(3 条非空) | |
224| Org 详情页 / Org 事件流 | 外部妥协项 `flutter` / `dart-lang`(CarGuo 是个人账号,非组织) | |
225| Notifications 仓库级筛选 | 主仓(CarSmallGuo 30 条 subscribed 都指向主仓) | |
226| Notifications reason chip | ⚠️ CarSmallGuo 当前 reason 单一(`subscribed x 28 / manual x 2`)→ 需 mention / review\_requested 场景时另找 | |
227| Search Labels | 主仓 `repository_id=142308181`(本轮真机日志已确认) | |
228| Search Commits / Topics | 全站搜索无需锁 fixture | 主仓也在结果集 |
229| Rate Limit 诊断 | 当前 token 自查(无需 fixture) | 本轮实测 core 4997/5000 |
230
231
232
233
234
CarGuo/gsy_github_app_flutter · lib/common/net/AGENTS.md
@@ +1 @@
1# 网络层协作说明
2
3这个目录承接全局共享网络能力,是高风险区域。
4这里的改动通常会影响多个页面和 repository。
5
6## 修改前先确认
7
8- 这是协议层问题,还是某个功能模块自己的展示问题?
9- 改动是否应该优先收敛在 repository,而不是直接改网络底层?
10- 是否会同时影响 REST、GraphQL、拦截器或响应转换?
11
12## 工作规则
13
14- 不要把页面定制逻辑塞进共享拦截器
15- 改公共请求头、token、错误处理时,预期会影响全局
16- 改 `graphql/` 时,同时检查对应 repository 和模型
17- 改 `transformer`、`interceptors` 时,优先做最小改动
18
19## 最低验证
20
21- `flutter analyze`
22- 至少手工验证一个相关功能页面
23- 若改动影响认证或公共响应格式,额外验证登录或高频页面加载
24
@@ −1 +1 @@
1−# GSY GitHub App Flutter 协作说明
1+# 网络层协作说明
22
3−这是一个 Flutter GitHub 客户端,同时也是带有教学展示性质的示例工程。
4−不要假设整个仓库是单一架构风格。多种状态管理方案并存是当前设计现实,不是偶然脏代码。
3+这个目录承接全局共享网络能力,是高风险区域。
4+这里的改动通常会影响多个页面和 repository。
55
6−## 进入仓库后先读
6+## 修改前先确认
77
8−在进行非微小改动前,先读这些文件:
8+- 这是协议层问题,还是某个功能模块自己的展示问题?
9+- 改动是否应该优先收敛在 repository,而不是直接改网络底层?
10+- 是否会同时影响 REST、GraphQL、拦截器或响应转换?
911
10−1. `README.md`
11−2. `docs/README.md`
12−3. `docs/00-overview/project-map.md`
13−4. `docs/00-overview/roadmap.md`
14−5. `docs/01-architecture/app-layering.md`
15−6. `docs/01-architecture/state-management-matrix.md`
16−
1712 ## 工作规则
1813
19−- 改动尽量限制在当前功能域,不要顺手做跨模块重构。
20−- 非任务明确要求时,不要迁移状态管理框架。
21−- 优先遵循目标模块现有模式,而不是引入新的全局规范。
22−- 未经明确允许,不得为了满足需求擅自替换模块既有框架或状态实现,即使替换后看起来更简单。
23−- `*.g.dart`、多语言生成文件、env 生成文件都视为生成产物;优先重新生成,不要手改。
24−- 不要提交密钥。`lib/common/config/ignoreConfig.dart` 属于本地或 CI 环境材料。
14+- 不要把页面定制逻辑塞进共享拦截器
15+- 改公共请求头、token、错误处理时,预期会影响全局
16+- 改 `graphql/` 时,同时检查对应 repository 和模型
17+- 改 `transformer`、`interceptors` 时,优先做最小改动
2518
26−## 高风险目录
19+## 最低验证
2720
28−- `lib/app.dart`:应用根装配、导航、全局报错、Redux 和 Riverpod 混合接线
29−- `lib/common/net/`:共享网络栈、拦截器、GraphQL/REST 入口
30−- `lib/common/repositories/`:功能数据访问边界
31−- `lib/env/`:构建期环境配置和生成文件
32−- `lib/common/localization/`:ARB 与多语言生成输出
33−
34−## 建议修改策略
35−
36−- 纯 UI 任务:优先只改页面或局部 widget,不碰全局状态
37−- API 任务:同时检查 `common/net` 与对应 `common/repositories`
38−- 状态任务:沿用该模块当前已有状态方案,除非任务明确要求迁移
39−- 配置/构建任务:同步更新 `docs/03-runbooks/` 中的操作说明
40−
41−## Review 规则
42−
43−- 中等以上改动默认使用独立 reviewer 上下文
44−- 每次非微小代码改动后,默认拉起新的 reviewer subagent 或新的干净上下文审查刚刚的修改
45−- author 在通过一轮新的 reviewer subagent 审查前,不应直接宣告代码任务完成
46−- reviewer 不应复用 author 的完整上下文历史
47−- 先看 `docs/05-ai/review-harness.md`
48−- reviewer 提示模板见 `docs/05-ai/prompts/reviewer-system.md`
49−- `tool/ai/build_review_bundle.ps1` 只是可选辅助,不是主流程
50−
51−## 本地最小验证
52−
53−按改动范围选择最小验证集合:
54−
55−- `flutter pub get`
56−- `dart run build_runner build --delete-conflicting-outputs`
57−- `flutter gen-l10n`
5821 - `flutter analyze`
59−- `flutter build apk --release --target-platform=android-arm64 --no-shrink`
60−
61−说明:
62−
63−- 改模型、env、注解生成代码时跑 `build_runner`
64−- 改 ARB 或本地化输入时跑 `flutter gen-l10n`
65−- 改 Android 构建、依赖或运行时关键路径时跑 APK 构建
66−
67−## 运行时冒烟验证(强制)
68−
69−**"能编译过 + 装机不崩" 不算测试通过。**
70−任何涉及运行时行为(UI 渲染、事件解析、状态流转、网络分支、多语言文案)的改动,
71−在宣告完成前,author 必须在真机或模拟器上跑通对应改动路径,
72−并把真实证据(截图 / 文案 dump / 错误日志)**以文件形式产出并写清路径**,
73−禁止只凭"app 启动了、日志没红"就报完成。
74−
75−强制的是**证据本身**,不是具体工具。工具链按可用性挑:
76−
77−### 工具选型(按可用性挑一条主路径 + 一条 fallback)
78−
79−1. **主路径 — `mcp_dart`(debug 构建、DTD 在线时首选)**
80− - `dtd` → `listDtdUris` / `connect` 建立 DTD 连接
81− - `widget_inspector` → `get_widget_tree` / `get_selected_widget` 抓真实渲染出的 widget 树
82− - `get_runtime_errors` 拉 Dart 层异常(改动前后各拉一次)
83− - `flutter_driver_command` 只在工程已引入 `flutter_driver` / `integration_test`
84− 并且 `main.dart` 里显式调用 `enableFlutterDriverExtension()` 时才可用。
85− 本仓库目前**未引入这套依赖**,因此该子工具默认不可用,不得作为唯一验证手段。
86−
87−2. **Fallback — `adb`(release 构建、DTD 掉线、driver 未启用时的一等公民)**
88− - `adb devices` 确认设备可见
89− - `adb shell input tap/swipe/text/keyevent` 驱动 UI
90− - `adb exec-out screencap -p > /tmp/xxx.png` 抓真实渲染截图
91− - `adb logcat -d -s flutter` 抓 Dart 侧输出
92− - **截图文件路径必须写进完成汇报**,reviewer 需要能拿到该路径复核。
93− - 反复用到的 tap 序列必须沉淀到 [`tool/ai/smoke/`](tool/ai/smoke/),
94− 不允许把已经跑通的坐标序列扔在一次对话里就丢掉。
95−
96−3. **Web / DevTools 类改动**:用 `integrated_browser` 走同样"操作 → 截图 → 抓日志"流程。
97−
98−### 强制流程
99−
100−1. `flutter run` 或已装机的 build 起到已连接设备。
101− **重要:装机一律用 `adb install -r <apk路径>`,禁止使用 `flutter install`。**
102− 原因见下方"禁止行为"条目——`flutter install` 内部会先执行 `adb uninstall`,
103− 把应用数据(含 SharedPreferences 里的 `TOKEN_KEY`)一并清空,等同强制登出,
104− 会直接毁掉真机 fixture 状态。
105−2. 按上表挑工具组合抓证据;`mcp_dart` 不可用时直接切 `adb`,不视为破例。
106−3. 走一遍改动**直接覆盖**的路径(例:改了 PR timeline 事件行 → 真的进 PR 详情页把
107− timeline 滚一遍,抓到目标文案的截图或 `get_text` 输出)。
108−4. 覆盖不到的分支(例:`base_ref_force_pushed` 真机上罕见)必须在完成汇报里
109− **显式列为已知缺口**,不能糊成"通过"。稀有分支覆盖率无法靠真机保证时,
110− 优先考虑加模型层单测 + 真实 JSON fixture 补齐。
111−
112−### 分级要求(避免形式主义)
113−
114−| 改动类型 | 最低证据要求 |
115−|---|---|
116−| 纯模型 / 纯工具函数 | `flutter analyze` + 单测(若 test 目录已存在);无需截图 |
117−| UI 渲染 / 文案 / 事件行 | 至少 1 张真机截图 + `get_runtime_errors` 或 `logcat` 空异常 |
118−| 关键路径(登录 / 网络栈 / 根装配 / 状态边界) | 主路径截图 + 至少 1 个失败/边界分支的证据 |
119−
120−### 完成汇报三段式(必填)
121−
122−**看代码**:改了哪些文件、哪些函数、为什么这么改。
123−**看编译**:`flutter analyze` / `build_runner` / `gen-l10n` 的产物结论。
124−**看运行**:设备 id、所用工具组合(mcp_dart 或 adb)、**截图文件绝对路径**、
125−`get_runtime_errors` 或 `logcat` 结果、无法覆盖的分支列表。
126−
127−三段任一缺失 = 任务未完成。
128−
129−### 禁止行为
130−
131−- ❌ 只跑 `flutter analyze` 就报"测试通过"
132−- ❌ 把"app 启动到首页"当成本次功能验证
133−- ❌ 让用户手动操作 UI 代替 author 自测(除非物理上无法自动化,且已说明原因)
134−- ❌ 拿"日志里没 Exception"当作行为正确的证据
135−- ❌ 只把截图放在自己上下文里而不写路径,导致 reviewer 拿不到证据
136−- ❌ **使用 `flutter install` 装机**:该命令内部走 `adb uninstall <package>` +
137− `adb install`,会把 `/data/data/<pkg>/` 下所有数据(含 SharedPreferences 里的
138− `TOKEN_KEY`)一起抹掉,等同把用户从 fixture 账号强制登出。
139− 正确姿势:`flutter build apk --release --target-platform=android-arm64 --no-shrink`
140− 后走 `adb install -r <apk 路径>`(`-r` 表示 reinstall,保留 app 数据)。
141− 历史教训:2026 装 discussions 冒烟版本时用了 `flutter install`,导致
142− CarSmallGuo 的 gho\_ token 从设备上被清空,reviewer 侧无法直接复核,属于
143− **author 责任事故**。此后但凡装机脚本 / 命令里出现 `flutter install`,
144− reviewer 一律直接打回。
145−
146−## 当前已知约束
147−
148−- 仓库既有 `test/`(纯 Dart 单测 + widget test)也有 `patrol_test/`(Patrol 集成测试脚手架,pubspec 中已引入 `patrol`);两条测试路径并存,按改动性质挑合适档次
149−- CI 使用 GitHub Actions,当前偏重构建成功
150−- 项目同时使用 Redux、Riverpod、Provider、Signals
151−- OAuth 登录相关流程依赖本地 `ignoreConfig.dart`
152−- **GSY 是 GitHub 的只读 + 评论客户端**,不承担写 PR / 提交 review / 建仓库这类"作者行为"。冒烟或回归时**禁止通过 gh cli 或 GitHub API 新建仓库、造 PR 或提交 review**去伪造证据,一律用既有仓库里的真实数据
153−
154−### 允许 / 禁止的写操作清单
155−
156−> 状态:作者已于 2026-07-06 拍板转正,正式约束。修改需在 PR 描述里显式提出并同步 `docs/00-overview/roadmap.md §4.1`。
157−
158−**允许(已在做且不打算收回)**:
159−
160−- Issue / Comment 上加/取消 reaction
161−- Issue / PR / Discussion 下发评论
162−- Notify 标记已读 / 标记 done / unsubscribe
163−- 关注 / 取消关注仓库(star / watch 切换)
164−- **PR review thread mark as resolved / unresolved(2026-07-06 新加)**:仅操作层,不做"未 resolved thread 计数"这类仪表盘
165−- **编辑自己发的 issue body / comment 内容(2026-07-06 新加)**:服务端会按作者身份校验,不会误伤他人;范围**限编辑**,不含删除
166−
167−**明确禁止(越界的作者行为)**:
168−
169−- 新建仓库 / fork 仓库
170−- 新建 issue / PR / discussion
171−- 提交 / dismiss review
172−- 合并 PR / close issue / lock conversation
173−- 修改仓库设置 / 分支保护 / webhook / secret
174−- 通过 gh cli 或 GitHub API 制造冒烟数据
175−- **GitHub Actions workflow rerun / cancel(2026-07-06 拍板归入禁止)**:属于仓库运维行为,GSY 不介入;用户如需 rerun 请去 GitHub 官网或官方 app
176−- **Projects V2 卡片移动 / 状态字段编辑(2026-07-06 拍板归入禁止)**:等同协作作者视角编辑,与只读 + 评论定位冲突;连 Projects V2 阅读也一并搁置
177−- **删除自己发的 issue / comment**:即使 API 支持,也不做——避免"误删无法恢复"的用户投诉面
178−
179−**判断口径**:
180−
181−- 判断依据是"是否让 GSY 用户在 GitHub 上产生新数据 / 修改他人内容 / 触发仓库运维",不是"API 是不是 write endpoint"
182−- 若未来需要新增一条允许项,需要在 PR 描述里显式提出,并同步更新本清单与 roadmap §4.1
183−
184−
185−## 真机验证专用 fixture(写死,不允许随手换)
186−
187−以下 PR/仓库是真机冒烟脚本 `tool/ai/smoke/open_pr_timeline.sh` 默认命中的证据源。改动 timeline 相关代码时,优先复用它们;只有在明确覆盖不到时才另外找 PR。
188−
189−- **fixture 账号**:`CarSmallGuo`(当前 adb 设备与 gh cli 登录的账号,token 有 `repo` 权限但**只做读**)
190−- **fixture 仓库**:`CarGuo/gsy_github_app_flutter`(GSY 主仓库自身)
191−- **fixture PR**:
192− - `#938`:Copilot 提交的 `reviewed / state=commented`,body 788 字符,同时覆盖 `ready_for_review` / `review_requested` / `assigned` / `merged` / `closed` / 未知事件兜底等新事件类型
193− - 打开方式:`bash tool/ai/smoke/open_pr_timeline.sh`(默认参数即可)
194− - 期望截图证据:`/tmp/gsy_smoke_07_issue_detail_scrolled.png` 与随后一屏能同时看到"Copilot 提交了评审意见"这一行**和其下方灰底 body 卡片**
195− - 后续若需要 approved/changes_requested body 场景,请在 `CarGuo` 名下的其它 PR 里挑选并把 PR 号写回本段落,不要造 PR
196−
197−### 按功能分类的 fixture 表(2026-07-06 扩展)
198−
199−上面 fixture PR 只覆盖 PR timeline 一个场景。为了让**开新功能前先看有没有可用测试数据**(避免走到装机验证才发现 fixture 空——Discussions 就吃过这个亏),把 GSY 各功能域可用的真实数据源固化如下。变更本表需附带该行 API 探针的实测结果。
200−
201−**探针复核方式**:所有 `✅` 项都用 CarSmallGuo 的 gho\_ token 在 `2026-07-06` 实测过;每半年可用 [docs/00-overview/roadmap.md §3.5 探针结果快照](file:///d:/workspace/project/gsy_github_app_flutter/docs/00-overview/roadmap.md) 那批命令重跑一次防止过时。
202−
203−**Fixture 优先级**:主仓 [CarGuo/gsy_github_app_flutter](https://github.com/CarGuo/gsy_github_app_flutter) > CarGuo 其他仓库 > CarSmallGuo 数据 > 外部真实仓库(`flutter/flutter` / `defunkt` 等,**必须标注为"外部妥协项"**)。**禁止造数据**同 §允许 / 禁止的写操作清单。
204−
205−| 功能域 | 首选 fixture | 备注 |
206−|---|---|---|
207−| PR timeline 词典化事件 | 主仓 `#938` | 见上文,已固化 |
208−| PR review thread(line-level comment) | 主仓 `#938`(2 条:`android/app/build.gradle` L41 / L84 by Copilot) | 探针实测 |
209−| Issue assignee 挂件 | 主仓 `#938`(assignees=`CarGuo,Copilot`) | 主仓 issue 只有 #938 有 assignee,其余是 (none) |
210−| Issue 长 timeline / 分页 | 主仓 [`#13`](https://github.com/CarGuo/gsy_github_app_flutter/issues/13) | README 明示"所有运行问题请点这里" |
211−| Issue comment reactions | 主仓 [`#643`](https://github.com/CarGuo/gsy_github_app_flutter/issues/643) | README 里的"登录失败"高流量 issue |
212−| Release 详情 / reactions | 主仓 `releases`(`8.0.0` 已在真机日志出现) | 本轮真机 `versionName 8.0.0` |
213−| Compare 视图 | 主仓 `423c762...bf557aa`(本轮实际 commit) | |
214−| Contributors / Stargazers / Watchers | 主仓(★15461) | |
215−| Repo Language 分布 / Community Health | 主仓(Dart+Java+ObjC+Kotlin,含 LICENSE / README) | |
216−| Repo Branches 切换 | 主仓多分支 | |
217−| Repo Fork 网络事件流 | 主仓 `/networks/CarGuo/gsy_github_app_flutter/events` | |
218−| Repo Milestones | ⚠️ **主仓无**(探针 count=0)→ 外部妥协项 `flutter/flutter` | |
219−| Repo Topics chip | ⚠️ 需重跑探针 → 若空退到 `flutter/flutter` | |
220−| User Pinned Repositories | CarGuo(GSYVideoPlayer / gsy\_github\_app\_flutter / GSYGithubAppCompose / GSYGithubAPP / GSYGithubAppKotlin / gsy\_flutter\_book) | 探针实测 6 个 pinned |
221−| User 贡献日历 | CarGuo(活跃开发者 calendar 稠密) | |
222−| User Following/Followers 交集 | CarGuo × CarSmallGuo | 天然双账号 |
223−| User 公共 Gists | ⚠️ **CarGuo 无**(探针 count=0)→ 外部妥协项 `defunkt`(3 条非空) | |
224−| Org 详情页 / Org 事件流 | 外部妥协项 `flutter` / `dart-lang`(CarGuo 是个人账号,非组织) | |
225−| Notifications 仓库级筛选 | 主仓(CarSmallGuo 30 条 subscribed 都指向主仓) | |
226−| Notifications reason chip | ⚠️ CarSmallGuo 当前 reason 单一(`subscribed x 28 / manual x 2`)→ 需 mention / review\_requested 场景时另找 | |
227−| Search Labels | 主仓 `repository_id=142308181`(本轮真机日志已确认) | |
228−| Search Commits / Topics | 全站搜索无需锁 fixture | 主仓也在结果集 |
229−| Rate Limit 诊断 | 当前 token 自查(无需 fixture) | 本轮实测 core 4997/5000 |
230−
231−
232−
233−
22+- 至少手工验证一个相关功能页面
23+- 若改动影响认证或公共响应格式,额外验证登录或高频页面加载
23424
