Files
boxmaker/docs/plans/M5a/19-review-ids.md
T
kyleandClaude Opus 5.5 0a7a95d709 M5a plan: task 19, a staged write never reuses an id
review::submit counted only the writes still waiting, so a write staged
after an accepted one got that one's id and was lost: never listed, never
acceptable. It now counts every Waiting line of the day. On a scratch tree
with task 16's line applied, both new tests fail and then pass, the old code
and a count of every line are both caught, and the gate passes (938 there;
941 after task 18).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 16:41:44 -07:00

3.1 KiB

M5a task 19: a staged write never reuses an id

Branch: m5a (run git switch m5a; git status --short must be empty, otherwise stop) Commit subject: memoryd: a staged write's id counts every write staged that day

Goal

A fix for a bug the M5a review found (2026-09-24). When review is on, review::submit gives each staged write an id, p-<day>-NNNN, numbered by how many writes that day already have one. It counted only the writes still waiting. So once p-2026-09-24-0001 had been accepted, the next write that day was given p-2026-09-24-0001 again. waiting treats every id with an Accepted line as done, so that write never showed in bxctl memory pending and could not be accepted or rejected: it was lost, while the model was told it was waiting for review.

The fix counts every Waiting line in pending.jsonl, done or not, so an id is never used twice. The comment above says the same, more plainly than before.

Files

  • Copy: the new test crates/memoryd/tests/review_ids.rs, from docs/plans/M5a/files/ (the same path under it)
  • Modify: crates/memoryd/src/review.rs, docs/implementer-log.md

The edits, exactly

Both are in submit in crates/memoryd/src/review.rs. Nothing else in the file changes; waiting does not change, since list, accept and reject still use it.

1. The comment lines

    // 2. `day` is the first 10 characters of `ctx.now.to_rfc3339()`. `taken` = how many Waiting
    //    lines have an id starting format!("p-{day}-"). The id is format!("p-{day}-{:04}", taken +
    //    1).

become

    // 2. `day` is the first 10 characters of `ctx.now.to_rfc3339()`. `taken` = how many Waiting
    //    lines of `lines(store)?`, done or not, have an id starting format!("p-{day}-"): an id is
    //    never used twice. The id is format!("p-{day}-{:04}", taken + 1).

2. The line

    let taken = waiting(store)?

becomes

    let taken = lines(store)?

The .iter(), .filter(..) and .count() lines after it stay as they are.

Steps

  • 1. Copy the test: cp docs/plans/M5a/files/crates/memoryd/tests/review_ids.rs crates/memoryd/tests/
  • 2. See it fail. cargo test -p memoryd --test review_ids. Expected: both tests fail, a_write_staged_after_an_accepted_one_gets_a_new_id_and_can_be_accepted and ids_count_every_write_staged_that_day_waiting_or_done.
  • 3. Make the two edits. Run cargo fmt --all.
  • 4. See it pass. cargo test -p memoryd --test review_ids: both pass. Then cargo test -p memoryd: every suite passes.
  • 5. Run the gate. make gate. Expected last line: gate: ok, with 941 tests (939 before this task, plus the two new ones).
  • 6. Log and commit. git add crates/memoryd docs/implementer-log.md && git commit

Done when

  • make gate prints gate: ok with 941 tests.

Stop and report if

  • Either quoted block is not in the file exactly as shown.
  • Step 2 shows a different result than two failures.
  • A test other than these two fails after the edits. Do not change a test.