Skip to content

feat(account): one participant list, and a dialog to make an account in - #61

Merged
smileygames merged 5 commits into
mainfrom
issue-59-one-list
Aug 23, 2026
Merged

feat(account): one participant list, and a dialog to make an account in#61
smileygames merged 5 commits into
mainfrom
issue-59-one-list

Conversation

@smileygames

@smileygames smileygames commented Aug 23, 2026

Copy link
Copy Markdown
Member

Closes #59

名簿と端末リストを一つにし、行にアカウントの操作を載せた。種別ごとに分かれ、起動していないアカウントも最初から並ぶ。アカウントの作成・編集・削除は同一 webview 内のモーダルへ移し、決定と取消を持たせた。

変更の順序

  1. protocol 4 → 5 と種別353520b)— hello / room_join に任意の account_id を足し、Accountkinduser / ai)を足した。
  2. 一つのリストとモーダル2bdf3a2)— 画面側。id が載ったことで名簿とアカウント一覧が結べる。
  3. 要求仕様と READMEc9e77e6
  4. 起動直後の描画281ef4d)— リストを config だけから描く。
  5. 本人の種別521831a)— 本人のアカウントを user から変えられないようにした。

運ぶだけである

アカウント id は席に載って名簿で返るだけであり、判定には使っていない。自分の発言の抑止(Fanout.origin)、名簿の鍵(RoomInner.participants)、Participant.ownspeaker の刻印(joined_as)はいずれも接続のままである(#39 / #40 / #47)。id が無い接続も参加者として扱う——helloPULLCEPT_ACCOUNT_ID が無ければキーごと省き、テストがその省略を検査している。

判断を要する点

  • タイトルバーの名前・色の欄を外した。 完了条件は「画面の本人が種別 user のアカウントとして扱われる」であり、本人がアカウントになった以上、同じ 2 値を change で保存する欄がタイトルバーに残るのは、この issue が閉じている分裂そのものになる。本人の名前と色は行の「編集」から直す。移行は localStorage の名前と色をその新しいアカウントの属性にするだけで、以後どちらのキーも書かない。
  • アカウントを持たない接続のグループを「ゲスト」とした。 種別ではなく宣言の不在である。接続の種類から種別を推測しないという制約の裏返しであり、推測しない以上、宣言の無い相手には宣言の無い置き場が要る。
  • user のアカウントをランチャの選択肢に出さない。 start_session も拒否する(そちらが権威)。拒否が唯一の知る手段になるのを避けている。
  • 削除を 2 クリックにし、window.confirm をやめた。 feat(account): give each account its own terminal and a way to end it #57 が終了について書いた理由がそのまま当たる。window.confirm はこのアプリから消えた。
  • 走る行の表示を折り返しに変えた。 モーダルには一行のランチャ行に無かった縦の余裕があり、切れていた末尾はアプリが統合した channel エントリ——表示する理由そのものである。

対象外

ミュートと複数部屋は issue のとおり触っていない。design/ の canvas は #46 の担当であり、この PR では触っていない(差はさらに増えた)。

確認

npm run build / npm run sidecar:check / npm run sidecar:test / cargo check / cargo testmcp-config / room-floor)はローカルで通っている。リストとモーダルの見た目は dev サーバ上で light / dark 両方の算出値を確認した(名前が参加者の色で出ること、オフラインが色を保ったまま薄くなり点が輪郭になること、264px で横に溢れないこと、モーダルが viewport に収まること)。実機での操作は未確認であり、要求仕様の「未実装」節にそう書いた。

🤖 Generated with Claude Code

Claude Lin & Lay added 4 commits August 23, 2026 23:58
…count

protocol を 4 から 5 へ上げ、`hello` と `room_join` に任意の
`account_id` を足した。部屋は席に載せて名簿で返すだけであり、判定には
一切使わない。自分の発言の抑止・名簿の同一性・`speaker` の刻印はいずれ
も接続で決まったままである(#39 / #40 / #47)。運ぶ理由は画面側にある
——アカウント一覧と部屋の名簿を、名前ではなく id で突き合わせられる。
名前で結ぶ形は #40#53 が却下しており、リストが二つに割れていた直接
の原因がこれである(#57)。

アカウント id は任意である。持たない接続も参加者であり、部屋はアカウン
トの存在を前提にしない。サイドカーは `PULLCEPT_ACCOUNT_ID` が無ければ
キーごと省く。

あわせて `Account` に種別(`user` / `ai`)を足した。作成時の宣言であり、
接続の種類から推測しない——別クライアントから来た人間を、部屋は
セッションと同じ種類の接続としてしか見られないためである。既存の config
は `ai` を既定として読む。当時保存できたアカウントは全て CLI の起動
レシピだったので、これは fallback ではなく移行である。種別 `user` の
アカウントの起動は `start_session` が拒否する。人間は起動するものでは
ない。

#59
… a dialog

名簿と端末リストを一つにした。部屋が運ぶようになったアカウント id で
突き合わせているので、行は「誰が居るか」と「その相手に何ができるか」の
両方に答えられる。二つに割れていたのは `Participant` が id を持たず、
名前でしか結べなかったためである(#40 / #53 が却下した形)。

行は作成時に宣言した種別で分かれ、見出しが種別名と件数を示す(`user — 1`
/ `AI — 2`)。アカウントを持たない接続は宣言が無いので「ゲスト」に入る
——接続の種類から種別を推測しない。名前は参加者ごとの色で表示し、オフラ
インは色を保ったまま薄くし、ドットを白抜きにする。色はアカウントの同一性
を担っているため、居ないだけで別人に見えてはならない。

行にアカウントの操作が乗る。編集はモーダルを開き、終了は #57 の 2 段階
(arm)をそのまま保つ。起動していないアカウントに端末の操作は出ない。

アカウントの作成・編集・削除をモーダルへ移した。欄の `change` では保存
しない。フォームは下書きを持ち、決定で初めてアカウント一覧へ入る。+ は
空のフォームを開くだけであり、取消は新規でも編集でも何も残さない。削除は
終了と同じ 2 クリックとし、`window.confirm` をやめた(#57 と同じ理由)。

画面の本人を種別 user のアカウントにした。#53 が保留にした判断であり、
本人が行を持てなかったことがリストの分裂の一因でもある。移行は
`localStorage` の名前と色をそのアカウントの属性にするだけである。
タイトルバーの名前・色の欄は外した。同じ 2 値を編集する面が二つ並ぶのは、
この issue が閉じている分裂そのものだからである。

ランチャ行に残したのはアカウントの選択と参加のみ。名前・色・作業ディレク
トリ・起動オプションと、実際に走る行の表示はモーダルへ移した。表示は
説明する欄の隣にあり、モーダルには行の無かった縦の余裕があるので、
省略記号で切らずに折り返す——切れるのはアプリが統合した channel エントリ
であり、そこが見せる理由そのものである。

#59
要求仕様に反映した。部屋プロトコルへ `hello` / `room_join` の
`account_id` と protocol 5 を足し、運ぶ理由(画面側の突き合わせ)と、
運ぶだけであること(名簿の鍵・自分の発言の抑止・`speaker` の刻印は接続
のまま)を分けて書いた。

参加者パネルの節を「リストは一つである」に書き直し、二つに割れていた
経緯と、種別ごとのグループ・件数・オフラインの見え方・行に乗る操作を
記した。端末の列の節はここへ畳んだ。

アカウントの節に種別を足し、「人間はアカウントではない」を「画面の本人は
種別 user のアカウントである」に置き換えた。#53 が保留にした判断であり、
「決まっていないこと」の表から外して「決まったこと」へ移した。モーダル
(決定と取消、2 クリックの削除、ランチャ行に残すもの)も同節に書いた。

README も同じ範囲で直した。ウィンドウが開くこと、決定するまで保存され
ないこと、リストが一つで種別ごとに分かれることを操作の順に書いている。

#59
起動していないアカウントが、部屋が答える前から並ぶようにした。以前は
最初の描画が席の読み取り(`refreshSeats`)に乗っており、そこが失敗する
と `参加者なし` のまま残った。並ぶことは一度でも起動したかどうかに依ら
ない、という #59 の条件をそのまま満たす位置へ移した。

席の読み取りが失敗したときも描画するようにした。失敗しているのはその
一つの値であり、前回の答えを保つことと、その間に動いた他のものを描かない
ことは別である。

#59
@smileygames smileygames self-assigned this Aug 23, 2026
本人のアカウントの種別を `user` から変えられないようにした。変えられると
本人が AI の見出しの下に並び、その名前で CLI を起動する選択肢が出る——
そういうものは一つも無い。

#59

@smileygames smileygames left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

セルフレビュー(auto モード / 人間チェックなし)

完了条件の照合

#59 の完了条件 結果
リストが一つ 満たす
稼働中の行に 終了、arm を維持 満たす
起動していないアカウントも起動直後から並ぶ 満たす。config から描く
種別で分かれ、数が読める 満たす(user — 1 / AI — 2 / ゲスト — n
種別は作成時に選ぶ、推測しない 満たす
画面の本人が種別 user のアカウント 満たす
モーダルで作成・編集・削除 満たす
モーダルに決定と取消、取消で何も残らない 満たす。下記
フォーカスが外れただけでは保存されない 満たす
ランチャ行は選択と参加のみ 満たす
hello にアカウント id、Participant が持つ、protocol 5 満たす
id を持たない接続も参加者 満たす
抑止と名簿の同一性が接続で判定されている 満たす。下記
グループ見出しが種別名と件数 満たす
オフラインが色を保ったまま薄く 満たす(opacity 0.55、白抜きドット)

「運ぶが判定しない」を親側で監査した

本 issue で最も壊れやすい制約なので、報告ではなくコードで確認した。

room.rsaccount 出現箇所は全 30 行、いずれも保存・直列化・getter・正規化のみ。判定に使っている箇所は無い。同一性の四点はすべて接続のまま。

判定 実装
名簿の同一性 participants: BTreeMap<String, Seat>(origin キー)
自分か他人か own: origin == room.local_origin
自分の発言の抑止 fanout.origin == own_origin
speaker の刻印 joined_as(接続に紐づく)

フロントの account === は 1 箇所、リストの突き合わせのみ(src/main.ts:594)。

コードが規律を明文化している点も評価する。

refusing a duplicate account belongs to the launcher (…) would be treating the account as the identity.

部屋が重複アカウントを拒否しないという判断まで書かれている。拒否は席(#53)の仕事であり、部屋がやればアカウントを同一性として扱ったことになる。制約の意図を理解している。

モーダルの決定/取消

draft はアカウント本体ではなく複製であり、決定 まで一切書かない。取消 は id すら消費しない。#59 が足した「モーダルにしただけでは直らない」部分が塞がっている。

種別 user の起動拒否

UI で隠すだけでなく session.rs で拒否している。理由もコードに書かれている。

Refused here rather than only hidden from the launcher, so the screen is not the only thing standing between a user account and a spawned claude.

画面を唯一の防壁にしない形であり、妥当。

issue に無い判断(3 件、いずれも是認する)

  1. タイトルバーの 名前 / 色 を削除。 完了条件が本人を user アカウントにする以上、同じ対を編集する change 保存の面を残せば、この issue が閉じようとしている分裂を小さく再生産する。旧 localStorage の値は一度だけ読んで移行し、以後書かない。妥当。
  2. アカウント id を持たない接続を「ゲスト」でまとめた。 種別ではなく種別の不在。代替は接続の種類からの推測であり、issue が禁じている。妥当。
  3. 削除を 2 段階 arm にし、window.confirm をアプリから排除。 #57 の理由付け(ホストの応答に依存する二つの誤り方)がそのまま当たる。削除はモーダルへ移る過程で書き直されており、便乗ではない。妥当。

検証

CI(check / CI)いずれも 521831a で pass。親側で room.rsaccount 全出現、同一性四点、protocol 定数、user 起動拒否、draft の意味論、リスト突き合わせを確認した。

実装側はスクリーンショットを取れない環境のため、計算済みスタイルで視覚条件を検証したと報告している。実機は未確認で、docs の未実装節に記載済み。阻却事由としない。

#60 への影響

タイトルバーから 名前 / 色 が消えた。#60(チャット文字サイズ)で「ヘッダは #59 と場所を取り合う」として置き場所を保留にしていたが、その競合は解消した。 #60 はヘッダに操作を置ける。

リリース種別

minor と判定する。protocol 4 → 5、画面構成の変更、アカウントに種別が加わる。構造変更かつ user/system observable。

自己レビュー通過。auto モードのため人間チェックはなく、このままマージへ進む。

@smileygames
smileygames merged commit 6f50497 into main Aug 23, 2026
2 checks passed
@smileygames
smileygames deleted the issue-59-one-list branch August 23, 2026 15:29
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.

feat(account): one participant list, and a dialog to make an account in

1 participant