92c612b94c
Four defects found by end-to-end testing, not by reading the code. 1. Extraction never ran, silently. Collecting every event type that ctx.event.subscribe actually delivers shows `session.idle` is NOT among them — it is defined in the protocol but never emitted on this stream. The subscription filtered on it alone, so auto-extraction was a permanent no-op with no error. Now debounced off events that do arrive (session.step.started / session.tool.called / session.inbox.delivered) after `settleMs` of quiet, which is what "idle" meant anyway. Verified: the trigger now fires and reports "轮数不足" for a 1-turn session. 2. Dedupe silently stopped rejecting duplicates. It compared against a fixed retrieval score, but that score carries idf and scope priors that drift as the corpus grows, so an obvious restatement of an existing memory scored 0.48 against a 0.9 threshold and was written as a rival entry. Now uses term coverage of the candidate, which answers "is this already said?" and does not move with corpus size. Verified: a 100%-duplicate is rejected, a novel pitfall is kept. 3. Harness-injected user turns became the retrieval query. "<system-reminder>" and "The server restarted while you were working" are user-role messages, so the hook retrieved on them and injected memories chosen by noise. Both are filtered out now. 4. The `pinned` flag was absent from the remember tool's input schema, so the schema stripped it and pinning was unreachable from the tool surface. `kind` also ignored the rules/ category when a stale value was stored. memory_inspect now reports runtime health for the two paths with no other observable effect: last injection size and query, and last extraction outcome with its reason. Without it, "working" and "silently dead" look identical — which is exactly how defects 1 and 2 survived the first round of testing.
312 B
312 B