# Goblin 当前 PR 第三轮代码审查报告

- 审查范围：`origin/main...HEAD`
- 分支：`feat/issue-280`
- HEAD：`d8dd7719`
- 审查方式：只读静态审查，覆盖前端状态同步、服务端生命周期以及 terminal/session 并发边界
- 未执行：未修改仓库代码，未运行测试、typecheck 或任何 check

## 结论

本轮确认 1 个仍未解决的 P1 问题。此前报告中的远端 Git capability downgrade 问题已经正确修复。

## Finding

### [P1] 同一窗口内切换回 Git 状态界面时可能永久显示旧数据

涉及位置：

- `src/web/repo-data-query.ts:588-605`
- `src/web/runtime/AppRuntimeProjectionProvider.tsx:44-55, 133-178`
- `src/web/components/workspace-pane/WorkspacePane.tsx:365-376, 554-597`

#### 根因

`useRepoWorktreeStatusReadModel()` 将 worktree status 查询设置为：

```ts
staleTime: Number.POSITIVE_INFINITY
```

查询挂载时的强制刷新已经被移除。当前新增的 invalidation 只覆盖以下边界：

- 当前 workspace 或 workspace runtime 发生变化；
- 浏览器窗口重新获得 focus；
- document 从 hidden 恢复为 visible；
- 页面从 bfcache 恢复。

Git pane/tab 的激活本身没有刷新或 invalidation 边界。

#### 触发场景

1. 用户打开一个 Git workspace，worktree status 首次读取并缓存；
2. 用户切换到 Goblin 内置 terminal；
3. 用户在 terminal 中修改文件、执行 `git checkout`，或创建/删除 worktree；
4. 用户直接点击同一窗口内的 status、changes、dashboard 或 branch navigator；
5. 窗口没有失焦，workspaceId 和 workspaceRuntimeId 也没有变化；
6. status 查询仍被视为永久 fresh，不会发起新的读取。

保持 Goblin 窗口焦点时，由其他进程修改仓库也存在相同问题。

#### 用户影响

界面可能持续展示旧的：

- dirty/clean 状态；
- change count；
- 当前分支；
- worktree 列表和 worktree 元数据。

除非之后发生 workspace 切换、窗口 focus/visibility 变化或应用已知写操作发布 invalidation，否则旧快照可能一直保留。

#### 建议修复方向

在真正消费 worktree status 的界面进入激活状态时建立明确刷新边界，例如：

- status/changes pane 被激活；
- dashboard 或 branch navigator 重新成为当前可见视图；
- 从 terminal pane 切换回依赖 Git status 的 pane。

当前 `AppRuntimeProjectionProvider` 中的 focus、visibility 和 persisted pageshow 刷新可以保留，它们适合负责应用恢复场景，但不能替代 pane 激活刷新。

应继续使用现有的 canonical React Query status projection，避免增加第二份缓存、额外同步状态或 application-layer 状态镜像。

建议补充回归用例：缓存初始 status 后，在 workspace/runtime 和 window focus 均不变化的情况下，从 terminal 切换到 status/changes，断言 status 查询会重新读取。

## 其他复核结果

- 远端 Git capability downgrade 修复已通过静态复核：cleanup、probe 和 lifecycle 位于同一串行提交边界，异常时能够回滚。
- Terminal session 创建、关闭、恢复及旧 runtime 隔离未发现新的高可信问题。
- Pane tabs reconciliation 与 runtime membership 清理未发现新的高可信问题。
