Tell OrbitPilot not to remember something — honestly, per message (BL-422)
The notice under the chat box
A small line now sits under the OrbitPilot composer, in the docked chat window and the full-page chat alike: "Conversations are remembered so I can help you better", linking to your Memory status page. If your plan does not currently include Chat History as a memory source, the line says that plainly instead — the exact same reason the Memory Status page and OrbitPilot's own ask-time honesty note would give, never a second guess at the same fact. Guests see an invitation to create a free account instead, since nothing of theirs is remembered yet.
Per-message "do not remember"
Next to your own messages — the same icon-cluster style as Catch on OrbitPilot's replies — is a small eye icon. Tap it and that message is marked not remembered. Three things follow, and the owner's own words are the reason for the shape of all three: "if the user is excluding that section for that current and active session... the OrbitPilot for that session and that moment CAN see it because should be able to continue the conversation with the user. But later, when the user is closing the session, then it's going to be excluded from the memory."
- OrbitPilot keeps following the conversation. Excluding a message never removes it from what OrbitPilot can see for the rest of THIS chat — the reply right after it, and anything you ask later in the same session, still has the full thread to work with.
- It never enters long-term memory. At the next memory build (quick update or full rebuild), that message AND the reply that answered it are skipped — they never become a retrievable memory chunk in any later conversation. If an earlier build had already turned that exchange into a chunk, the very next build removes it.
- Nothing is hidden or deleted. The message stays exactly where it was in your conversation history, just tagged "Not remembered" so you can see its status at a glance. There is no purge button — deciding to also erase a message from your own visible history is a separate, bigger decision the owner deliberately left out of this one.
Changing your mind
The toggle works both ways and takes effect at the next memory build, never immediately and never retroactively for a build that already ran. Exclude a message, then re-enable it before the next build runs, and it is remembered exactly as if you had never touched it. Re-enable it AFTER a build already dropped it, and it comes back starting with the build after that — there is no way to reach back and "un-skip" a build that has already happened.
How this works — for admins
Nothing to configure for the per-message toggle — it is available to every
signed-in user; guests have no persistent chat history to exclude anything from. The
notice's wording follows the SAME Source/Plan Assignment setting
(orbitpilot.chat_history) that already controls whether Chat History
feeds a user's memory build at all — turn that off for a plan on the assignment page
and the notice tells that plan's users so, honestly, in the same words the Memory
Status page already uses.
How this works — for developers
OrbitPilotMessage.not_remembered (BooleanField, default False) lives on
the USER turn only — the assistant reply is never flagged separately, because
pipeline/extract.py::_extract_chat_history already pairs each user
message with the assistant message that answered it, and simply skips emitting that
one pair's record when the flag is set. pair_index still advances for a
skipped pair, so every OTHER pair in the same conversation keeps its exact
source_id across builds — excluding one turn never forces a re-embed of
every later turn too.
Toggling the flag writes nothing else. Removal of an already-built chunk happens
naturally at the NEXT build, through services.run_memory_build's existing
replace semantics: the incremental (quick update) path deletes any stored
OrbitPilotMemoryChunk whose (source_key, source_id, chunk_index,
content_hash) key no longer appears in the fresh extraction, and the full
rebuild deletes every chunk before restoring from the new extraction — both already
existed for ordinary content changes, and an excluded chat pair triggers the same
path with no new deletion logic required.
View: orbitpilot.views.orbitpilot_toggle_remember, URL name
orbitpilot_toggle_remember (POST /orbitpilot/message/remember/,
message_id + optional format=json, same dual
AJAX/plain-form response shape as Catch). Icons reuse the EXISTING "view"/"hide"
registry meanings (bi-eye / bi-eye-slash) — the same pair
templates/blink/_memory_status.html already uses for "the AI reads this"
vs. "excluded from AI memory" on a Blink — rather than minting a new icon meaning for
the same idea. Parity pinned by orbitpilot/test_bl422_do_not_remember.py.
The notice's text is deliberately CHEAPER than it first looks, and that
was a real regression caught before it shipped. The first version of
orbitpilot.services.get_chat_memory_notice(user) called
resolve_build_sources — the same function BL-428's Memory Status page and
BL-405's ask-time honesty note use — for full agreement with those pages. That failed
plans.test_capability_cache.CapabilityCacheSavesQueriesTests:
resolve_build_sources calls plans.services.get_plan_for_user
TWICE internally (once directly, once again inside get_effective_limits),
and neither call is wired into plans.capabilities' per-request cache — a
documented, deliberate gap (a per-request memo was tried there once and reverted over
gating-staleness risk). Paying that cost once per ASK was already accepted; paying it
once per PAGE LOAD, for every signed-in user, on every page, is a materially larger
cost this widget must not add. So the shipped version checks only chat_history's OWN
plan assignment — the admin's In-RAG switch and its Source/Plan Assignment row — read
through plans.capabilities.get_user_plan (reuses whatever the page's own
gate checks already cached; degrades to a plain query outside a request, e.g. tests).
It does not reproduce the plan's overall source CAP
(included_sources) — a source can be "assigned" here and still be crowded
out of an actual build by the cap (see the SU-101 Q1 finding below) — which is exactly
why the notice always sits beside a link to the fuller, cap-aware Memory Status page,
a page you visit deliberately, where paying the real cost once is the right trade.
Wired into the template via a new chat_memory_notice template tag in
orbitpilot/templatetags/orbitpilot_extras.py (the widget has no dedicated
view to pass per-user context through).
A note on SU-101 Q1's verify item
The row asked whether orbitpilot.chat_history is actually covered by
the owner's "keep it on" intent. Checked, two findings: chat_history's OWN plan
assignment already reads available on every plan whenever no admin row exists at all
(the registry's default_visible=True is the fallback) — nothing to grant
there. But a SEPARATE mechanism can still exclude it: every plan's
included_sources (the overall knowledge-source cap) defaults to 3, and
several other default-visible sources sort ahead of chat_history in the registry — so
on any plan the owner has not personally raised, resolve_build_sources
fills the cap before reaching chat_history. This is live admin PLAN DATA, not a
chat_history-specific fix, and already the subject of a separate investigation
(BL-419 / SU-106) — so it is reported, not patched, here. Pinned as a regression guard
in orbitpilot/test_bl422_do_not_remember.py
(SU101Q1SourceCoverageTests, SU101Q1SourceCapFindingTests).
Related pages
Docshub: "Memory Status — one page, one truth" (BL-428), "Catch — turn an
OrbitPilot reply into a Blink" (BL-421, the icon-cluster pattern this reuses).
docs/orbitpilot/TASKS.md.