fix: classify reflection writer-1 mapped rows as source reflection, not legacy#950
Conversation
c9278bf to
cbd55a1
Compare
…ce: reflection parseSmartMetadata's missing-source fallback only mapped "memory-reflection" / "memory-reflection-item" types to source "reflection". Writer-1 mapped rows (buildReflectionMappedMetadata) carry type: "memory-reflection-mapped" and write no source field at all, so every mapped row fell through to "legacy" instead -- visible anywhere source is displayed or used, including the memory-consolidate source legend. - add "memory-reflection-mapped" to parseSmartMetadata's type-based fallback map - stamp source: "reflection" at write time in buildReflectionMappedMetadata too, so newly-written rows carry it explicitly and don't depend on the read-path fallback - pin the knock-on: reclassifying a mapped row's source as "reflection" also changes its derived memory_layer from durable/working to "reflection" (deriveDefaultLayer treats source: "reflection" specially)
cbd55a1 to
0e3b172
Compare
app3apps
left a comment
There was a problem hiding this comment.
Reviewed head 0e3b172. Correcting the displayed/source provenance from legacy to reflection is reasonable, and the build, full suite, six focused tests, and GitHub CI pass.
There is one blocking semantic regression in the coupled layer change. parseSmartMetadata now classifies every historical type: "memory-reflection-mapped" row without an explicit source as source: "reflection"; deriveDefaultLayer consequently returns memory_layer: "reflection". New rows take the same path because buildReflectionMappedMetadata now stamps that source. At index.ts:3480, auto-recall governance unconditionally filters every row whose layer is reflection.
These mapped user-model, preference, lesson, and decision rows are described by this PR as durable memories. The exported loadReflectionMappedRowsFromEntries reader has no production caller (its only references outside its definition are tests), so ordinary auto-recall is currently their automatic prompt-injection path. This PR therefore retroactively and prospectively makes the mapped durable rows disappear from auto-recall. The new test explicitly pins the layer transition but never exercises that consumer.
Please keep the corrected source: "reflection" provenance while preserving the mapped rows' category-based durable/working layer, or first wire a dedicated production injection path that replaces ordinary auto-recall. Add an end-to-end regression proving a mapped durable row remains automatically recallable after parsing/storage.
|
Confirmed on a live deployment, good catch. Rows carrying the new reflection source classification are excluded by the recall governance layer filter, and the inheritance injection does not cover them (it ships slice rows only), so mapped rows become invisible to auto-recall while remaining tool-searchable. A fix will land on this PR in the coming days: mapped rows will be stored with a recall-visible layer/state, while the governance exclusion stays scoped to slice rows, whose double-injection avoidance is its legitimate purpose. We will re-verify with the same live probe after the change. Update: the fix is now on this PR in f03ff73. Rather than stamping a layer at write time, |
Classifying writer-1 mapped rows as source: reflection had a knock-on: deriveDefaultLayer treats reflection-source rows as layer "reflection", and mapped rows write no explicit memory_layer field, so every judge-admitted mapped row derived into the reflection layer and was dropped by both recall paths (auto-recall governance and manual recall exclude that layer). Confirmed live: rows present in the store, absent from the injected relevant-memories block. Mapped rows are general-pool memories; their reflection source is provenance, not residence. deriveDefaultLayer now takes the row type and derives category-appropriate general-pool layers (durable/working) for memory-reflection-mapped rows. Deriving at parse time (rather than stamping a layer at write time) keeps one derivation source of truth and heals rows already stored with reflection source. Slice rows (memory-reflection / memory-reflection-item) still derive the reflection layer and stay recall-excluded by design; explicit memory_layer fields still win over derivation.
81d465e to
f03ff73
Compare
Reflection writer-1 mapped rows (the distiller's "User model deltas", "Agent model deltas", "Lessons & pitfalls", and "Decisions" sections, mapped into durable memory rows via buildReflectionMappedMetadata) were classified as
source: "legacy"instead ofsource: "reflection", everywhere source is displayed or used.Root cause
parseSmartMetadata's missing-source fallback only maps twotypevalues tosource: "reflection":Writer-1 mapped rows carry
type: "memory-reflection-mapped"(a third, distinct type) and write nosourcefield at all, so every mapped row fell through thedefault: "legacy"branch.Fix
"memory-reflection-mapped"toparseSmartMetadata's type-based fallback map (src/smart-metadata.ts), so already-stored rows read back correctly.source: "reflection"at write time inbuildReflectionMappedMetadata(src/reflection-mapped-metadata.ts), so newly-written rows carry it explicitly and don't depend on the read-path fallback.Behavior change (knock-on)
deriveDefaultLayer(source, category, state)treatssource: "reflection"specially, always returningmemory_layer: "reflection". Reclassifying mapped rows assource: "reflection"therefore also changes their derivedmemory_layerfromdurable/working(whatever the category-based default would have been) toreflection. This is pinned explicitly in the new test rather than left as an untested side effect, and matches the layer every other reflection-sourced row already gets.Tests (TDD, red-first)
New file
test/smart-metadata-source-classification.test.mjs:memory-reflection-mappedrow (no explicit source) assource: "reflection"memory-reflection/memory-reflection-itemtypes still classify asreflectionlegacysourcefield still overrides type-based inferencememory_layerknock-on described abovebuildReflectionMappedMetadatastampssource: "reflection"at write timeRegistered in
package.json's test chain andscripts/ci-test-manifest.mjs(storage-and-schemagroup). Full targeted suite green,npx tsc --noEmitclean,npm run buildclean.Fixtures are entirely synthetic, no real fleet data.