Skip to content

feat(history): delete a topic from the list (topic-index crate, room_log, room.rs, session.rs, pty.rs, index.html, main.ts, styles.css, CI, docs) - #120

Merged
smileygames merged 6 commits into
mainfrom
119-topic-delete
Aug 28, 2026
Merged

feat(history): delete a topic from the list (topic-index crate, room_log, room.rs, session.rs, pty.rs, index.html, main.ts, styles.css, CI, docs)#120
smileygames merged 6 commits into
mainfrom
119-topic-delete

Conversation

@smileygames

Copy link
Copy Markdown
Member

Closes #119

トピックを一覧から消せるようにした。行の が確認のダイアログを開き、答えると
logs/main/{topic_id}.jsonl と索引の項目の両方が消え、そのトピックで走っていた
CLI セッションが終わり、開いていたトピックだった場合は部屋が新しいトピックへ移る。

保存の側は crates/topic-index/ へ出した。docs/0-requirements.md の「テストの配置」
#115 の時点で正しい形として名指し、範囲外として見送っていたものである。#119
それを load-bearing にした——索引の項目だけを消す削除は、次の読み出しの照合が黙って
元へ戻す。走らせて見るしかない性質のものであり、crate のテストの中心がそれである。

Claude Lin & Lay and others added 5 commits August 28, 2026 00:07
…es/topic-index)

索引とディレクトリの照合を `crates/topic-index/` へ出した。`docs/0-requirements.md`
の「テストの配置」が既に正しい形として名指していたもので、`AppHandle` への依存を
外せば `cargo test` の対象になる。#119 の削除がこれを load-bearing にした——索引の
項目だけを消してファイルを残す削除は、次の読み出しの照合がそのまま元へ戻すためである。

移したもの: `LoggedPost` / `Topic` / `TopicIndex`、索引の読み書き、孤立ファイルの
照合、題の生成、一行の解析、そして `delete`。`delete` はファイルを先に、項目を後に
消す——この順序が load-bearing であり、逆順が「復活する削除」になる。

テスト 8 件。中心は `removing_only_the_entry_lets_the_next_read_resurrect_the_topic`
で、項目だけを消す形を実際に走らせ、次の読み出しでトピックが戻ることを見る。#117 の
状態(項目は在るがファイルが無い)を消せることと、一ファイル名でない id の拒否も含む。

`src-tauri` 側の配線は次のコミットで行う。

#119

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`room_delete_topic` を足した。三つの行為をこの順で行う。

1. そのトピックで走っているセッションを終える(決定4)。トピックが消えれば
   戻り道も消えるため、走らせたままにするとどのトピックにも属さないセッションが
   残る。どのトピックの席かは起動時の事実であり、`RunningSession` が `topic_id`
   を持つようにした——トピックの `sessions` から引くと、以前ここで走り今は別の
   トピックで走っているアカウントに届いてしまう。走っていることを理由に削除を
   拒まない(決定3)。
2. ファイルと索引の項目を消す(決定1、`room_log::delete_topic`)。順序が逆だと
   決定4が禁じた状態——トピックが消えてセッションが残る——になる。
3. 部屋がそのトピックに居たなら新しいトピックへ移る(決定6)。起動直後と同じ
   状態を使い回す。移った先を画面へ返す——画面は自分の現在トピックを持っており、
   消えたトピックを指したままだと、描いている会話と記録先が食い違う。

`room_log` 側は crate への配線に置き換えた。`PtyState::kill_each` は `kill_all`
をリストへ絞ったもので、失敗を報告しない理由も同じ(#96)。

#119

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
一覧の行に ❌ を足した。押すと `#topic-delete-dialog` が開き、そこで答える——
削除は取り消せず、ログは git に載っておらず写しも無いため、確認の一段は必須である
(決定2、決定1から導かれること)。`#end-dialog` / `#quit-dialog` と同じ作法であり、
CSS も同じ規則で描く。三つ目の問いに三つ目の写しを作らない。

ダイアログは二行を持つ。一行目はトピック名と、何が消えるか(発言の記録と、
セッションへの戻り道)。二行目はそのトピックで走っているセッションの名前であり、
走っていなければ出さない——決定4でセッションが止まる以上、ログの話だけをする
ダイアログは、止まったセッションを不意打ちにする。走っているかどうかはアプリへ
毎回訊く。画面の写しは最後に更新された時点のものでしかない。

題の無い行には ❌ を出さない(決定5)。そう読まれる行は二つあり、どちらもここから
消す理由が無い——まだ何も言われていない現在のトピック(索引に無く、消すものが無い)
と、索引に行があってファイルが無いトピック(#117)である。

行は flex のトラックになった。`.pick` が残りを取るため、長い題は ❌ を押し出さずに
省略される。

#119

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…carries it

「部屋のログ」に削除の項を足した——ファイルと索引の項目の両方を消すこと、
ファイルが先であること、そして逆順が黙って復活する削除になること。

「トピック」に決定 1-6 を書いた。三つの行為(セッション → 保存 → 部屋)の順序と、
その順序がなぜそれでなければならないかを含む。「トピックの一覧」に行の `❌` と
ダイアログの作法を足し、「未実装」から「トピックの削除」を落として「実装済み」へ
移した。

「テストの配置」を書き直した。#115 の時点で「照合は読んで確かめられる範囲を出て
いる、crate へ出すのが正しい形である、この issue の範囲では行っていない」と書いて
あったものが、#119 で行われた。削除は照合の裏返しであり、読んで確かめられる性質の
ものではない。CI の表に `crates/topic-index` の行を足した。

「受容したトレードオフ」の #115 の行を現状へ更新し、起動途中の席(`Seat::Starting`)
が削除から見えないことを新しい行として足した。

#119

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`kill_pty` だけを名指していたが、席を取り出して殺す経路は `kill_each`(#119)と
`kill_all` の掃き出しもある。どれが先に取り出しても、終了を告げるのはこのスレッドで
あることは変わらない。

#119

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@smileygames smileygames linked an issue Aug 27, 2026 that may be closed by this pull request
@smileygames smileygames self-assigned this Aug 27, 2026
`openTopicDeleteDialog` は走っているセッションをアプリへ訊いてからダイアログを
開く。その await をまたいで二度目の ❌ が入ると、二つの呼び出しが絡む——二度目が
一度目のトピックと一文目を上書きし、そのあと一度目の読みが返ってダイアログが開く。
出るのは、片方の名前ともう片方のセッションを載せた問いである。二度目の読みが返ると
`showModal()` が既に開いた dialog に対して投げる。

問いが立っている間は開かない形にした。`deletingTopic` はダイアログから出るどの
経路でも消えるため、これで詰まる状態は無い。

#119

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

@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 モード)

brake 1 は適用外。本リポジトリは USER_REPO5 であり、rules/evolution/initiator-autonomy.md の self-evolution PR 定義の条件②(LI_PLUS_REPO のガバナンス面)を満たさない。

merge は保留する。 auto モードに人間ゲートは無いが、#48 の顛末(本文の粒度が意図と違い、下流の誰も気づけなかった)を踏まえ、Master の確認を待つ。

受け入れ基準の照合

決定 実装 結果
1 ファイルも索引も消す crates/topic-indexdelete。両方を落とす pass
2 確認ダイアログ #topic-delete-dialog#end-dialog の作法に合わせた pass
3 走っていても消せる 走行を理由に拒まない pass
4 走っている CLI を止める pty_state.kill_each(seats.running_in_topic(...)) を削除の先頭で pass
5 空タイトル行にボタンを出さない 出していない pass
6 開いているトピックを消したら新規へ state.enter_topic(TopicRef::new(...))。移動先を戻り値で画面へ返す pass

設計として評価する点

  • 止めるセッションを sessions マップではなく起動時の topic_id で引いている。 マップで引くと、このトピックで一度走って現在は別トピックに居るアカウントまで巻き添えにする。指示に無い気づきであり、実機でしか踏まない類の欠陥を先に塞いでいる。
  • 三つの act の順序に理由が書かれている。 ストアを先にして失敗すると「トピックは消えたのにセッションは走っている」形になり、それは決定4が禁じた状態そのもの。順序が設計判断として明示されている。
  • 削除後の移動先を戻り値で画面へ返す。 画面が消えたトピックを指したまま次の投稿を別のトピックへ記録する、という食い違いを構造で塞いでいる。
  • 要求したテストが要求どおりの形で入っている。 removing_only_the_entry_lets_the_next_read_resurrect_the_topic は、索引だけ消すと復活することを実際に示してから、正しい削除なら消えたままであることを示す。復活の経路を仕様として固定した。

スコープ

crates/topic-index への切り出しは #119 の要求より広い。#119 は対象ファイル表を持たないため超えるべき線が引かれておらず、scope-exceed の対話確認は発火しない。線を引かなかったのは親の書き落としである。

その上で妥当と判断する。CI は src-tauri に対して cargo check のみを走らせ、cargo test を走らせない(tauri ツリーをリンクしたテストバイナリが GNU ターゲットで読み込めない。docs/0-requirements.md テストの配置 に run 32431917979 付きで記録済み)。要求したテストを src-tauri に置いても走らないどころかコンパイルもされない。加えて #115 の時点で「AppHandle 依存を外して crate へ出すのが正しい形。この issue の範囲では行っていない」と repo 自身が書いており、この切り出しはその名指しの移動にあたる。CI にもテスト実行ステップが追加されている。

本文の矛盾(親の瑕疵、修正済み)

#119 の前提に「削除ボタンは #117 の手動の逃げ道にもなる」と書いたまま、Master の決定5(空タイトル行にはボタンを出さない)を受けた際に前提側を直さなかった。同じ行について本文が食い違ったまま実装へ渡っている。

実装 AI がこれを発見し、決定を優先して正しく実装した上で報告している。本文は修正済み。#117 の行はどの経路でも消せないまま残るという結論に変わりはない。

持ち越し

  • #quit-dialog に固有 CSS が無い(#85 以来の既存状態、未スタイルの <dialog> として描画)。実装は #topic-delete-dialog#end-dialog の規則集合を共有させたが、範囲外の面の描画を変えないため #quit-dialog は畳み込まなかった。判断として正しい。follow-up issue の候補。
  • Seat::Starting の席は PTY を持たないため削除で止められない。その起動がトピック消滅後に完了すると、セッション id が孤児になる。閉じるには seats ロックと index ロックを spawn を跨いで保持する必要があり、狭い窓を受け入れて 受容したトレードオフ に記録した。黙らせずに書いた点を評価する。

規約面

PR タイトル純 ASCII(非 ASCII バイト 0)。PR 本文 Closes #119、日本語。コミット 6 本すべてタイトル純 ASCII、本文に日本語と #119 参照。docs 同 PR。CI 緑、mergeStateStatus=CLEAN

判定

self-review pass。実機確認を経て merge する。

@smileygames

Copy link
Copy Markdown
Member Author

実機確認の結果(親 / 2026-08-28)

119-topic-delete05a7ccf を worktree で tauri build --debug --no-bundle し、実際のアプリデータに対して確認した。確認後、データは事前の退避から復元済み。

決定の照合

決定 実測
1 ファイルも索引も消す 削除後 .jsonl 0 件、索引の項目 0 件。他トピックは無傷
2 確認ダイアログ 「発言の記録と、セッションへの戻り道が消えます。取り消せません。」
3 走っていても消せる 拒まれない
4 走っている CLI を止める claude.exe 15 → 14。ちょうど 1 プロセス
5 空タイトル行にボタン無し #117 の行を実際に生成して確認。❌ が出ない
6 開いているトピックを消したら新規へ 新しい未命名トピックへ移り、部屋が空になる

復活しないことを再起動で確認した。crates/topic-indexremoving_only_the_entry_lets_the_next_read_resurrect_the_topic が固定した経路が、実物でも塞がっている。

決定4の分離が実物で効いている

二つのセッションを別トピックで走らせ、片方のトピックを削除した。

  • pid 22976(Claude Lay、削除した T1 で起動)→ 消えた
  • pid 15368(Claude Lin、残した T2 で起動)→ 生きている
  • 機械上の無関係な claude.exe 13 プロセス → 全て無傷

sessions マップではなく起動時の topic_id で引く実装判断が、期待どおりに分離している。

ダイアログが要件より一段深い

走行中のセッションを持つトピックで押すと、ダイアログに赤字で一行増える。

Claude Lay のセッションも終了します。

どのアカウントが止まるかを名指ししており、別トピックで走っている Lin には触れていない。issue の「セッションが止まることを述べる必要がある」より踏み込んでいる。

付随して確認できたこと

declares_session_id の門番が効いている。{session_id} を書いていない Claude Lin は id を発行されず、その起動先トピックの sessions は 0 件のままだった。プレースホルダを書かないアカウントには id が付かない、という決定4Bの形(#115)が実物で確認された。

見つかったこと(この PR の受け入れは妨げない)

  1. 意図した終了が事故の経路で報告される。 削除でセッションを止めた直後、状況行に「Claude Lay が終了しました(終了コード不明)。端末を確認してください。」と出る。アプリが自ら意図して止めた終了であり、端末を確認させる理由が無い。別 issue とする。
  2. bug(history): a session-only topic leaves an index entry with no posts file #117 の行と未実体化の現在トピックが画面上で区別できない。 どちらも 未命名 として並ぶが、前者は索引に残って消せず、後者は何も書かずに消える。bug(history): a session-only topic leaves an index entry with no posts file #117 の判断材料として渡す。

判定

受け入れ基準は全て満たしている。merge する。

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(history): delete a topic from the list

1 participant