Skip to content

Send approved project lessons to Room rounds (#174) - #250

Merged
memtomem merged 1 commit into
mainfrom
feat/174-room-round-lessons
Nov 4, 2026
Merged

memtomem merged 1 commit into
mainfrom
feat/174-room-round-lessons

Conversation

@memtomem

@memtomem memtomem commented Nov 4, 2026

Copy link
Copy Markdown
Owner

Follow-up to #245 (#174 PR 2): Room rounds now receive the project's approved lessons. #174 stays open for the TUI work (recording a verdict, promoting and choosing lessons from the TUI) and goal-scoped lessons in rooms.

What changes

Showing and choosing, before the round

  • room round (foreground and --detach) and start list the lessons a round will use, where each came from, and take --skip-lesson ID (repeatable) and --no-lessons. start also forwards both flags to its single-agent run, including the compare-to-single fallback; with --trial they are refused.
  • The CLI resolves the lessons (cli._show_round_lessons, sharing _show_lessons with run, whose output is unchanged). The coordinator never opens the board: it receives RoundLesson (id, text) pairs through RoomCoordinator.run_round(lessons=).
  • The preview checks the lessons against the round prompt with the coordinator's own rooms.round_lessons_fit. Only a task within about 4 KB of the size limit leaves no room; then the preview names them as left out and none are sent, so it never promises a delivery that cannot happen.
  • A detached worker gets exactly the listed pairs as JSON on a second anonymous inherited fd (--lessons-fd), staged like the prompt fd: unlinked before writing, full-write loop, rewound. Lesson text never reaches argv. A staging or spawn failure closes both fds and removes the config snapshot. The worker refuses a malformed payload, null included, before any round state changes, and one cleanup scope owns both fds and the snapshot.

In the prompt

  • Every member gets the lessons every round, cold or resuming, after the untrusted peer checkpoint and right before the task, under --- APPROVED PROJECT LESSONS ---. When lessons are present, the checkpoint preamble says to follow the approved lessons and the current task after the separators, instead of "only the task".
  • The checkpoint excerpts are budgeted around the lessons, in encoded bytes, and the complete prompt is checked with the platform accounting. Memory context gives way first. Every excerpt fallback keeps the lessons and the task, and returns its candidates/omitted metadata together with the prompt.
  • Without lessons, prompts are byte-identical to before (the frozen pre_188 fixture still passes).

Recording and showing

  • rounds.conversation_json moves to schema_version 2: lessons.selected (canonical uuids, each once) plus each member's lessons delivery (included / dropped / none). The shared validator keeps strict per-version key sets and accepts v1 records. selected == [] iff every member is none. An older syncmill reports a v2 record as unreadable (noted in CHANGELOG).
  • room compare / room export / TUI Rooms evidence: the round line lists the selected ids and per-candidate deliveries; null for v1 rounds, distinct from a v2 round's []. JSON adds rounds[].conversation.lessons and candidates[].conversation.lessons.

History in resumed conversations

  • A resumed provider conversation keeps what earlier rounds sent it, and syncmill cannot take that back. Leaving a lesson out stops it being sent again; it does not remove it. RoomCoordinator.resumes_with_lesson_history (read-only) is true when the round would resume at least one member's stored session in a room where an earlier v2 round selected lessons. The CLI then adds one note pointing to --fresh-session, and the TUI shows a notify naming the fresh lineage and the CLI flag. The note names no lesson and claims nothing about what a conversation holds. It reflects the room as of the listing, a limit the guides state.
  • TUI-launched rounds send no lessons yet: the TUI cannot show them before execution, which [product] Preserve human selection outcomes and explicitly promote project lessons #174 requires.

Design and review

  • The design went through three Codex design rounds before any code (R3 SHIP).
  • History handling was first a precise per-lesson, per-member warning. Round 2 found three Majors in it: the session boundary, attempted vs confirmed delivery, and preview staleness. The generic note replaced it (option A), with the timing limit documented.
  • Three Codex implementation rounds followed:
    • R1: a Ruff F541, and a TUI note missing its recovery hint.
    • R2: the null worker payload accepted as "no lessons" (Major), plus two doc wordings.
    • R3, unprimed (diff only): SHIP with no findings.
  • Not adopted (R2 Minor): showing lessons none / not recorded in every compact TUI candidate cell. That cell is already a summary that leaves out fields such as candidate ids, and the Details view (conversation_label) carries the full state, so the cell shows lessons only when they were included or dropped.

Tests

  • New tests/test_room_lessons.py (61 tests):
    • placement and preamble;
    • no-candidate layout;
    • checkpoint budgeting around lessons, including multibyte lessons;
    • every excerpt fallback (framing, marker, platform units);
    • round_lessons_fit bounds and round_lessons validation;
    • end-to-end rounds: every member, resuming members, none, dropped, memory gives way first;
    • resumes_with_lesson_history cases;
    • v2 validator acceptance and 14 malformed shapes, with v1 still accepted;
    • compare JSON and labels;
    • worker fd hand-off, staging, spawn and payload failures with cleanup;
    • CLI preview, skip, no-lessons, too-large, history note, board off or unreadable, an end-to-end CLI round through the real coordinator;
    • start forwarding and the --trial refusal.
  • tests/test_tui.py: the launch note, and that a failed history read after launch is never shown as an error.
  • Updated expectations:
    • _record checks the v2 lesson fields;
    • v1 compare fixtures read lessons: null / "not recorded";
    • CLI and start fakes gained a board-off config and the new coordinator methods.
  • Re-rendered docs/assets/tui/11-rooms-details.svg and 12-rooms-compare.svg (the round conversation label grew).
  • 19 mutations of the new code, each caught by a test: the reserve, the preamble switch, the validator rules, the fit check, the session and conversations conditions, the fallbacks, the fd and snapshot cleanup, the preview fit, the detach and worker hand-offs, the start forwarding and the null guard.
  • Full suite via suite-run: CLEAN. The one failure is start: gate discovery names 'makefile' for a Makefile on case-insensitive filesystems #249: test_discovery_reads_known_files_and_never_runs_them fails on case-insensitive filesystems, on main too. ruff check . passes.

Docs

CLAUDE.md, CHANGELOG, docs/user-guide.md + .ko.md (Rooms lessons and the conversation record), docs/architecture/board.md, README.

🤖 Generated with Claude Code

`room round` (foreground and --detach) and `start` now list the
project's approved lessons before a round and take --skip-lesson /
--no-lessons; `start` also forwards them to its single-agent run. The
CLI resolves them and hands (id, text) pairs to
RoomCoordinator.run_round(lessons=); the coordinator never opens the
board. A detached worker receives exactly the listed pairs over a second
anonymous inherited fd and refuses a malformed payload.

Every member gets the lessons each round, after the untrusted peer
checkpoint and right before the task. Checkpoint excerpts are budgeted
around them and memory context gives way first; prompts without lessons
are byte-identical to before. A round prompt that leaves no room for them
is caught in the preview with the coordinator's own fit check.

The round conversation record moves to schema_version 2 with the
selected lesson ids and each member's delivery; readers accept v1.
compare, export and the TUI show them. A resumed conversation keeps what
earlier rounds sent it, so a round that would resume one in a room with
earlier lessons adds a note about --fresh-session. TUI-launched rounds
send no lessons yet and show the same note.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant