Files
stack/agents/dewey/work/chat-02/evidence/backend/mutate-board.py
T
jason.woltjeandClaude Opus 5.5 a5beb6d97d feat(conversation): CHAT-02 read-only Pi history reader and two board routes (#1507)
packages/conversation is a library with no server: safe-fs, the Pi session
parser, CHAT-01 pages, pinned snapshots, cursors and follow. The control
board adds GET /api/conversations and /api/conversation behind the Host
and Origin guard. Both are read-only, their queries are validated, and
each refusal code maps to a status.

Dewey authored it (packet 0cf177b1, revision 2). Filbert reviewed the code:
R1 revise (branch ids moving on append, the assumed-link bridge merging
branches, one unreadable seat directory turning the catalogue into a 500),
then R2 approve (3b14d66c). Darkwing reviewed the routes: R1 approve
(07b10ad1), R2 approve (b9d92003). The package lands with the routes,
because serve.mjs imports the reader at load.

On an index export: the eight suites 24/90/43/17/14/15/63/18,
conversation and control-board 153/153, webui 9/9.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-26 16:36:20 -05:00

31 lines
2.2 KiB
Python

import subprocess, os
S="/tmp/dewey-chat02/scratch-board"
f=os.path.join(S,"packages/control-board/src/serve.mjs")
orig=open(f).read()
M=[
("conversation routes before the guard",[(""" const refused = foreignRequest(req);""",""" { const u0 = new URL(req.url, "http://localhost"); if (u0.pathname.startsWith("/api/conversation")) { let o; try { o = conversationResponse(reader, u0); } catch { o = { status: 500, body: {} }; } return sendConversationJson(res, o.status, o.body); } }
const refused = foreignRequest(req);""")]),
("no nosniff",[(', "x-content-type-options": "nosniff"','')]),
("all refusals 422",[("status: REFUSAL_STATUS[out.refusal.code] ?? 422","status: 422")]),
("no query validation",[(" if (values.length !== 1 || !QUERY_VALUE.test(values[0])) return { error: `invalid ${key}` };\n","")]),
("unknown params allowed",[(""" if (!["id", "branch", "cursor"].includes(key)) return { error: `unknown parameter: ${key}` };\n""","")]),
("reconcile dropped",[("refusal: { code: out.refusal.code, reconcile: out.refusal.reconcile }","refusal: { code: out.refusal.code }")]),
("cursor ignored",[(" const out = query.cursor\n"," const out = false\n")]),
("registrations ignored",[("rootsFromSpecs(specs, loadRegistrations(seatsDir).registrations)","rootsFromSpecs(specs, [])")]),
("cursor without branch served",[(" if (out.cursor && !out.branch) return"," if (false) return")]),
("unavailable falls to 422",[(" unavailable: 404,\n","")]),
("CORS header sent",[('"x-content-type-options": "nosniff" });','"x-content-type-options": "nosniff", "access-control-allow-origin": "*" });')]),
]
for name,reps in M:
src=orig
ok=True
for a,b in reps:
if a not in src: print("NOT APPLIED",name); ok=False; break
src=src.replace(a,b,1)
if not ok: continue
open(f,"w").write(src)
r=subprocess.run(["node","--test","--test-concurrency=1","tests/serve.test.mjs"],cwd=os.path.join(S,"packages/control-board"),capture_output=True,text=True,timeout=600)
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 ")+name+" -> "+"; ".join(fails))
open(f,"w").write(orig)