#2451

Allow an operator to append to the protocol text returned by mempalace_status

Opensteamtonkopened 1mo ago

Version: mempalace 3.9.0 (PyPI), served via mempalace serve, backend chroma

Summary

The protocol string returned by mempalace_status is hardcoded and cannot be extended. It instructs the reading agent to query the palace before answering and never to guess. An operator who knows their corpus carries a systematic bias has no way to tell the agent that is reading it.

Where

mcp_server.py:2278. No config.json key and no environment variable appends to or overrides it — I checked for MEMPALACE_PROTOCOL, protocol_override, custom_protocol, and environment reads around the string.

Worth noting the boundary falls in a slightly surprising place: topic_wings and hall_keywords are operator-configurable via config.json, so the palace already accepts operator input about how it classifies — just not about how its output should be read.

Why it matters: two independent, measured biases

1. Extraction keeps rules and drops exceptions.

Scoped honestly: one model, at one size, under four schema shapes. Not a claim about extraction in general.

A passage whose entire thesis was a caution had its positive claim extracted on every run (bm25 | is | a FOREIGN-VOCABULARY detector) while the contrast that carried the warning — not a confabulation detector — was dropped in all four.

Attempts to require the missing content made it worse rather than better:

  • a free-text caveats array returned commentary about the note ("The note does not specify...") rather than the warning the note issued;
  • renaming it warnings with an explicit description — imperatives the NOTE ITSELF issues, quote the note, NOT observations about what it omits — produced exactly one item, and it was the forbidden kind;
  • tightening to a {is, is_not} object produced tautologies: is: "below a confabulation at 0.473", is_not: "above a confabulation at 0.473".

minItems: 1 forces presence, not correctness. Notably, the negative predicates in this palace that are trustworthy — do_not_trust, must_not_be_used, should_not_be_used_in, around 38 distinct ones — all appear because the model volunteered them, not because a schema demanded them.

2. Retrieval is dominated by base rate in a skewed corpus.

One wing holds roughly 91% of ~3.4k drawers. total_before_filter reads 20 unscoped against 10 when scoped to a small wing, so the candidate pool is drawn palace-wide and capped. A generic-vocabulary query whose best answer lived in a 10-drawer wing returned 5 of 5 results from the large wing. The relevant drawer scored 0.441 against a top result of 0.486 — marginal on relevance, but rarely in the candidate set to be ranked at all.

These are different mechanisms with different fixes. Both are facts the operator knows and the reading agent cannot.

Why a local patch is not a workaround

The image here is FROM python:3.12-slim + pip install --no-cache-dir mempalace==3.9.0, so editing mcp_server.py in site-packages is discarded by the next image build, silently and with no warning.

More importantly, and this is the part that would rule it out even if it were easy: a protocol that sometimes carries the caveat and sometimes does not is worse than one that never does, because a reader cannot distinguish it from its own absence. The workaround would introduce the exact failure mode the caveat exists to prevent.

Request

A config key (e.g. protocol_append in config.json) or an environment variable whose contents are appended to the protocol payload returned by mempalace_status.

Append rather than replace, so the shipped guidance stays authoritative and the operator's note is strictly additive.

Current mitigation, and its limit

Per-machine context injected at session start — a CLAUDE.md on one machine, memory notes on another. It is durable and it works, but it is per-machine: a machine added later silently has no copy, and nothing reports the gap. That is why the caveat wants to live with the corpus rather than with the reader.

Activity

0

No activity yet.