Conversation
The Changes panel treated every unreadable source alike: one error Banner with Retry. A directory that is not a repository can never succeed on retry, so the shared failure surface invited a retry that could not help (apache#5940). Map the failure reasons to distinct states in SessionReviewPanel: - not_git_repository: neutral guidance (EmptyState surface, not the red Banner) naming what Changes needs, the task directory it looked at, and the next step (git init here or move the task into a repository); no Retry, since retrying cannot create a repository. - workspace_unavailable: keeps its error Banner and Retry (restoring the directory makes a retry succeed) and adds recovery guidance pointing at restore-or-relocate paths. - git_failed and unborn_repository: unchanged error Banner + Retry. - empty (no differences) and invalid_base_branch (auto-recovered in load()) stay as they were. The task directory reaches the panel through an optional `cwd` on the GitReviewReadResult failure branch; the git-review:read handler fills it from the Session's declared workspace (and from the directory the read ran in, for the other reasons). The app default workspacePath is deliberately not used — it is not the task directory. Stories: ChangesSourceNotGit now asserts guidance without Retry; new ChangesWorkspaceUnavailable covers the recovery Banner. Fixes apache#5940 Generated-by: GLM-5.3-Flash (ZCode)
Astro-Han
left a comment
There was a problem hiding this comment.
Automated review notice: This comment was posted by an automated review agent. It is not an independent human review and does not replace one.
Review of exact head 6163e59e (single commit on merge-base e57b0295). GitHub reports MERGEABLE (merge state BLOCKED). CI test was still pending when I reviewed; label passes.
No P0-P2 findings. The state split is correct.
What I checked:
- Reason routing:
not_git_repositorygets a neutral EmptyState with no Retry.workspace_unavailablegets an error Banner with recovery copy and Retry.unborn_repositoryandgit_failedkeep the old Banner and Retry.invalid_base_branchis still handled inload()(pin is dropped and the read retried) and otherwise falls through togitFailed, as before.emptyexcludes both new states, so no double rendering. cwdplumbing:readGitReviewhas a single caller (runtime-host-workspace-ipc-main.ts). Every non-ok result now carriescwd. The preload/ports passGitReviewReadResultthrough untouched, andcwdis optional on the core type, so a result without it degrades to "no path line". The renderer shows the path only for the two guidance states, and thegit_failedtest pins that.- Markup: Astryx
Bannerrendersdescriptionin a<div>andTextdefaults to<span>, so nesting the path line is valid. - Copy: zh-CN, zh-TW and en all define the three new keys.
Two P3 inline: (1) "not a repository" no longer has an in-place Retry, but its copy tells the user to run git init; (2) remote-host sessions hit an early workspace_unavailable and now get "moved/deleted, restore it" recovery copy that does not apply.
| ) : null} | ||
| {/* A source that cannot be read is a failure, not an absence — it takes | ||
| the same Banner the load error above does, not an EmptyState. */} | ||
| {guidance ? ( |
There was a problem hiding this comment.
P3: the not-a-repository state no longer has a reload affordance, but its copy suggests an in-place fix. notGitRepositoryHelp says "Initialize one here (git init)". The premise "retrying cannot turn a directory into a repository" holds only until the user does exactly that. The panel reloads on window focus/visibilitychange, on agent tool_result/complete, and on re-activation. But the workbar has a terminal tool (workbar-tool-definitions.ts, right/bottom placement), so it can sit in the bottom panel next to Changes on the right. Running git init there fires none of those triggers, and the panel stays on "not a Git repository" with no button until the user changes focus or tab. Consider keeping a low-emphasis Retry/Refresh here, or dropping the "here (git init)" wording. Note that after git init the next read becomes unborn_repository, which does show Retry.
There was a problem hiding this comment.
Addressed in 795f4c1: the guidance keeps the git-init wording and gains a low-emphasis ghost Refresh button that re-reads the source. Once git init lands, the next read reports unborn_repository, which already carries Retry.
| @@ -40,17 +40,32 @@ export function registerRuntimeHostWorkspaceIpc( | |||
| return { ok: false as const, reason: 'workspace_unavailable' as const }; | |||
There was a problem hiding this comment.
P3: this early workspace_unavailable now gets misleading recovery copy. allowLocalWorkspace is !usesHostWorkspace (runtime-host-boot.ts:1727/1763). Remote/host-workspace runtime targets therefore always return this result, with no cwd. Before this PR the panel just said "This task directory is unavailable". It now adds "may have been moved, deleted, or become inaccessible. Restore it or switch the project's working directory, then retry" plus a Retry that can never succeed, because the directory exists and the desktop host simply doesn't read it. Consider a distinct reason (or a flag) for "Changes is not available for this runtime host", or at least keep this branch out of the new guidance.
There was a problem hiding this comment.
Addressed in 0f2b62e: the early return now reports a distinct local_workspace_disabled reason (core enum + doc), rendered as a neutral "not available for this runtime host" state — no recovery guidance, no directory line, no Retry. The panel's empty and sourceError guards were extended so the new reason cannot fall into either the diff-empty or the error surface.
The workbar's terminal tool can share the screen with the Changes panel, so a reader may run `git init` right next to it. None of the panel's automatic reload triggers (window focus, visibilitychange, agent tool results, re-activation) fire while the panel keeps focus, so the guidance used to stay stuck with no way forward until the reader refocused the window. Keep the git-init guidance and add a low-emphasis Refresh that re-reads the source; once the repository appears the next read reports unborn_repository, which already carries Retry. Review feedback on apache#5963 (Astro-Han, P3: guidance state had no reload affordance despite the "Initialize one here (git init)" wording). Generated-by: GLM-5.3-Flash (ZCode)
…rkspace `allowLocalWorkspace` is `!usesHostWorkspace`, so remote/runtime-host targets always failed the git-review read before any directory was looked at, and they reported it as `workspace_unavailable`. The panel then showed the "may have been moved, deleted..." recovery guidance plus a Retry that could never succeed — the directory exists; the desktop host simply never reads it. Give the early return its own `local_workspace_disabled` reason and render it as a neutral "not available for this runtime host" state with no recovery guidance, no directory path line, and no Retry. Review feedback on apache#5963 (Astro-Han, P3: misleading recovery copy on the runtime-host early return). Generated-by: GLM-5.3-Flash (ZCode)
Astro-Han
left a comment
There was a problem hiding this comment.
Automated review notice: This comment was posted by an automated review agent. It is not an independent human review and does not replace one.
Incremental review: 6163e59e → 0f2b62e2 (two new commits, 795f4c19 and 0f2b62e2). The merge-base with main is unchanged (e57b0295), so the delta is exactly 6163e59e..0f2b62e2. GitHub reports MERGEABLE (merge state BLOCKED). CI test is still pending on this head.
Both P3s from the previous pass are resolved. No new findings.
- Not-a-repository has no reload affordance → fixed in
795f4c19. The guidance state keeps its git-init wording and now has a low-emphasis ghostRefreshbutton (session-review-panel.tsx:330-336) that callsload(). There is still noRetry, which keeps the "nothing failed" framing. The test now checks thatRetryis absent, thatRefreshis present, and that clicking it triggers a second read (reads1→2). The story asserts刷新. All three locales definerefresh. - Remote hosts got recovery advice that could never work → fixed in
0f2b62e2. TheallowLocalWorkspace === falseearly return now sends its own reason,local_workspace_disabled(runtime-host-workspace-ipc-main.ts:45, added to the core union atgit-review.ts:77). The panel shows it as a neutral EmptyState with no path line, no recovery copy and no Retry, and leaves it out of bothsourceErrorandempty, so nothing renders twice. The new test pins the absence of "may have been moved", "Task directory:", the error banner and Retry.
What I checked:
- Union consumers: a grep for the reason literals at the new head turns up only the IPC producer,
git-review-main.ts(not_git_repositoryonly), the renderer predicates and the stories. There is no exhaustive switch that the new member breaks. Preload passes the result through unchanged, and main and renderer ship in the same bundle, so there is no version-skew window. - Copy: zh-CN, zh-TW and en all define
runtimeHostWorkspaceUnavailable,runtimeHostWorkspaceUnavailableHelpandrefresh. - Refresh while loading:
isLoading={loading}handles repeated clicks.load()bumps the revision, so a stale read can't overwrite a newer one.
What I could not judge: I did not run the suite, and CI test is still pending on this head.
Summary
Fixes #5940 — the Changes (Git review) panel treated every unreadable source alike: one error Banner with Retry. Split the failure surface into the distinct states the issue asks for:
not_git_repository→ neutral guidance on the EmptyState surface (no red Banner, no Retry): what Changes needs, the task directory it looked at, and the next step (git inithere, or move the task into a repository). Retrying cannot create a repository.workspace_unavailable→ keeps its error Banner and Retry (restoring the directory makes a retry succeed) and adds recovery guidance pointing at restore-or-relocate paths.git_failed/unborn_repository→ unchanged error Banner + Retry (an unborn repository gains commits; a failed read can succeed).invalid_base_branch(auto-recovered inload()) stay as they were.The task directory reaches the panel through an optional
cwdon theGitReviewReadResultfailure branch, filled by thegit-review:readhandler from the Session's declared workspace (and from the directory the read ran in for the other reasons). The app-defaultworkspacePathis deliberately not used — it is not the task directory. No second relocation mechanism, no automaticgit init, no non-Git diff: the guidance names the existing authorities.Out of the four states, only the renderer mapping was missing —
GitReviewReadResultalready carried the five failure reasons and the copy layer already had per-reason strings; this PR separates the rendering and adds the two guidance strings plus a directory line, in all three locales (en / zh-CN / zh-TW).Verification
node --test --test-force-exit apps/desktop/dist/main/__tests__/session-review-panel-recovery.test.jsnot a Git repositoryrendered with Retry; unavailable workspace missing recovery guidance)pass 10 / fail 0(incl. guards thatgit_failed/unborn_repositorykeep Retry and thatgit_failedshows no directory line)git-review-main/session-review-base-branch/review-base-branch-preferencespackages/corefull suitenpm run test:distnpx biome format .node scripts/check-locale-hygiene.mjsnode apps/desktop/scripts/check-renderer-architecture.mjsnpm run typecheck(preload / main / renderer / storybook)Not run locally (left to CI): Playwright e2e and the live Storybook smoke — the story assertions (
ChangesSourceNotGitnow guidance-without-Retry; newChangesWorkspaceUnavailable) are covered bytypecheck:storiesand the DOM suite here.AI use
Coding, test authoring and verification runs were performed by GLM-5.3-Flash (ZCode) under human direction; the human reviewed the diff and the verification matrix.
Checklist