loopd: compact summary on the background slot

Co-Authored-By: ornith-1.5-35b-a3b <agent@wntrmute.dev>
This commit is contained in:
2026-10-03 00:14:03 -07:00
co-authored by ornith-1.5-35b-a3b
parent 32e81b51fb
commit c8b0a01c41
4 changed files with 245 additions and 1 deletions
+36
View File
@@ -1156,3 +1156,39 @@ sources), or remove the table if the workspace needs no key, then restart `memor
**Check.** After the restart the waiting turns are sent, no line names this entry, and `bxctl
memory sync` shows no `key refused` line.
## session-compact-failed
**What you see.** `loopd` logs that it could not compact a session, then this entry. The session
stays on its current epoch. A turn that was already too large to fit (`session_full`) stays
`session_full`. A turn that finished stays finished; the next turn on that session may be
`session_full` if it would not fit.
```text
loopd: could not compact session chat-0-0: compact.md: No such file or directory (os error 2); see docs/runbook.md#session-compact-failed
```
**Why.** Compaction needs a summary of the current epoch (a completion on the background slot
with `compact.md` as the last user message, or the fallback of that epoch's owner texts). If the
prompt file cannot be read, the summary call fails for a reason other than a full context, or
writing the next epoch's files fails, `loopd` refuses to guess a prefix. It does not start a new
epoch from an empty summary when the model call failed.
**Confirm.**
```sh
ls -l "$(dirname "$BOXMAKER_HOME/../config")/compact.md" 2>/dev/null
ls -l "$BOXMAKER_HOME/sessions/<id>"/
tail -n 5 "$BOXMAKER_HOME/sessions/<id>/0.jsonl"
```
`compact.md` lives next to `system.md` (the path in `loopd.toml`'s `[baseline] system`). A last
line of type `epoch_end` without `<n>.baseline.json` and `<n>.jsonl` is a compact that stopped
halfway; the next compact resumes it.
**Fix.** Restore `compact.md` beside `system.md` (the starter is `config/compact.md` in the
repository). Check that `inferproxy` still answers. If the session directory is mid-write, do not
delete `EpochEnd`; the next compact continues from it.
**Check.** The next turn on that session either runs on the current epoch, or compact succeeds
and the next turn's log is `<n>.jsonl` with `epoch` n.