Skip to content

fix: 詳細画面の c が無反応に見える問題と、--repo の初期タブ - #61

Merged
kukv merged 11 commits into
mainfrom
worktree-glistening-floating-perlis
Sep 7, 2026
Merged

fix: 詳細画面の c が無反応に見える問題と、--repo の初期タブ#61
kukv merged 11 commits into
mainfrom
worktree-glistening-floating-perlis

Conversation

@kukv

@kukv kukv commented Sep 7, 2026

Copy link
Copy Markdown
Owner

Phase 2 の立て直し(#59 / #60)のあとに残っていた宿題を片付ける。利用者から見える
不具合が 2 つ、コードの中だけの問題が 4 つ。実装計画は
docs/superpowers/plans/2026-09-07-phase2-followups.md

詳細画面で c が無反応に見える問題を直した

「詳細画面で c を押してもコメント欄が開かない」という報告の原因が分かった。
本文の読み込みが終わるまで c / x / v / l / a は無視されるのに、その間の
画面はスピナー 1 行だけで、無視した理由がどこにも出ていなかった。

実端末(pty)で実 API を相手に再現した結果:

  • enter の 4 秒後に押した c → 何も起きない
  • 同じ手順で 25 秒後に押した c → コメント欄が開く

断ったときに理由を 1 行出すようにした(diff が既に持っている declined と同じ流儀)。

⣾  読み込み中...
本文がまだ届いていません。少し待ってからもう一度

設計書 §3.4 は原因を「端末から届くキーイベントが "c" にならない」と推測し、
--debug-keys を足して切り分ける、としていた。実際は違ったので §3.4.1 に結論を
追記し、--debug-keys は入れていない。

--repo を渡したら Repos タブから始まるようにした

これまでは --repo kukv/octoscope を渡しても Work タブで始まっていた。spec §4 の
「起動直後は Work タブ」どおりの動作だったが、フラグを渡すのは「このリポジトリを
見に来た」という意思表示なので、spec を先に直してから Repos 開始に変えた。

カレントディレクトリの git remote から後で解決した場合はタブを移さない
その答えは盤面が出てから数秒後に届くので、見ている画面を奪うことになる。

README(en / ja)の --repo の説明も追随させた。

別の item 宛ての応答で画面が入れ替わるのを防いだ

detail.Model は item ごとに作り直されるので、利用者が別の item を開いたあとに前の
item の応答が届く
と、それが今の画面に効いてしまう。itemMsg にはこのガードが元から
あったが、7 つのメッセージに無かった。全部に ref を持たせて捨てるようにした。

メッセージ ガードが無いと
pickerCandidatesMsg 頼んでいないピッカーが、別リポジトリの候補で開く
pickerAppliedMsg / pickErrorMsg 押していない l の結果やエラーが出る
commentPostedMsg / stateChangedMsg 別の item を取り直して本文が入れ替わる
commentErrorMsg / stateErrorMsg 開いていない item の失敗が画面に出る

これで detail の非同期メッセージは全部ガードつきになった(diff は元から全部ついて
いる)。当初の指摘は pickErrorMsg 1 つだったが、同じ形の穴が 7 つあった。

読みにくかったコードとテストを直した

  • mode / phaseString() を足した(detail / diff)。テストの失敗が
    mode = 3 ではなく mode = pick と出る
  • diff.submitCancelled だけ errText を消していなかったので detail に揃えた。
    「modeView は描かないから残してよい」という言い訳コメントは消えた
  • 空振りしていたテストを直した。 Repos のシナリオ 2 本は、Repos タブが無くても
    Work の enter が同じ詳細画面を開くので通ってしまっていた。タブの前提を確認する
    ガードを足し、詳細画面の判定も #12(Repos 一覧も番号を描く)から詳細画面だけが
    描く state: open に替えた
  • 初期タブを変えたことで app のテストが新たに 3 種類の空振りを起こしたので、
    そちらも直した(シナリオ 3 本が Repos 経由になる、"2" が no-op になる、
    幅テストが Repos タブを "work" という名前で記録する)

確認

  • make check 814 テスト緑、lint 0 件。新しいテストは検証対象を壊して落ちることを
    確認済み
  • 実端末で見た。 python の pty.fork() + TIOCSWINSZ で端末を作り、実 API 相手に
    120 桁 ja の Work 盤・詳細画面・上の decline 行・--repo での Repos 開始を目視
  • 見ていないもの: 80 桁の桁ずれ(ANSI を剥がすと erase-line で判定できない。
    golden が担保)、diff 画面、Web UI 側での Pending の確認、レビューの提出と破棄。
    実在の PR に ctrl+s は送っていない

🤖 Generated with Claude Code

kukv and others added 10 commits September 7, 2026 13:51
The Work board's own enter opens the same detail view, so both scenarios
passed with no Repos tab at all. Guard the tab after 2, and the label one
also on the detail view having opened.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
l and a reach the repository, so an answer started on another item looks
plausible here: the picker would open prechecked against that item's
labels, and enter would then take them off this one. The three picker
messages now carry the ref itemMsg already did.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
detail clears errText when the submit popup closes and the diff kept it,
on the grounds that nothing under modeView draws it. That is true and it
still left the two views with different rules for the same field.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Every assertion on these two views reports the state with %v, and on a
uint8 that prints a number: "mode = 3" left the reader counting the
constants to find out which overlay had been up.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The guard's comment claimed the picker would open prechecked against
another item's labels and enter would take them off; it prechecks from
m.labels and newPicker keeps a current label that is not a candidate, so
neither happens. The cost is a picker nobody asked for, offering another
repository's candidates. The String tests claimed to catch a state added
without a name, which their fixed loop bound cannot see; they catch a
case dropped from String.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
GetItem has been measured at over twenty seconds on a cold call, and
until it answers the detail view is a spinner with no footer, so c, x,
v, l and a read as broken rather than early. They now leave the same
kind of note the diff view leaves.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Naming a repository on the command line is a statement about what the
user came to look at. A repository found later, from the working
directory, still does not move them: that answer arrives seconds after
the board is already on screen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
--repo now opens on Repos, and every one of these built its model with it:
the Work scenario was walking the Repos list, the two Repos scenarios' 2
had nothing to switch, and the width harness recorded the Repos list under
the name "work". The scenarios build without the flag, and the Repos
guard on the closing one now looks at the state line detail alone draws.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…body measured

The design's 3.4 still called the cause unknown and pointed at a
--debug-keys build; the pty run answered it, so the section now carries
the answer. The code comment claimed GetItem takes over twenty seconds,
which was never measured: what was seen is that the item was still on
its way four seconds after the key.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

This comment has been minimized.

The last four messages without a ref. Both ways out end in a refetch of
the item they were sent for, so an answer that arrives after the user
opened something else pulls the old item's body onto the screen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown

Code Metrics Report

Coverage Test Execution Time
88.5% 38s

Code coverage of files in pull request scope (90.4%, patch 94.1%)

Files Coverage Patch Coverage
internal/tui/app/app.go 95.6% 100.0%
internal/tui/detail/detail.go 92.7% 95.3%
internal/tui/detail/render.go 95.6% 100.0%
internal/tui/diff/diff.go 80.2% 81.8%

Reported by octocov

@kukv kukv changed the title fix: 繰り越し 4 件と未解決 2 件(詳細の c、--repo の初期タブ) fix: 詳細画面の c が無反応に見える問題と、--repo の初期タブ Sep 7, 2026
@kukv
kukv merged commit 8d2719b into main Sep 7, 2026
3 checks passed
@kukv
kukv deleted the worktree-glistening-floating-perlis branch September 7, 2026 05:52
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.

1 participant