feat(room): tell a seat taken without the topic's earlier posts that they exist (topic-index, mcp-config, session.rs, room_log, sidecar, docs) - #134
Conversation
…they exist (topic-index, mcp-config, session.rs, room_log, sidecar, docs) (#133) 読み出し(`read_room_history`)は在って動くが、呼ぶべき場面を名指す文が 作法に無かった。欠けていたのは道具ではなく引き金である。文脈を持たない まま席に着いたセッションに、そのことを伝える。 伝える条件は「そのトピックに既に発言が在り、かつこの起動が再開の線に 入らなかったこと」である(AI 判断1)。「再開先を外した席」ではない—— 外した席も、発言のあるトピックへ初めて入った席も、等しく来る前の発言を 持たない。判定は解決後の行に対して行う(`resumed_from` が無いこと)。 伝えるのは「在る」ことだけで、件数は載せない(AI 判断2)。見るのは ファイルの大きさだけであり(`topic_index::has_posts`)、トピックの全読みを 起動のたびに払わない。アプリが代理で `read_room_history` を呼ぶ形は 採らない(AI 判断3)。作法は「在る」と述べるだけで、「読め」とは言わない。 経路: `session.rs` が起動ごとに判定し、`crates/mcp-config` が `PULLCEPT_UNSEEN_HISTORY` を `.mcp.json` の登録へ書き、サイドカーが `instructions` の「前を見る」の節を差し替える。登録は起動のたびに丸ごと 書き直されるため、状態が成り立たない起動へ前回の鍵は残らない。 push にはしない。渡すのは「在る」という事実であって、発言そのものでは ない(`docs/0-requirements.md` の「部屋から参加者へ過去を push しない」)。 CI が効く場所へロジックを置いた: `crates/topic-index` に `has_posts` と その両方向のテスト、`crates/mcp-config` に鍵の有無の往復テスト、 サイドカーには二つの形の全文リテラルのテスト。 #133 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
smileygames
left a comment
There was a problem hiding this comment.
self-review (auto mode)
受け入れ条件
AI 判断1(境界)— 満たす。 src-tauri/src/session.rs の判定は launch_line.resumed_from.is_none() && room_log::topic_has_posts(...) であり、dropped_resume 専用の分岐は作られていない。issue が要求したとおり「再開先を外した席」ではなく「再開しなかった席」が境界になっている。#131 の経路への絆創膏を避けるという理由が、実装の literal に落ちている。
AI 判断2(件数を載せない)— 満たす。 crates/topic-index の has_posts は std::fs::metadata の長さだけを見る。トピックの全読みは起動経路に入らない。env は PULLCEPT_UNSEEN_HISTORY="1" の presence のみで、数を運ばない。
AI 判断3(代理で呼ばない)— 満たす。 作法は「在ります」と述べるだけで、読めとは言わない。テストが否定形も検査している(まず read_room_history を呼んで が instructions に無いこと)。述べることと命じることを分ける判断が、通る/通らないの形で守られている。
制約
- push にしない — 渡るのは事実一つで、発言は渡らない。
docs/0-requirements.md:71(#31 / #39)の一線は動いていない。 - PTY への流し込みを採らない — 経路は env と
instructionsのみ。 - #110(画面側)に触れない — 差分に画面側は無い。
- 席の引き取り(#84 / #115 決定4C)に触れない — 同上。
効いている設計判断
二形態は並置ではなく置換である。 一般形と着席済み形を両方出せば、「在る」と「在るかもしれない」を同じ息で言うことになる。テストが置換であることを負の検査で固定している(- あなたが来る前の発言は届きません。 が出ないこと)。
巻き戻しの一行だけは両形態に残る。 一ページで返り切らないのは通常の場合であり、カーソルの取り方を失えば分岐そのものが読み手の足を止める。共有部分の切り分けが正しい。
壊れた行しか無いファイルは「在る」と答える。 多く答えれば要らない呼び出しが一回、少なく答えれば欠けていること自体が伝わらない——非対称なので、この向きが正しい。doc comment がその非対称を述べている。
scope の逸脱(報告)
issue の target files に無い二つが加わっている。
src-tauri/src/room_log.rs(topic_has_postsラッパ)crates/topic-index/src/lib.rs(has_posts本体 + テスト)
内容としては受け入れる。事実の出所はトピックのログであり、room_log はアプリからそこへの唯一の口である。topic-index はトピックのファイル配置を所有する crate であり、かつ CI がテストを走らせられる場所である(src-tauri は GNU ターゲットのため走らない)。判断2 を「全読みしない」形で満たすには、この二つ以外に置き場所が無い。
target files の列挙が私の側で不足していた。 #131 / #132 に続いて二回連続で、事実の出所を辿らないまま列挙している——変更が読むデータの出所を追っていれば、どちらの回も列挙に入っていた。scope-exceed の対話確認はコミット前に発火していない(実装側に対話面が無いため)。この点は Master へ報告済み。
残る穴(この PR の範囲外)
再開した席は対象外である。 判断1 の境界がそうなっているため、自分の会話を持って戻った席は、留守の間に部屋で言われたことを持たないままフラグを受け取らない。盲目の度合いは小さい(自分の文脈は continuous)が、ゼロではない。仕様どおりであり defect ではないが、次に問われる場所なので記録しておく。
実機
未確認。 着いた席がこの一文を読んで実際に read_room_history を引くかどうかは計測していない。docs/0-requirements.md の未確認一覧にそう書かれている。押し付けない判断がそのまま「引かれない」に落ちる可能性は残っており、そこは observe してからの判断になる。
版数
patch。 追加的で小さい振る舞いの変更である。rules/operations/release-version-rule.md の minor は「大きい」構造変更に掛かる修飾を持つ。
次
auto mode のため人の gate は無い。self-review pass として merge する。
Closes #133
読み出しは在って動くが引き金が無かった。文脈を持たないまま席に着いたセッションに、そのトピックに既に発言が在ることを伝える。伝えるのは「在る」ことだけであり、引くかどうかはセッションが決める。
境界は「再開しなかった席」であって「再開先を外した席」ではない(AI 判断1)。件数は載せない(AI 判断2)。アプリが代理で
read_room_historyを呼ぶ形は採らない(AI 判断3)。push にしないという制約はそのまま——渡すのは事実であって発言そのものではない。経路:
session.rsが起動ごとに判定 →crates/mcp-configがPULLCEPT_UNSEEN_HISTORYを.mcp.jsonへ書く → サイドカーがinstructionsの「前を見る」を差し替える。CI が効く場所へロジックを置いた(
crates/topic-indexのhas_posts、crates/mcp-configの鍵の往復、サイドカーの二形態の全文リテラル)。