memoryd: a reported turn decided after loopd has its answer, from brokerd and the log
Co-Authored-By: ornith-1.5-35b-a3b <agent@wntrmute.dev>
This commit is contained in:
+65
-16
@@ -368,7 +368,9 @@ that does not parse tool calls, or whose cache does not work.
|
||||
## session-log-damaged
|
||||
|
||||
**What you see.** A turn on an existing session fails with `<file>:<line>: <reason>` naming
|
||||
`sessions/<id>/<epoch>.jsonl`, and this entry. Other sessions work.
|
||||
`sessions/<id>/<epoch>.jsonl`, and this entry. Other sessions work. With `[honcho]`, `memoryd`
|
||||
logs the same line once, starting `memoryd: `, and that session's turns wait undecided for Honcho
|
||||
until the log reads again.
|
||||
|
||||
**Why.** `loopd` replays the log exactly to rebuild the conversation, so a line it cannot read
|
||||
would change what the model sees. It refuses rather than guess. `last line does not end in a
|
||||
@@ -926,23 +928,27 @@ tables and every `[secrets.honcho_…]`.
|
||||
|
||||
## honcho-ledger-damaged
|
||||
|
||||
**What you see.** `memoryd` logs a line naming `memory/honcho.jsonl`, a line number and a reason,
|
||||
then this entry:
|
||||
**What you see.** `memoryd` exits 1 at start, before it binds its sockets, with one line naming
|
||||
`memory/honcho.jsonl`, a line number and a reason, then this entry:
|
||||
|
||||
```text
|
||||
/srv/bx/memory/honcho.jsonl:12: turn 3 of session chat-1: decided already; see docs/runbook.md#honcho-ledger-damaged
|
||||
memoryd: /srv/bx/memory/honcho.jsonl:12: turn 3 of session chat-1: decided already; see docs/runbook.md#honcho-ledger-damaged
|
||||
```
|
||||
|
||||
Or, while it runs, `memoryd: <path>: <error>; see docs/runbook.md#honcho-ledger-damaged` when the
|
||||
ledger cannot be written (a full disk, a wrong owner). The turn waits undecided, and is decided at
|
||||
a later turn's end once the ledger can be written.
|
||||
|
||||
**Why.** The ledger is `memoryd`'s record of what it sends to Honcho: one line when a turn or a
|
||||
memory write is decided (where it goes, or that it goes nowhere), and one when it is sent or
|
||||
refused (M5c spec, section 5). What is decided and not yet sent is the outbox. `memoryd` reads the
|
||||
ledger through at start so that it sends nothing twice and nothing to a workspace it was not
|
||||
decided for. A line it cannot read, or one that breaks the ledger's rules, could do either, so it
|
||||
does not guess: it does not start its Honcho sync, and nothing is decided or sent to Honcho until
|
||||
the ledger reads through. The rules: an item is decided once (`decided already`), and it is sent
|
||||
or refused once, only after it is decided and only when it was not decided to go nowhere (`not
|
||||
waiting to be sent`). A last line cut off by a crash is not damage: `memoryd` drops it and says so
|
||||
in its log.
|
||||
does not guess: it does not start. While it is stopped no memory is served either, and `loopd`
|
||||
cannot start a session (`memory-unavailable`). The rules: an item is decided once (`decided
|
||||
already`), and it is sent or refused once, only after it is decided and only when it was not
|
||||
decided to go nowhere (`not waiting to be sent`). A last line cut off by a crash is not damage:
|
||||
`memoryd` drops it and says so in its log.
|
||||
|
||||
**Confirm.** Look at the line named, and at every line of the same item:
|
||||
|
||||
@@ -952,12 +958,55 @@ sed -n '<line>p' "$f"
|
||||
grep -n '"session":"<id>","turn":<n>}' "$f" # a turn; for an edit: '"id":"<id>","part":<n>}'
|
||||
```
|
||||
|
||||
**Fix.** Keep a copy first: `cp -a "$f" "$f.damaged-$(date +%s)"`. The ledger is written only by
|
||||
`memoryd`, so a damaged line was changed by hand or by the disk. If you know what the line should
|
||||
say, correct it. Otherwise remove it (`sed -i '<line>d' "$f"`), knowing what that costs: a removed
|
||||
`sent` or `failed` line means the item is sent again (a turn's messages appear twice in Honcho, a
|
||||
conclusion is made twice); a removed `decided` line means the item is decided again, and any
|
||||
later `sent` or `failed` line of the same item then breaks the rules, so remove those too. Honcho
|
||||
cannot delete a message, so a turn sent twice stays twice.
|
||||
**Fix.** If the ledger cannot be written, free space or correct the owner of `memory/`
|
||||
(`df -h`, `ls -l "$f"`); nothing else is needed. For a damaged line, keep a copy first:
|
||||
`cp -a "$f" "$f.damaged-$(date +%s)"`. The ledger is written only by `memoryd`, so a damaged line
|
||||
was changed by hand or by the disk. If you know what the line should say, correct it. Otherwise
|
||||
remove it (`sed -i '<line>d' "$f"`), knowing what that costs: a removed `sent` or `failed` line
|
||||
means the item is sent again (a turn's messages appear twice in Honcho, a conclusion is made
|
||||
twice); a removed `decided` line means the item is decided again, and any later `sent` or
|
||||
`failed` line of the same item then breaks the rules, so remove those too. Honcho cannot delete a
|
||||
message, so a turn sent twice stays twice.
|
||||
|
||||
**Check.** `memoryd` starts, and its log has no line with this entry.
|
||||
|
||||
## broker-state-unavailable
|
||||
|
||||
**What you see.** `memoryd` logs one line when it cannot get a session's state from `brokerd`,
|
||||
then this entry:
|
||||
|
||||
```text
|
||||
memoryd: /srv/bx/run/memory-broker/state.sock: Connection refused (os error 111); turns wait undecided; see docs/runbook.md#broker-state-unavailable
|
||||
```
|
||||
|
||||
The reason may instead be `No such file or directory` (nothing listens), a timeout
|
||||
(`frame I/O error: Resource temporarily unavailable`, after 5 seconds without a byte), or
|
||||
`brokerd: <its error>` when `brokerd` answered with an error. When `brokerd` answers again,
|
||||
`memoryd` logs `memoryd: brokerd answers on its state socket again; turns are decided`.
|
||||
Conversations are not affected.
|
||||
|
||||
**Why.** With `[honcho]`, `memoryd` decides where each finished turn goes in Honcho: the trusted
|
||||
workspace, the untrusted one, or nowhere (M5c spec, section 5). It needs `brokerd`'s record of the
|
||||
session's class and trust for that, and never guesses it: a guess could put a turn from a session
|
||||
that read a web page in the trusted workspace. So nothing is decided while `brokerd` does not
|
||||
answer. The turns wait, in memory, and are decided at the next turn's end of any session once
|
||||
`brokerd` answers, from the session's state then (which can only have moved towards untrusted).
|
||||
The outage is logged once, not at every turn. A restart of `memoryd` forgets the waiting turns
|
||||
until each of their sessions has another turn.
|
||||
|
||||
**Confirm.**
|
||||
|
||||
```sh
|
||||
ls -l "$BOXMAKER_HOME/run/memory-broker/state.sock"
|
||||
grep -n 'state' /etc/boxmaker/memoryd.toml /etc/boxmaker/brokerd.toml
|
||||
```
|
||||
|
||||
`memoryd`'s `[sockets] state` and `brokerd`'s `[sockets] state` must name the same path (both
|
||||
default to `<home>/run/memory-broker/state.sock`). If `brokerd` answered with an error, its own
|
||||
log names the problem, usually `broker-state-damaged`.
|
||||
|
||||
**Fix.** Start `brokerd` if it is stopped; make the two `[sockets] state` paths agree; or, for
|
||||
`brokerd`'s error, follow the entry its log names.
|
||||
|
||||
**Check.** At the next turn's end `memoryd` logs that `brokerd` answers again, and
|
||||
`memory/honcho.jsonl` gains a `decided` line for each turn that waited.
|
||||
|
||||
Reference in New Issue
Block a user