feat(webui): CHAT-02 Console, read-only conversation view (#1507)

History opens a seat's conversation from the Waiting card, table row
and inspector. It pages the whole branch through the CHAT-02 board
routes, renders untrusted text inert, polls with the follow cursor, and
marks every switch (branch, newer, reconcile, gone). The WebUI proxy
passes only the two conversation routes' queries upstream.

Dewey authored it. Filbert asked for changes on r1 (24b046af) and
approved r2 (d06de6a7) in review 160dd68d. A relaunch shows 'newer',
not 'reconcile', a deviation from brief 2.3 item 6 that Filbert
accepted.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-09-26 18:05:11 -05:00
co-authored by Claude Opus 5.5
parent 3a209eeafe
commit c9e771cf59
34 changed files with 1669 additions and 26 deletions
+6 -1
View File
@@ -6,6 +6,11 @@
section{margin-bottom:20px}#seen-section{margin-bottom:20px}summary{cursor:pointer}#seen{margin-top:10px}
.table-wrap{background:var(--surface);border:1px solid var(--line);border-radius:var(--r)}table.sessions{min-width:1050px}table.sessions td{max-width:270px;overflow-wrap:anywhere}table.sessions .task{min-width:190px}.source{display:block;color:var(--muted);font-size:.75rem}.session-open{font:inherit;font-weight:600;background:none;border:0;color:var(--action);padding:3px;cursor:pointer;text-align:left;overflow-wrap:anywhere}
.waiting{grid-template-columns:repeat(auto-fit,minmax(min(100%,260px),1fr))}.wait-item .session-open{font-size:1rem}.wait-item p{margin-top:6px}.wait-item .actions{justify-content:space-between}.wait-item .preview{white-space:pre-wrap;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.inspector .kv{grid-template-columns:1fr}.inspector .kv dd{margin-bottom:10px}.last-text,.receipt{white-space:pre-wrap;overflow-wrap:anywhere}.last-text{font:inherit;font-size:.9rem;margin:0}.receipt{font-size:.85rem;margin-top:8px}.receipt.failed{color:var(--danger)}.reply-form{display:grid;gap:8px;margin-top:14px}.reply-form .btn{justify-self:start}.inspector-head{flex-wrap:wrap}#inspection{min-width:0}.badge{white-space:nowrap}.foot>*{min-width:0;overflow-wrap:anywhere}
.inspector .kv{grid-template-columns:1fr}.inspector .kv dd{margin-bottom:10px}.last-text,.receipt,.conv-receipt{white-space:pre-wrap;overflow-wrap:anywhere}.last-text{font:inherit;font-size:.9rem;margin:0}.receipt,.conv-receipt{font-size:.85rem;margin-top:8px}.receipt.failed,.conv-receipt.failed{color:var(--danger)}.reply-form,.conv-form{display:grid;gap:8px;margin-top:14px}.reply-form .btn,.conv-form .btn{justify-self:start}.inspector-head{flex-wrap:wrap}#inspection{min-width:0}.badge{white-space:nowrap}.foot>*{min-width:0;overflow-wrap:anywhere}
@media(max-width:959px){.tree #projects{flex-basis:100%;width:100%}.tree-list{display:flex;flex-wrap:wrap}.tree-list li{max-width:100%}.tree .small{flex-basis:100%;margin:0}.inspector{max-height:75vh}.cmdbar{position:static}}
@media(max-width:479px){.cmd-right{margin-left:0;gap:6px}.cmd-right label{flex:1 1 110px}.cmd-right select{max-width:100%;width:100%}.kv{grid-template-columns:1fr}.content{padding:12px}.tree{padding:12px}.page-head>h2{flex-basis:100%}}
/* Conversation view (#1507, CHAT-02). Text wraps; nothing in it scrolls the page sideways. */
.conversation{min-width:0}.conversation .page-head{flex-wrap:wrap;gap:10px}.conversation .page-head>div:first-child{min-width:0;overflow-wrap:anywhere}.conv-actions{display:flex;gap:8px;align-items:end;flex-wrap:wrap;max-width:100%}.conv-actions label{display:grid;gap:2px;font-size:.75rem;min-width:0;max-width:100%}.conv-actions select{max-width:min(100%,360px);min-height:36px}
.conv-log .turn{max-width:100%;min-width:0}.conv-turn time{display:block;font-size:.72rem;color:var(--muted);margin-bottom:4px}.conv-user{border-left:3px solid var(--action)}.conv-notice,.conv-compaction{background:none;border:1px dashed var(--border)}
.conv-text,.conv-pre{white-space:pre-wrap;overflow-wrap:anywhere;margin:0}.conv-pre{font-family:var(--mono);font-size:.82rem;max-height:60vh;overflow:auto;margin-top:6px}.conv-turn details{margin-top:6px}.conv-turn summary{font-size:.85rem;color:var(--muted);cursor:pointer}
.conv-marker{display:flex;gap:10px;align-items:center;flex-wrap:wrap}.conv-marker p{margin:0;flex:1 1 220px;overflow-wrap:anywhere}.conv-open{margin-left:6px;padding:2px 8px;min-height:0;font-size:.8rem}#conv-form{max-width:72ch}