Files
boxmaker/docs/plans/M5d2/02-bxcore-tool-summary.md
T
kyleandGrok 4.6 2a48b7f36d docs: M5d-2: after gate: ok, do not sum test results
Task 01 told Ornith to add up every `test result:` N passed. A greedy
sed kept the last digit (1512 became 1022) and it stopped with the
correct T1 and given test uncommitted. T50/T59: the last line of
make gate is the count; summing is not a stop.

Co-Authored-By: Grok 4.6 <noreply@x.ai>
2026-10-03 12:56:14 -07:00

6.1 KiB

M5d-2 task 02: LogRecord::ToolSummary

Branch: m5d2. Check it: git branch --show-current prints m5d2 and git status --short is empty; otherwise stop. Never switch branch. Commit subject: bxcore: ToolSummary log record; messages ignore it Log row: the Task cell is M5d2/02-bxcore-tool-summary.

Goal

A tool that opts in gets a second record, for the index only (spec 4.3):

LogRecord::ToolSummary { time, call, tool_call_id, content, class, untrusted }

JSON type tool_summary. messages() / messages_with_carry ignore it, so the epoch's prefix does not change. support/turn.rs types names it (T19: this task ships its own copy).

Nothing summarises yet. That is task 08.

Every place that changes

Place What happens there
crates/bxcore/src/log.rs the variant, after ToolResult (edit L1)
crates/loopd/src/baseline.rs ignore arm (edit B1)
crates/loopd/tests/support/turn.rs replaced, given
crates/bxcore/tests/tool_summary.rs new, given
crates/loopd/tests/tool_summary_messages.rs new, given
everything else no change: not index.rs (task 09), not turn.rs

memoryd/src/index.rs index_record already has _ => {}. It compiles. Summaries are skipped until task 09.

Files

  • Copy, from docs/plans/M5d2/files/ (the same path under it): the new tests crates/bxcore/tests/tool_summary.rs and crates/loopd/tests/tool_summary_messages.rs, and the replacement crates/loopd/tests/support/turn.rs.
  • Modify: crates/bxcore/src/log.rs, crates/loopd/src/baseline.rs, docs/implementer-log.md.
  • Do not touch: any other file.

Facts you need

  • Field order is the wire format. time, call, tool_call_id, content, class, untrusted. No truncated: a summary is already capped.
  • Unknown fields are errors, as on every LogRecord variant (deny_unknown_fields is on the enum).
  • types is exhaustive. Adding the variant without the replacement support/turn.rs fails to compile turn / limits tests. Copy the given file over the existing one. The only intended change is the ToolSummary => "tool_summary" arm. Setup::turn still returns (Result<TurnOutcome, TurnError>, Vec<TurnEvent>).
  • messages names every variant. The new arm is empty, like Usage / CacheLoss / EpochEnd.
  • The items the edits use. This table is complete.
    Item What it does
    CallId already imported in log.rs
    DataClass already imported in log.rs

The edits, exactly

Each quoted "before" block occurs exactly once after task 01.

crates/bxcore/src/log.rs

L1. After the ToolResult variant (the lines)

        truncated: bool,
    },
    Usage {

become

        truncated: bool,
    },
    ToolSummary {
        time: Timestamp,
        call: CallId,
        tool_call_id: String,
        content: String,
        class: DataClass,
        untrusted: bool,
    },
    Usage {

Keep the fields in that order.

crates/loopd/src/baseline.rs

B1. After the ToolResult arm (the lines)

            } => out.push(ChatMessage::Tool {
                tool_call_id: tool_call_id.clone(),
                content: content.clone(),
            }),
            LogRecord::Usage { .. } => {}

become

            } => out.push(ChatMessage::Tool {
                tool_call_id: tool_call_id.clone(),
                content: content.clone(),
            }),
            LogRecord::ToolSummary { .. } => {}
            LogRecord::Usage { .. } => {}

Steps

  • 1. Copy the given files. From the repository root:

    cp docs/plans/M5d2/files/crates/bxcore/tests/tool_summary.rs crates/bxcore/tests/
    cp docs/plans/M5d2/files/crates/loopd/tests/tool_summary_messages.rs crates/loopd/tests/
    cp docs/plans/M5d2/files/crates/loopd/tests/support/turn.rs crates/loopd/tests/support/turn.rs
    
  • 2. See them fail. cargo build --tests --keep-going -p bxcore -p loopd, timeout 600000 ms: tool_summary and tool_summary_messages do not compile (E0599 no variant ToolSummary). support/turn.rs does not compile for the same reason until L1. After L1 and before B1, baseline.rs fails (non-exhaustive patterns). Do L1 then B1 in step 3; this step is the first cargo build against the given tests only, which is E0599.

  • 3. The edits. Make L1 then B1. cargo check -p bxcore -p loopd prints no error and no warning.

  • 4. The tests. cargo test -p bxcore --test tool_summary --test records and cargo test -p loopd --test tool_summary_messages --test turn --test baseline --test session_slot: every test passes, 3 in tool_summary, 3 in tool_summary_messages.

  • 5. Check. git diff --stat lists crates/bxcore/src/log.rs, crates/loopd/src/baseline.rs, crates/loopd/tests/support/turn.rs.

  • 6. Run the gate. cargo fmt --all, then make gate, timeout 600000 ms. Last line gate: ok. Test count 1518 (1512 before, plus 6). After gate: ok, do not add up test result: lines.

  • 7. Log and commit. Task cell M5d2/02-bxcore-tool-summary. Stage with git add crates/bxcore crates/loopd docs/implementer-log.md Cargo.lock, then commit as AGENTS.md says.

Done when

  • make gate prints gate: ok with 1518 tests.
  • git diff HEAD~1 --stat lists only crates/bxcore/src/log.rs, crates/bxcore/tests/tool_summary.rs, crates/loopd/src/baseline.rs, crates/loopd/tests/tool_summary_messages.rs, crates/loopd/tests/support/turn.rs and the log.

Stop and report if

  • The branch check fails; a "before" block is not found exactly once; step 2 differs; cargo check warns; a test fails; the gate's last line is not gate: ok; you replay a summary as a User or Tool message; you add truncated; you change Setup::turn's return type.

What the given tests pin

JSON type is tool_summary; unknown fields are refused; field order is the struct order; messages() with and without a summary are equal; a summary is not a tool message; inserting a summary between a result and a later user does not break prefix extension.