personal memory agent

feat(talents): add participation talent with structured role/source per span master

Introduce a per-span participation talent that produces structured participation records (role, source, confidence, context, entity_id) for each activity, consolidating per-segment Sense entity drafts. Three coordinated changes: 1. Extend talent/sense.md entities schema with role (attendee|mentioned) and source (voice|speaker_label|transcript|screen|other), plus a prompt-level contamination guard for screen-only names and tool/app UI. 2. Add talent/participation.md (quality-judge, activity-scheduled, tier 3) and talent/participation.py post-hook. The hook parses the LLM JSON, resolves entities read-only via think.entities.matching.find_matching_entity, and atomically merges participation + participation_confidence onto the activity record. 3. Generalize think/activities.update_record_description into update_record_fields, preserving the atomic tempfile+rename write. update_record_description becomes a thin wrapper. Sense drafts reach participation via think/sense_splitter.py, which now also writes a sense.md summary alongside sense.json. This was the only viable load path because think/cluster.py only discovers talents/**/*.md — sense.json is invisible to the existing load mechanism. The alternative (widening cluster) was rejected as out of scope. active_entities on activity records is preserved unchanged for backward compatibility. The state-machine flatten in think/activity_state_machine.py is untouched. The entity resolver is read-only: it calls find_matching_entity against already-loaded entities and injects entity_id (or null) per participation entry. It never writes under facets/{facet}/entities/. Tests cover: Sense schema, contamination guard prose, participation frontmatter/prompt, resolver file-count invariance, contamination regression at the plumbing layer, and atomic activity-record merge including malformed-JSON early return. Co-authored-by: Codex <codex@openai.com>