Skip to content

feat: surface memex PersonalContext in orchestrator system prompt#286

Merged
toadkicker merged 1 commit intomainfrom
feat/3d73-surface-memex-co
Apr 14, 2026
Merged

feat: surface memex PersonalContext in orchestrator system prompt#286
toadkicker merged 1 commit intomainfrom
feat/3d73-surface-memex-co

Conversation

@toadkicker
Copy link
Copy Markdown
Contributor

Summary

  • Introduces PersonalContext — a compact JSON-LD preamble built from EpisodeDB history, AgentProfile aggregates, and the user's TraitBeacon Person document
  • Injects context into the orchestrator's LLM calls via a tokio::sync::watch channel; consumers borrow the latest preamble lazily at call time (zero polling overhead)
  • Scope: OnDeviceAiExecutor + build_orchestrator_prompt_with_template only. pap-agents / DynamicAgentHandler are untouched.
  • New Tauri command save_trait_beacon_profile lets the frontend persist the user's Schema.org Person document; triggers an immediate preamble refresh
  • 365 tests pass (241 papillon-shared, 124 papillon); 10 new tests added

Key files

  • crates/papillon-shared/src/personal_context.rs (new)
  • apps/papillon/src/state.rscontext_tx watch sender + trait_beacon_profile Arc
  • apps/papillon/src/agents/on_device_ai.rs — lazy preamble inject
  • apps/papillon/src/inference.rscontext: Option<&str> param
  • apps/papillon/src/commands/episodes.rs / orchestrator.rs — push after write
  • apps/papillon/src/commands/agents.rssave_trait_beacon_profile command

Test plan

  • All CI checks green (13 jobs)
  • Smoke test: issue On-Device AI query after recording an episode, confirm [PAP PERSONAL CONTEXT] block appears in RUST_LOG=debug output
  • save_trait_beacon_profile with @type: "Person" persists and refreshes preamble
  • Empty DB path: no preamble injected (no noise in first-run experience)

🤖 Generated with Claude Code

Introduces `PersonalContext` — a compact JSON-LD preamble synthesised
from EpisodeDB history, AgentProfile aggregates, and the optional
TraitBeacon Person document — and injects it into the orchestrator's
LLM calls via a `tokio::sync::watch` channel.

### What changes

**`crates/papillon-shared`**
- New `personal_context.rs` (native-gated): `PersonalContext` struct,
  `EpisodeSummary`, `AgentSummary`, `from_db()`, `to_system_preamble()`
  (`[PAP PERSONAL CONTEXT]…[END PAP CONTEXT]` sentinels), `is_empty()`.
  Six unit tests covering cap, ordering, JSON-LD validity, trait filtering.
- `lib.rs`: export `personal_context` + `PersonalContext` (native only).

**`apps/papillon`**
- `state.rs`: add `context_tx: watch::Sender<String>` and
  `trait_beacon_profile: Arc<RwLock<Value>>` to `AppState`.
  `with_db()` loads the trait profile from DB, builds the initial
  preamble, and passes the receiver to `OnDeviceAiExecutor::new`.
- `agents/on_device_ai.rs`: accepts `watch::Receiver<String>`, borrows
  the latest preamble lazily at call time and prepends it to the
  `[INST]` prompt when non-empty.  Two new unit tests.
- `inference.rs`: `build_orchestrator_prompt_with_template` gains
  `context: Option<&str>`; prepends the block when `Some` and non-empty.
  Two new tests; existing test updated to pass `None`.
- `commands/episodes.rs`: `record_episode` gains `State<AppState>` and
  pushes a fresh preamble to `context_tx` after persisting.
- `commands/orchestrator.rs`: same preamble push after scenario episode
  insertion.
- `commands/agents.rs`: new `save_trait_beacon_profile` Tauri command —
  validates `@type == "Person"`, persists to DB setting, updates
  in-memory Arc, pushes preamble.
- `lib.rs`: register `save_trait_beacon_profile`.
- `commands/llm.rs`: pass `None` to the probe call (no personal context
  needed for capability probing).

All 365 tests pass (241 papillon-shared, 124 papillon).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

Benchmark Regression Report

PAP Protocol Benchmark Regression Check
========================================
Baseline: .bench-baseline/baseline.json
Threshold: 30%

  ed25519_keypair_generation                19.7 µs  (baseline: 19.7 µs, +0.1%)  [ok]
  did_key_derivation                         1.5 µs  (baseline: 1.5 µs, -1.7%)  [ok]
  mandate_create_sign                       24.0 µs  (baseline: 24.0 µs, -0.2%)  [ok]
  mandate_chain_verify_depth3              130.5 µs  (baseline: 139.0 µs, -6.1%)  [ok]
  sd_jwt_issue_5claims                      27.9 µs  (baseline: 27.9 µs, +0.0%)  [ok]
  sd_jwt_verify_disclose_3of5               46.1 µs  (baseline: 48.6 µs, -5.1%)  [ok]
  session_open_full_lifecycle              112.3 µs  (baseline: 108.6 µs, +3.3%)  [ok]
  receipt_create_cosign                     47.9 µs  (baseline: 47.9 µs, +0.1%)  [ok]
  federation_announce_local                 55.8 µs  (baseline: 61.3 µs, -9.0%)  [ok]

All benchmarks within 30% of baseline.

Threshold: 10% regression vs baseline from main

@toadkicker toadkicker merged commit e5f35b7 into main Apr 14, 2026
24 checks passed
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.

1 participant