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]>
30 lines
2.5 KiB
Python
30 lines
2.5 KiB
Python
# Console conversation-view mutants. Run from a full scratch copy of the checkout
|
|
# (/tmp/dewey-chat02/scratch-board/packages/webui), never the served tree.
|
|
import subprocess
|
|
f="src/public/app.js"; orig=open(f).read()
|
|
M=[("text set as HTML","e.textContent = inert(text)","e.innerHTML = text"),
|
|
("controls not made visible","e.textContent = inert(text)","e.textContent = String(text)"),
|
|
("fragments replace instead of join","b.value += c[FIELDS[c.type]]","b.value = c[FIELDS[c.type]]"),
|
|
("details open by default","n.open = open[i++] ?? false","n.open = open[i++] ?? true"),
|
|
("no branch marker","if (v.defaultBranch !== v.branch) marker(","if (false) marker("),
|
|
("no newer-session marker","if (conv.sessionId && r?.sessionId && r.sessionId !== conv.sessionId) marker(","if (false) marker("),
|
|
("no reconcile marker","if (res.body.refusal?.reconcile) marker(","if (false) marker("),
|
|
("follow drops its branch","branch: c.branch, cursor: c.follow","cursor: c.follow"),
|
|
("follow switches to the default branch","conv.branch = body.page.branch;","conv.branch = body.view.defaultBranch;"),
|
|
("forms share the reply-form class","if (!e.target.matches('.reply-form, #conv-form')) return;","if (!e.target.matches('.reply-form')) return;"),
|
|
# Revision 2 (Filbert B1, N1, N3).
|
|
("reload drops its branch","a === 'reload' ? { branch: c.branch } :","a === 'reload' ? {} :"),
|
|
("latest keeps the open branch","a === 'newest' ? { from: c.id, sessionId: c.sessionId } : {}","a === 'newest' ? { from: c.id, sessionId: c.sessionId } : { branch: c.branch }"),
|
|
("gone branch not reopened","if (!first.ok && opts.branch && first.body.refusal?.code === 'unknown-branch') {","if (false) {"),
|
|
("gone branch reopened silently","if (first.ok) marker('gone',","if (false) marker('gone',"),
|
|
("newest on the same file clears the marker","c.newerUnread = !!opts.from && opts.from === choice.conversation;","c.newerUnread = false;"),
|
|
("C1 controls left raw","UNSEEN = /[\\u0080-\\u009f\\u061c","UNSEEN = /[\\u061c"),
|
|
("bidi marks left raw","\\u061c\\u200e\\u200f\\u202a","\\u202a")]
|
|
for n,a,b in M:
|
|
assert orig.count(a)==1,n
|
|
open(f,"w").write(orig.replace(a,b))
|
|
r=subprocess.run(["node","--test","--test-concurrency=1","tests/conversation.test.mjs","tests/history-return-flow.test.mjs"],capture_output=True,text=True,timeout=900)
|
|
fails=sorted(set(l.strip()[2:].split(" (")[0][:60] for l in r.stdout.splitlines() if l.lstrip().startswith("✖") and "failing tests" not in l))
|
|
print(("CAUGHT " if r.returncode else "MISSED ")+n+" -> "+"; ".join(fails))
|
|
open(f,"w").write(orig)
|