Skip to content

feat(context,memory): persist ContextFidelity per message for cross-turn floor invariant (#4550)#4615

Merged
bug-ops merged 2 commits into
mainfrom
cam-phase-2b-fidelity-persist
May 29, 2026
Merged

feat(context,memory): persist ContextFidelity per message for cross-turn floor invariant (#4550)#4615
bug-ops merged 2 commits into
mainfrom
cam-phase-2b-fidelity-persist

Conversation

@bug-ops
Copy link
Copy Markdown
Owner

@bug-ops bug-ops commented May 29, 2026

Summary

CAM Phase 2-B: fidelity levels are now persisted to SQLite after each scoring pass and reloaded on the next turn, enforcing the floor invariant across conversation turns.

  • Migration 095 (zeph-db): additive ALTER TABLE messages ADD COLUMN fidelity_tag INTEGER NOT NULL DEFAULT 0 (SQLite ≥ 3.37 O(1); PostgreSQL SMALLINT NOT NULL DEFAULT 0)
  • ContextFidelity::from_u8 (zeph-common): converts DB integer → enum; unknown values → Full (safe default); 0None sentinel avoids false floor on pre-CAM rows
  • MessageStore::update_fidelity_tags (zeph-memory): batch-writes (MessageId, u8) pairs in a single transaction; no-op when slice is empty; load_history / load_history_filtered now populate fidelity_tag from DB
  • Floor invariant (zeph-context): score_and_apply gains allow_upgrade: boolfalse enforces floor (Compressed cannot upgrade to Full; Placeholder cannot upgrade at all); true bypasses floor on the proactive regrade path; more_restrictive() propagates floor through tool-use / tool-result atomicity pairs
  • persist_fidelity_tags (zeph-agent-context): private helper that batch-writes after normal scoring and after regrade path, so floor constraints survive to the next turn
  • truncate_to_tokens (zeph-context): manual is_char_boundary backward scan replaced with str::floor_char_boundary (stable since Rust 1.91)

Test plan

  • 4 new round-trip tests in zeph-memory (update_fidelity_tags_round_trip, placeholder_round_trip, zero_maps_to_none, empty_is_noop) — all pass
  • 8 new floor invariant tests + 1 mixed atomicity test in zeph-context — all pass
  • 1766 tests across zeph-common, zeph-context, zeph-memory pass
  • clippy clean on all touched crates
  • fmt clean workspace-wide
  • No blocking std::fs — all DB writes are async

Closes #4550

@github-actions github-actions Bot added documentation Improvements or additions to documentation memory zeph-memory crate (SQLite) rust Rust code changes enhancement New feature or request size/XL Extra large PR (500+ lines) labels May 29, 2026
@bug-ops bug-ops force-pushed the cam-phase-2b-fidelity-persist branch from d39ac12 to ca757d0 Compare May 29, 2026 12:58
bug-ops added 2 commits May 29, 2026 15:04
…urn floor invariant (#4550)

CAM Phase 2-B: fidelity levels are now written to SQLite after each scoring pass and
reloaded into Message::metadata.fidelity_tag on the next turn.

- db (migration 095): add fidelity_tag INTEGER NOT NULL DEFAULT 0 to messages table
  (SQLite additive ALTER TABLE; PostgreSQL SMALLINT NOT NULL DEFAULT 0)
- zeph-common: ContextFidelity::from_u8 — DB integer → enum; unknown → Full (safe default)
- zeph-memory: MessageStore::update_fidelity_tags batch-writes in a single transaction;
  load_history / load_history_filtered populate fidelity_tag; 0 → None sentinel avoids
  false floor on pre-CAM rows; 4 new round-trip tests
- zeph-context: score_and_apply gains allow_upgrade: bool — false enforces floor
  (Compressed cannot upgrade to Full; Placeholder cannot upgrade at all);
  true bypasses floor on the proactive regrade path; more_restrictive() propagates
  floor through tool-use/tool-result atomicity pairs; 8 new floor invariant tests;
  truncate_to_tokens uses str::floor_char_boundary (stable since 1.91)
- zeph-agent-context: persist_fidelity_tags private helper batch-writes after normal
  scoring and after prograde path so floor constraints survive to the next turn

Closes #4550
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request memory zeph-memory crate (SQLite) rust Rust code changes size/XL Extra large PR (500+ lines)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(context): CAM Phase 2-B — persist ContextFidelity per message in SQLite for cross-turn stability

1 participant