Skip to content

fix: classify reflection writer-1 mapped rows as source reflection, not legacy#950

Open
gorkem2020 wants to merge 4 commits into
CortexReach:masterfrom
gorkem2020:fix/reflection-mapped-source-classification
Open

fix: classify reflection writer-1 mapped rows as source reflection, not legacy#950
gorkem2020 wants to merge 4 commits into
CortexReach:masterfrom
gorkem2020:fix/reflection-mapped-source-classification

Conversation

@gorkem2020

Copy link
Copy Markdown
Contributor

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 of source: "reflection", everywhere source is displayed or used.

Root cause

parseSmartMetadata's missing-source fallback only maps two type values to source: "reflection":

parsed.type === "memory-reflection" || parsed.type === "memory-reflection-item"

Writer-1 mapped rows carry type: "memory-reflection-mapped" (a third, distinct type) and write no source field at all, so every mapped row fell through the default: "legacy" branch.

Fix

  • Add "memory-reflection-mapped" to parseSmartMetadata's type-based fallback map (src/smart-metadata.ts), so already-stored rows read back correctly.
  • Also stamp source: "reflection" at write time in buildReflectionMappedMetadata (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) treats source: "reflection" specially, always returning memory_layer: "reflection". Reclassifying mapped rows as source: "reflection" therefore also changes their derived memory_layer from durable/working (whatever the category-based default would have been) to reflection. 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:

  • classifies a memory-reflection-mapped row (no explicit source) as source: "reflection"
  • unchanged: memory-reflection / memory-reflection-item types still classify as reflection
  • unchanged: an unrecognized/absent type still classifies as legacy
  • unchanged: an explicit source field still overrides type-based inference
  • pins the memory_layer knock-on described above
  • buildReflectionMappedMetadata stamps source: "reflection" at write time

Registered in package.json's test chain and scripts/ci-test-manifest.mjs (storage-and-schema group). Full targeted suite green, npx tsc --noEmit clean, npm run build clean.

Fixtures are entirely synthetic, no real fleet data.

@gorkem2020
gorkem2020 force-pushed the fix/reflection-mapped-source-classification branch 2 times, most recently from c9278bf to cbd55a1 Compare July 18, 2026 15:52
…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)
@gorkem2020
gorkem2020 force-pushed the fix/reflection-mapped-source-classification branch from cbd55a1 to 0e3b172 Compare July 19, 2026 02:59
@gorkem2020
gorkem2020 marked this pull request as ready for review July 19, 2026 02:59

@app3apps app3apps left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@gorkem2020

gorkem2020 commented Jul 19, 2026

Copy link
Copy Markdown
Contributor Author

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, deriveDefaultLayer now recognizes the mapped row type and derives category-appropriate general-pool layers (durable/working), which also heals rows already stored with the reflection source. Slice rows still derive the reflection layer, so the governance exclusion keeps its double-injection purpose. We will re-verify with the same live probe after our next fleet deploy.

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.
@gorkem2020
gorkem2020 force-pushed the fix/reflection-mapped-source-classification branch from 81d465e to f03ff73 Compare July 20, 2026 06:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants