The speaker goes on every turn of the chat: interactive, --say and --say's retry. Without the
flag it is None. A name that is empty or holds whitespace or a control character (Unicode), or a
second --speaker, is a usage error: the usage text on stderr and exit status 2. The usage text
gains the flag and one line explaining it. Given: chat_speaker.rs (new) and new versions of
chat.rs, chat_approvals.rs and cli.rs. Task 01 now copies chat.rs-task01, the older chat.rs.
Checks: every before block found once at ref 03; replayed from the task text on a fresh ref-03
worktree with its own build directory, byte-identical to the reference, gate ok with 1158 tests
(1148 + 10); /tmp unchanged around the reference's and the replay's gate runs; 20 of 20
mutations caught; the new tests passed 40 of 40 runs under CPU load; given files pass fmt and
the 500-line check; no chat-template tag in the plan or the given files.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A batch carries the Mattermost user id of each message; the turn's speaker
is the username of the one user who wrote all of it (Client::username,
kept in a map on the event loop), and None for two or more people or a
failed lookup. The turn's text is unchanged.
Checks: reference replayed from the task text on a fresh ref-02 worktree
with its own build dir, byte-identical; make gate ok with 1148 tests
(1138 + 10); /tmp unchanged around both gate runs; 21 mutations, all
caught; new tests stressed 40 times under load, no failure; every before
block found once at ref 02; no chat-template tags.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
loopd copies the Turn's speaker onto the User record it logs, as it
came (not checked, not neutralised), and never into a request; after a
finished turn it sends SessionUpdated with the turn's number, the count
of User records in the session's log (Session::turns), so the first
turn is 1, a failed turn that was logged counts, and the count goes on
after a reopen or a restart. Failed turns are still not told.
Given: speaker_turn.rs (8 tests) and new versions of loopd's memory.rs,
turn_broker.rs, end_to_end.rs and support/turn.rs (run_turn gains
speaker, MemorySource::updated gains turn). Task 01 now copies
memory.rs-task01, its own version.
Checks: the reference passes make gate with 1138 tests (1130 + 8); the
task replayed from its text on a fresh ref-01 worktree with its own
target is byte-identical to the reference and passes the gate; /tmp
unchanged around both gate runs; 15 one-line mutations (speaker not
logged or dropped by the channel or neutralised, speaker in the request
at log time or at replay, turn 0-based or +1, counting Assistant
records, all records or only speakers' turns, a global or per-process
counter, told before logging or on failure, MemoryPort sending 0) all
caught; speaker_turn run 60 times under load, no failure; no
chat-template tag in the plan or given files; task lines within 100
characters but tables.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Task 01 changes bxcore's wire and log types for M5c-1: Turn.speaker and
LogRecord::User.speaker (optional, skipped when None, so old frames and logs
keep their bytes), SessionUpdated.turn (required, refused when missing), and
the new SessionState / SessionStateReply messages. The other crates only
construct the new fields (speaker: None, turn: 0) and brokerd's kind() names
the two new kinds; later tasks give them values. 20 given files.
Checks, against a reference at 7b40686 with its own build directory:
- every "before" block found exactly once at 7b40686 (and at master, which
changed no crate since);
- step 2's failures as the task names them: two strict tests, fifteen test
targets with E0559/E0560/E0432/E0599 only;
- make gate: gate: ok, 1130 tests (1122 + 8); /tmp unchanged around it;
- replay from the task text in a fresh worktree of 7b40686 with its own
target/: crates/ byte-identical to the reference, gate ok, 1130; removed;
- 23 mutations: 21 caught; the two that drop `default` from an Option
field cannot change behaviour (serde reads a missing Option as None);
- no chat-template tag whole in the task or the given files; lines over
100 characters only in tables, fixtures and verbatim strings.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
29 request/response pairs, each request exactly as roncho 1.0.0's
blocking client sends it, recorded in a throwaway workspace
(boxmaker-plan-probe) created for it and deleted afterwards; no other
workspace was touched. For the fake Honcho server of task 10. Found:
creation is get-or-create (201, then 200); adding messages to a missing
session creates it; a 422 echoes the whole input; a deleted conclusion
answers 204 with an empty body, and 404 the second time.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>