fix: route reflection mapped rows through admission control and ground the distiller prompt#931
Open
gorkem2020 wants to merge 3 commits into
Open
Conversation
The distiller's four mapped headings (User model deltas, Agent model deltas, Lessons & pitfalls, Decisions) become ordinary durable memory rows via bulkStore with no admission gate, no gating knob, and no audit trail; reflectionStoreToLanceDB gates only the document writer. A contaminated or hallucinated distillate line therefore landed directly as a confirmed memory. Gate each mapped row through the same AdmissionController instance the smart extractor uses (new SmartExtractor accessors), scoring legacy mapped categories under the smart registers admission priors are keyed by: user/agent model deltas as preferences, lessons as cases, decisions as events. Rejected rows are skipped with the audit reason logged; admitted rows persist the audit (tagged provenance memory-reflection-mapped) in their metadata when auditMetadata is on. Behavior is unchanged when admission control is disabled, and the gate fails open on infra errors so a transient store or LLM failure cannot suppress reflection persistence. Also add a grounding rule to the distiller prompt (in-fiction or test-frame claims must never appear under the four mapped headings), export buildReflectionPrompt for prompt-content tests, and mark the caller-less mapped-rows reader in reflection-store with a comment. Wire the new regression suite into the local npm test chain and the core-regression CI group.
Dead reader, cross-writer double-store, memory_layer parity question, and the auto-capture watermark pointer, kept as PR discussion material.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Reflection mapped rows bypass admission control entirely. On
/reset, the distiller's markdown sections (User model deltas, Agent model deltas, Lessons and pitfalls, Decisions) are mapped to ordinary user-memory rows (preference,fact,decision) and written viabulkStorewith no gate, while extraction candidates from the same conversation go through the full admission pipeline. Anything the distiller writes into those sections becomes durable user memory unconditionally, and generic semantic recall serves it back as fact.Live demonstration: a roleplay session's fictional canon ("favorite drink is plasma coffee") passed through the reflection door into bare
preferencerows and was asserted back to the user as fact on the next session, while the extraction door correctly suppressed the identical content.Fix
Two layers:
AdmissionControllerinstance the extractor uses before storage (newreflection-mapped-admissionmodule; the controller is exposed via an accessor on the extractor). Rejected rows are skipped with the reason logged; admitted rows persist the full admission audit in metadata withprovenance: "memory-reflection-mapped". For scoring, mapped categories are resolved to the smart registers the type priors expect (model deltas as preferences, lessons as cases, decisions as events). Behavior is unchanged when admission control is disabled, and infrastructure errors fail open so a transient failure cannot suppress reflection persistence.A known limitation is documented in code and in
docs/notes/reflection-write-path-findings.md: with smart extraction disabled there is no controller instance to borrow, so that configuration keeps the legacy ungated write. The notes file also records adjacent findings for discussion (the caller-less mapped-rows reader, cross-writer double-store of durable decision bullets, and thememory_layerlabeling asymmetry between subsystems).Tests
8 cases: admitted and denied mapped-row paths, admission-disabled passthrough, error fail-open, and prompt-content assertions for the new distiller rule.
Verification on a live gateway
Deployed and exercised end-to-end: a reset over a session containing a genuine lesson produced a mapped
factrow carrying a complete admission audit in its metadata (decisionpass_to_dedup, score 0.685, five feature scores, compared-row ids, provenance tag), and a reset over a fiction-framed session produced empty durable sections with the fiction confined to Context.