Jason ruled on seven open items (20:27Z-20:45Z): seat Gitea tokens read in place, one Discord restart after 6b with row 25 live, row 8 limited to the dev seats, DYOR in dyor-stack-v4 with Sage moved to SetSpark, skills/aws-* excluded locally, no second WebUI return defect, and go on CHAT-02 only. Sage persona files name SetSpark as its business work. Darkwing's SOUL drops harness names that were wrong for T3. DEFERRED adds the slash-prefix paste hazard and the board Host/Origin gap, and moves the ledger T3 item to Done. Dewey's approved CHAT-02 brief (636b0fac) and Filbert's review are recorded. Co-Authored-By: Claude Opus 5.5 <[email protected]>
202 lines
11 KiB
Markdown
202 lines
11 KiB
Markdown
# CHAT-02 brief: read-only histories and Age (#1507, row 5)
|
|
|
|
Author: Dewey, 2026-09-26. R2: Sage's decisions on D1-D5 are recorded in §3
|
|
(R1 frozen as `BRIEF-r1-314da8b0.md`). For Filbert's review. No source edits.
|
|
Plan row: `docs/plans/2026-09-13_webui-session-chat.md` line 214. Depends on
|
|
CHAT-01 (`28d4e98a`) and uses the CHAT-01C companion (`b023841c`).
|
|
|
|
## 1. Is there a second defect in the return path?
|
|
|
|
Short answer: no second defect in the return path shows up for repository Pi
|
|
seats. The answers reach the transcript, the board reads them, and the Console
|
|
shows them. What Jason hit on 09-13 is best explained by the product gap: the
|
|
Console offered one "Last assistant text" field, clipped at 240 characters, in
|
|
an inspector, with no reply thread and no pending signal. 42c08d52 fixed the
|
|
pending display. The clip and the missing thread are CHAT-02's job.
|
|
|
|
I found one real defect on the send side, not the return side (§1.3).
|
|
|
|
### 1.1 Evidence so far
|
|
|
|
1. **Transcripts.** I scanned every `.pi/state/*/sessions` file (darkwing,
|
|
dewey, filbert, researcher) for board sends. The script is
|
|
`evidence/sends.mjs` and the output is `evidence/board-sends-repo-pi.jsonl`.
|
|
There are 30 sends and 29 have a final answer in the same file. Latency is
|
|
1.5 s minimum, 14.6 s median and 1019 s maximum. In 16 of the 29 answers
|
|
the text exceeds 240 characters, so the Console showed them clipped.
|
|
2. **The unanswered send.** Filbert, 2026-09-12T16:33:17Z. The seat started
|
|
working on it: it read files until 16:35:44Z, the last entry is an
|
|
`aborted` assistant turn, and a new filbert session began at 16:36:26Z. The
|
|
seat was relaunched mid-turn. That lost the answer, but the loss is in the
|
|
seat, not in the return path.
|
|
3. **Jason's report window.** At 2026-09-13T00:49:59Z he asked dewey "What
|
|
are the Gate E criteria?". The answer landed at 00:50:07Z with 365
|
|
characters, clipped to 240 in the Console. He wrote the report at 00:56:51Z.
|
|
The report says the sessions "are all cards within the project dashboard and
|
|
not available as independent chat interfaces". That describes the missing
|
|
thread, not a missing answer.
|
|
4. **The 09-13 Console, replayed.** I extracted `ea00ec66` into a scratch
|
|
directory and ran the return-flow test with the pending and Age
|
|
assertions removed. It passed: the new answer arrived through the 10 s
|
|
poll, once, in the open inspector. That page did not drop answers.
|
|
5. **Jason's live send today.** Researcher, user entry at
|
|
2026-09-26T20:10:57.429Z, answer "pong" at 20:11:06.173Z (8.7 s). At
|
|
20:15:18Z `/api/board` showed the researcher row as `idle` with
|
|
`lastAssistantText: "pong"`, `lastActivity` 20:11:06.173Z, the same
|
|
`sessionFile`, and a live registration (`evidence/board-researcher-*.json`).
|
|
The live WebUI (pid 1266267, port 7330) serves `app.js` byte-identical to
|
|
HEAD (`d1a51646…`), so the 42c08d52 pending notice is live. The WebUI
|
|
server code has not changed since that process started on 09-13 16:19 CDT.
|
|
The board (pid 3977979, port 7331) started today at 15:03 CDT.
|
|
|
|
### 1.2 What is still unverified
|
|
|
|
- **What Jason's screen showed.** For today's send I have the transcript and
|
|
the board JSON, not the Console DOM or a screenshot. The one missing fact is
|
|
whether "pong" appeared in the open inspector without a manual refresh.
|
|
- **The 09-13 processes.** The board keeps no reply receipts and the 09-13
|
|
board and WebUI processes are gone. I cannot prove what those processes
|
|
served at 00:50Z. I can only show that the same code, replayed, works.
|
|
- **Fleet seats.** I did not scan `~/.mosaic` fleet transcripts. The rule for
|
|
this phase is to leave them alone, and CHAT-02 does not cover fleet
|
|
catalogues.
|
|
- **Clipping in a live send.** "pong" is 4 characters, so today's send does
|
|
not exercise the 240-character clip.
|
|
|
|
### 1.3 Send-side defect found in passing
|
|
|
|
Today's user entry starts with `/`: `/[dragon-lin:control-board ->
|
|
dragon-lin:researcher] ping`. `agent-send.sh` adds the header, so the `/` was
|
|
already sitting in the Pi editor when the paste arrived. `send-message.sh`
|
|
pastes into whatever is in the composer (`paste-buffer -p`, then Enter). It
|
|
does not clear it first. Here Pi treated the result as plain text. If the
|
|
composer had held a real command prefix, a board reply could have become a
|
|
slash command. This is the unmediated-ingress hazard that CHAT-01 assigns to
|
|
CHAT-03I (B3). `tools/tmux/**` is excluded from the WebUI plan, so I
|
|
record it and do not propose a fix here. Sage confirmed it as a safety gap
|
|
and is adding it to DEFERRED.md under CHAT-03I/B3. It gets one line on #1507.
|
|
There is no tools/tmux change now.
|
|
|
|
### 1.4 Evidence that settles it
|
|
|
|
One question for Jason settles the live case: **after today's ping, did
|
|
"pong" appear in the Console inspector without pressing Refresh?**
|
|
|
|
- If yes, there is no second defect. CHAT-02 proceeds as a product-gap fix.
|
|
- If no, `/api/board` had the answer, so the defect is in the Console or the
|
|
WebUI proxy. Then capture the Console DOM and the network log for
|
|
`/api/board` during one send.
|
|
- If `/api/board` had lacked it, the defect would be in the scanner (wrong
|
|
newest file). If the transcript had lacked it, the defect would be in the
|
|
transport or the seat. Neither happened today.
|
|
|
|
To make the check complete for the clip, one more live send can ask for an
|
|
answer over 240 characters. Every step above then repeats, and the Console
|
|
should show the text ending in "…". That proves the clip is what cut the
|
|
09-13 answer short.
|
|
|
|
## 2. Scope
|
|
|
|
CHAT-02 per the plan: both harness catalogues, safe full branch history with
|
|
pagination and cursors, separate timestamps, relative Age from last
|
|
activity, and fixtures for malformed, truncated, replaced and touched logs,
|
|
cross-project and symlink denial, and no log writes. Read-only: opening a
|
|
conversation never resumes, forks, launches or controls anything.
|
|
|
|
### 2.1 Backend: `packages/conversation/**`
|
|
|
|
Dewey authors it (D4).
|
|
|
|
- **Catalogue.** Approved source roots only: the board's repository specs
|
|
(`<repo>/.pi/state/<seat>/sessions`) and live seat registrations. There is
|
|
no global scan and no browser-supplied path. Each conversation gets an
|
|
opaque ID mapped server-side to a file. Catalogue creation time, engine
|
|
launch time and last activity are separate nullable fields.
|
|
- **No-write Pi parser.** Never `SessionManager.open`, which can migrate old
|
|
files (CHAT-00 line 67). Open read-only. Record size, mtime and inode
|
|
before and after each read, and the fixture asserts they are unchanged.
|
|
- **Branches.** Build the `id`/`parentId` tree and select a leaf explicitly.
|
|
The default leaf is the last appended entry, which the implementer must
|
|
confirm against the pinned Pi session docs. Other leaves are read-only
|
|
branches.
|
|
Compaction entries render as markers. Pi `get_entries` order is not a
|
|
branch transcript (CHAT-00 line 66), so the parser does not use it.
|
|
- **Pages.** CHAT-01 limits: at most 100 parts, 8 MiB serialized UTF-8, 64
|
|
blocks per part and 262144 characters per string. Oversize content splits
|
|
into continuation parts and is never clipped. The cursor binds actor,
|
|
purpose, conversation, branch, snapshot, source epoch and expiry. A
|
|
replaced file (new inode or a shorter length) is a new source epoch, so old
|
|
cursors refuse and the client keeps its view with a reconcile marker. It
|
|
never silently switches files.
|
|
- **Damaged input.** A malformed line becomes an unavailable part with its
|
|
position, and reading continues. A truncated trailing line counts as
|
|
incomplete, not as an error.
|
|
- **Denials.** A symlink anywhere under the root, a path that resolves
|
|
outside the root, a parent-session reference, or a conversation from
|
|
another project all refuse, with fixtures.
|
|
|
|
### 2.2 Console: `packages/webui/**` (Dewey)
|
|
|
|
This is the smallest piece that answers the 09-13 complaint: a read-only
|
|
conversation view per session, opened from the card, table or inspector. It
|
|
renders the selected branch in full, unclipped: user text, assistant text,
|
|
tool calls and results collapsed, thinking hidden by default, and Markdown as
|
|
untrusted text with no active HTML. Age stays as 42c08d52 shipped it. Reply
|
|
keeps the existing board path unchanged. The view gets the new answer through
|
|
polling, as the inspector does now. Streaming belongs to CHAT-03.
|
|
|
|
The full chat UI (sidebar, composer, queue, approvals, uploads) stays in
|
|
CHAT-05.
|
|
|
|
### 2.3 Return-flow regression (required by the plan)
|
|
|
|
Extend `packages/webui/tests/return-flow.test.mjs`, or add a sibling test.
|
|
Send from the conversation view. Then the seat appends user, toolCall,
|
|
toolResult and a final answer longer than 240 characters. Assert that the
|
|
whole answer appears once, unclipped, in the same open view, with no manual
|
|
refresh, and that the draft and caret survive. Add a delayed-result variant
|
|
where the toolResult lands after a poll. This covers the Pi engine only; see
|
|
D2.
|
|
|
|
## 3. Decisions (Sage, 2026-09-26)
|
|
|
|
- **D1: moved.** CHAT-01 line 342 had deferred "the actual
|
|
execution/writer-claim record" to CHAT-02. CHAT-01C line 217 had deferred
|
|
R3-1, reconciling dispatched but unconsumed input, to "CHAT-02 adapter
|
|
evidence". A read-only reader needs neither, so both go to CHAT-03, which
|
|
owns binding and the single writer. This is noted on #1507.
|
|
- **D2: accepted.** Pi ships in CHAT-02. The Claude catalogue refuses
|
|
`unsupported-harness` under a fixture until B1 has evidence (Claude's
|
|
persisted branch format and leaf selection, CHAT-00 line 66). This narrows
|
|
the plan's "both harnesses". Sage records the scope change in the lead
|
|
decisions file.
|
|
- **D3: accepted.** `packages/conversation` is a library with no server. The
|
|
board adds two read-only routes, catalogue and page, in
|
|
`packages/control-board/src/serve.mjs` and `scan.mjs`. Darkwing reviews
|
|
that change before it lands. The coordination note goes to Darkwing when
|
|
the backend reaches review, not before.
|
|
- **D4: Dewey authors both.** The backend comes first, then the Console
|
|
against its fixtures. Filbert reviews this brief now and the code after.
|
|
- **D5: stays with Jason.** Sage set the live reply test as the condition,
|
|
and it passed. Sage is asking Jason for the go on CHAT-02. No code goes
|
|
under `packages/conversation` until Sage relays his answer.
|
|
|
|
## 4. Acceptance
|
|
|
|
- The new `packages/conversation` tests cover every fixture in §2.1, including
|
|
a before/after hash, mtime and inode check proving no log writes.
|
|
- The return-flow regression from §2.3 passes on the served WebUI.
|
|
- These still pass: `node docs/plans/chat-00/check.mjs`, `chat-01/check.mjs`,
|
|
`chat-01c/check.mjs`, and the control-board, webui and seat suites.
|
|
- Browser evidence: conversation view at 320 and 1440 in both themes, with a
|
|
long answer, a tool call, a malformed-line marker and a stale-cursor
|
|
reconcile marker. No horizontal overflow at 320.
|
|
- Filbert approves the exact candidate hashes. Live check: one board send
|
|
with a long answer, visible in full in the view.
|
|
|
|
## 5. Not in scope
|
|
|
|
Live adapters, control, streaming, queues, uploads, approvals, fleet seats,
|
|
Claude history until B1, any change to `tools/tmux/**`, `roles/**` or
|
|
session logs, and the `/` paste hazard (CHAT-03I).
|