Eight closed tasks for epochs and compaction, then ten for the scheduler, ToolSummary, and tiers. Given tests first. Gate 1456 → 1507 → 1572. Co-Authored-By: Grok 4.6 <noreply@x.ai>
6.7 KiB
M5d-1 task 03: the carried summary in the next epoch's prefix
Branch: m5d1. Check it: git branch --show-current prints m5d1 and git status --short
is empty; otherwise stop. Never switch branch.
Commit subject: loopd: replay a carried summary as an unlogged user message
Log row: the Task cell is M5d1/03-loopd-carry-messages.
Goal
For epoch n > 0, the request prefix is the new system message, then one ChatMessage::User
whose content is a fixed heading plus the carry, then the new epoch's records (spec 3.5). That
user message is not a LogRecord::User: it is not a turn, not reported to Honcho, and not
counted by turns(). Epoch 0 is unchanged (carry is None).
run_turn must send this prefix, or a compacted session's next live turn would omit the
summary.
Every place that changes
| Place | What happens there |
|---|---|
crates/loopd/src/baseline.rs |
CARRY_HEADING; messages_with_carry; messages calls it with None |
crates/loopd/src/turn.rs |
the request uses messages_with_carry and session.carry() |
crates/loopd/tests/carry_messages.rs |
new, given |
| everything else | no change: not the existing baseline tests (they still call messages) |
Files
- Copy, from
docs/plans/M5d1/files/(the same path under it): the new testcrates/loopd/tests/carry_messages.rs. - Modify:
crates/loopd/src/baseline.rs,crates/loopd/src/turn.rs,docs/implementer-log.md. - Do not touch: any other file.
Facts you need
-
The heading is built from pieces so no file holds a chat-template tag whole (T33):
pub const CARRY_HEADING: &str = concat!("Earlier ", "turns, summarised:");The user content is
format!("{CARRY_HEADING}\n\n{carry}")whencarryisSome.Noneinserts nothing. -
messagesstays. Existing tests andlimits.rscallmessages(baseline, records). Make itmessages_with_carry(baseline, records, None)so those tests do not change. -
run_turntoday (one place):messages: messages(baseline, session.records()),It must pass
session.carry().Session::carryisOption<&str>from task 02. -
Insert the carry user after the system message and before walking
records. -
The items the edits use. This table is complete.
Item What it does concat!heading from pieces Session::carry(&self) -> Option<&str>task 02 ChatMessage::User { content }the carry, and log users
The edits, exactly
crates/loopd/src/baseline.rs
B1. After the Baseline impl, replace messages. The lines
/// The system message, then each log record replayed in order. Every record variant is named, so a
/// new one is a compile error rather than a silent skip.
pub fn messages(baseline: &Baseline, records: &[LogRecord]) -> Vec<ChatMessage> {
let mut out = vec![ChatMessage::System {
content: baseline.system.clone(),
}];
for record in records {
become
/// The heading in front of a carried summary. Built from pieces (T33).
pub const CARRY_HEADING: &str = concat!("Earlier ", "turns, summarised:");
/// The system message, then each log record replayed in order. Every record variant is named, so a
/// new one is a compile error rather than a silent skip.
pub fn messages(baseline: &Baseline, records: &[LogRecord]) -> Vec<ChatMessage> {
messages_with_carry(baseline, records, None)
}
/// Like `messages`, and when `carry` is `Some` inserts one user message after the system
/// prompt: the heading, a blank line, the summary. That user is not a `LogRecord::User`.
pub fn messages_with_carry(
baseline: &Baseline,
records: &[LogRecord],
carry: Option<&str>,
) -> Vec<ChatMessage> {
let mut out = vec![ChatMessage::System {
content: baseline.system.clone(),
}];
if let Some(summary) = carry {
out.push(ChatMessage::User {
content: format!("{CARRY_HEADING}\n\n{summary}"),
});
}
for record in records {
The rest of the match is unchanged; do not touch it.
crates/loopd/src/turn.rs
T1. The use line
use crate::baseline::messages;
becomes
use crate::baseline::messages_with_carry;
T2. The lines
let request = ChatRequest {
slot: rt.cfg.slots.main,
messages: messages(baseline, session.records()),
tools: baseline.tools.clone(),
thinking: true,
};
become
let request = ChatRequest {
slot: rt.cfg.slots.main,
messages: messages_with_carry(baseline, session.records(), session.carry()),
tools: baseline.tools.clone(),
thinking: true,
};
Steps
-
1. Copy the given test.
cp docs/plans/M5d1/files/crates/loopd/tests/carry_messages.rs crates/loopd/tests/ -
2. See it fail.
cargo build --tests --keep-going -p loopd, timeout 600000 ms: test targetcarry_messagesdoes not compile (E0432unresolved importloopd::baseline::{CARRY_HEADING, messages_with_carry}). Every other target compiles. -
3. The edits. B1, T1, T2.
cargo check -p loopdprints no error and no warning. -
4. The tests.
cargo test -p loopd --test carry_messages --test baseline --test turn: every test passes, 5 incarry_messagesand the others as before. -
5. Check.
git diff --statlists exactlycrates/loopd/src/baseline.rsandcrates/loopd/src/turn.rs. -
6. Run the gate.
cargo fmt --all, thenmake gate, timeout 600000 ms. Last linegate: ok. Test count 1478 (1473 before, plus 5). -
7. Log and commit. Task cell
M5d1/03-loopd-carry-messages. Stage withgit add crates/loopd docs/implementer-log.md Cargo.lock, then commit asAGENTS.mdsays.
Done when
make gateprintsgate: okwith 1478 tests.git diff HEAD~1 --statlists onlycrates/loopd/src/baseline.rs,crates/loopd/src/turn.rs,crates/loopd/tests/carry_messages.rsanddocs/implementer-log.md.
Stop and report if
- The branch check fails; a "before" block is not found exactly once; step 2 differs;
cargo checkwarns; a test fails; the gate count is not 1478; a comment does not fit its code. - You think
messagesshould insert the carry. It must not: existing tests callmessagesand would see an extra user.run_turnis the one call that must passsession.carry().
What the given tests pin
Epoch 0 with None matches messages; a carry is a user after the system prompt and before the
epoch's users; the carry is not in the log records; the heading is the concat! pieces; the
first request of epoch 1 is not a prefix-extension of epoch 0's messages.