# M5d-2 task 01: `run_turn` sends `session.slot()` **Branch:** `m5d2`. Check it: `git branch --show-current` prints `m5d2` and `git status --short` is empty; otherwise stop. Never switch branch. **Commit subject:** `loopd: live turns use the session's slot` **Log row:** the Task cell is `M5d2/01-loopd-session-slot`. ## Goal Heartbeat and cron run on the background slot (spec 4). Live Mattermost and `bxctl chat` sessions keep `cfg.slots.main`. Today `run_turn` always sends `slots.main`. This task makes it send `session.slot()`: the slot stored on that session's `SessionStart` (M5d-1 task 02). Nothing else changes. Compaction's summary call already uses `slots.background`. The scheduler does not exist yet. ## Every place that changes | Place | What happens there | |---|---| | `crates/loopd/src/turn.rs` | `ChatRequest.slot` is `session.slot()` (edit T1) | | `crates/loopd/tests/session_slot.rs` | new, given | | everything else | **no change**: not `session.rs`, not `compact.rs`, not channel | ## Files - Copy, from `docs/plans/M5d2/files/` (the same path under it): the new test `crates/loopd/tests/session_slot.rs`. - Modify: `crates/loopd/src/turn.rs`, `docs/implementer-log.md`. - Do not touch: any other file. ## Facts you need - **`Session::slot()`** returns the `u32` stored on create / on the current epoch's `SessionStart`. It is already `pub` (M5d-1 task 02). - **`messages_with_carry`** stays as it is. Only the `slot:` line changes. - **Existing turn tests** create sessions with `cfg.slots.main` (0). They still send 0. - The items the edits use. This table is complete. | Item | What it does | |---|---| | `Session::slot` | the live slot for this session | | `ChatRequest.slot` | becomes `id_slot` on the wire | ## The edits, exactly Each quoted "before" block occurs exactly once after M5d-1 task 08. ### `crates/loopd/src/turn.rs` **T1.** The lines ```rust let request = ChatRequest { slot: rt.cfg.slots.main, messages: messages_with_carry(baseline, session.records(), session.carry()), tools: baseline.tools.clone(), thinking: true, }; ``` become ```rust let request = ChatRequest { slot: session.slot(), messages: messages_with_carry(baseline, session.records(), session.carry()), tools: baseline.tools.clone(), thinking: true, }; ``` ## Steps - [ ] **1. Copy the given test.** From the repository root, one command: ```sh cp docs/plans/M5d2/files/crates/loopd/tests/session_slot.rs crates/loopd/tests/ ``` Then `git status --short` lists one new file, `crates/loopd/tests/session_slot.rs`. - [ ] **2. See it fail.** `cargo test -p loopd --test session_slot`, with a shell timeout of 600000 ms: the four tests compile (they call `session.slot()`, which exists) and `a_session_created_on_the_background_slot_sends_that_slot` fails: `id_slot` is `0`, not `1`. `a_main_slot_session_still_sends_main` may pass. `the_request_slot_follows_session_start_not_the_config_main` fails: `id_slot` is `0`, not `7`. - [ ] **3. The edit.** Make edit T1. `cargo check -p loopd` prints no error and no warning. - [ ] **4. The tests.** `cargo test -p loopd --test session_slot --test turn --test channel --test compact_turn`: every test passes, 4 in `session_slot` and the others as before. - [ ] **5. Check.** `git diff --stat` lists exactly `crates/loopd/src/turn.rs`. - [ ] **6. Run the gate.** `cargo fmt --all`, then `make gate`, with a shell timeout of 600000 ms. Expected last line: `gate: ok`. The test count is **1511** after this task, 1507 before it, and the 4 new ones are the tests of `session_slot.rs`. To count, add up the `N passed` of every `test result:` line the gate's `cargo test --workspace` printed, and add 1. Never run the gate again only to count. - [ ] **7. Log and commit.** Add your row to `docs/implementer-log.md`; its Task cell is `M5d2/01-loopd-session-slot`. Stage with `git add crates/loopd docs/implementer-log.md Cargo.lock`, then commit as `AGENTS.md` says. `Cargo.lock` does not change in this task; the `git add` is harmless. ## Done when - `make gate` prints `gate: ok` with 1511 tests. - `git diff HEAD~1 --stat` lists only `crates/loopd/src/turn.rs`, `crates/loopd/tests/session_slot.rs` and `docs/implementer-log.md`. ## Stop and report if - The branch check at the top fails. - A "before" block is not in its file exactly as shown, or is there more than once. - Step 2 shows a different result: the tests do not compile, or a different assertion fails. - `cargo check` in step 3 prints an error or a warning. Quote it, and stop. - A test fails in step 4. Do not change the test: stop, and give the failing tests' names and their messages. - The fix seems to need a change anywhere else. It does not; stop and say why you think so. - A test outside `session_slot.rs` fails in the gate: check once whether it fails without your change (`git stash -u`, run it, `git stash pop`), then stop and report both results. - The gate passes with a count other than 1511. ## What the given tests pin A session created with `cfg.slots.background` sends that slot; one created with `cfg.slots.main` still sends main; a session created with slot `7` sends `7` even when `cfg.slots.main` is `0`; a heartbeat turn between two main turns does not change the main session's message prefix.