Install
openclaw skills install @caix84476-netizen/personal-understandingVerbatim-first timeline, entity profiles, and proactive follow-ups
openclaw skills install @caix84476-netizen/personal-understandingThis is a local, traceable, verbatim-first, timeline-driven personal cognition archive. It stores experiences, relationships, states, and rules, and lets the model:
The legacy memory/records/ layout is kept as a compatibility layer. The v2 derivation trunk lives in memory/v2/, and immutable conversation verbatims live in sources/conversation/.
Before invoking this skill, classify the request. If it is primarily technical — including configuration, debugging, code, model/provider setup, MCP, plugins, repositories, or project maintenance — and the answer will not materially change because of the user's experiences, preferences, values, current state, or prior decisions, skip this skill entirely. Do not run a survey, capture the message, create a derived record, or store an audit copy for that request.
Use this skill only when the request contains personal material, the user explicitly asks to remember or archive it, or personal context would materially change the recommendation, tradeoff, warning, or action order. A request to maintain this skill's boundaries is not itself personal material; update the skill rules without archiving the maintenance conversation.
Global conversation style, coding-language preferences, tool preferences, and planning/interview behavior belong in the host client's instruction file, not in this personal archive. This skill must not capture or derive those client-configuration decisions as personal facts.
Whenever the user adds content that belongs in the Personal Understanding skill — in any form, in any scenario — the complete user message must be saved verbatim, character for character, before any summarizing, event splitting, person extraction, relationship judgment, or causal interpretation.
The execution order is fixed:
user verbatim / raw attachments
↓ saved first, never overwritten
verbatim fragment
↓
events, entities, context cards, states, follow-ups, hypotheses
↓
retrieval and answers
Mandatory:
utf8_sha256, capture time, session identifier, and source path;summary_only;scripts/preflight_context.py <full-message> --turn-id <turn-id> or MCP personal_preflight_turn; then capture with scripts/capture_user_update.py --turn-id <turn-id> or MCP personal_capture_user_turn. A text capture's SHA256 must match the receipt's full message;personal_add_record, content the user just supplied must carry capture_id or verbatim_refs; bare current-conversation source attributions are forbidden.A successful capture only means the raw material was not lost. It enters pending in memory/derivation-ledger.json and still must be split semantically, linked, and closed.
Before every answer, every personal-material capture from the current turn must be in one of these states:
scripts/finalize_capture.py --disposition derived or MCP tool personal_finalize_capture;no-derivation-needed and a concrete reason.Hard constraints:
pending;derived requires at least one verifiable bidirectional capture→record link;scripts/capture_attachment.py to keep originals and register hashes;scripts/validate_memory.py --require-closed-captures must block orphaned captures, untracked captures, and unfinished derivations from entering the completed state;All content is handled at one of these levels:
What the user just said outranks the existing archive. Old facts are never silently erased; new content establishes supersedes, contradicts, or correction chains.
What an entry is and how much future understanding depends on it are different things — and there must not be two competing "importance" standards.
entry_kind: event, state, decision, fact, etc. — what it is;salience: how much future understanding of the user depends on it, on a single 0–3 axis:
3 pivotal: changes long-term understanding, multiple domains, or life direction;2 key: clearly changes one life thread, a current decision, or a relationship's course;1 supporting: provides background, connections, or counterexamples;0 passing: appears only as a name or detail."pivotal / key / supporting / passing" are display labels on this one scale — there is no second "core / important / background event" classification. When migrating legacy records, weights may only be marked imported heuristic, never disguised as user-assigned.
The timeline is the archive's first backbone — but it must not force a life into a biography.
Each timeline entry keeps, where possible:
date_start, date_end;date_precision: day, month, year, approximate, relative order, unknown;date_basis: when it happened, when recalled, when the source was written, or model inference;phase: childhood, middle school, high school, college transition, etc.;salience: the single memory weight;entity_refs: people, schools, places, objects, works, concepts, environments;before_ids, after_ids;Never record the record-creation date as the event date. If a date is uncertain, write uncertain — never invent dates to make the timeline look tidy.
The overview uses an events-first, experience-follows, current-state-overlaid structure:
So this is neither "examples-first" nor "feelings-first": the timeline uses events as the skeleton, feelings and meaning are the expansion layer of events, and current state adds a short, information-dense snapshot on top.
Any object the user explicitly refers to and that plays some role in the current content can get a lightweight entity profile — neither skipped because it is a passerby nor padded with invented biography because material is thin.
Entity types are not limited to people:
person: people, relatives, friends, classmates;group: class, team, community;school_or_organization: schools, universities, institutions;place: cities, homes, courts, workplaces;object: computers, headphones, football boots, equipment;book_or_work: books, novels, works, articles;game_or_media: games, videos, music, account content;concept: concepts, values, ideals, systems;environment: family environment, school atmosphere, living conditions, institutional environment.A "bare vague pronoun" means:
In that case, do not invent a fake person and do not write "unconfirmed entity" junk nodes the model cannot use: hang that verbatim on the event's unresolved_referent, keep the original text, and fold it into the formal profile once the user later clarifies who it is.
Whenever identity IS clear from context, create a short profile even from a single sentence. A passerby profile with a few sentences is not waste.
Entity profiles never hand-copy a duplicate biography. Instead:
identity_note, time spans, etc. are retrieval metadata that stay out of the profile body unless they affect understanding.A person's profile may talk about the people around them, because social relations are part of who that person is. Connections stay; the same fact returns to the same canonical fragment through links and context cards.
Beyond entity profiles there are facet / context cards:
school entity
football entity
school × football context card
The school profile jumps to this card, the football profile jumps to the same card. The card holds their shared events, people, places, objects, and verbatim entry points — never a fabricated "school football story" copy.
Context card boundaries form around shared stories:
Coincidental co-occurrence is never auto-written as causation — but cross-domain cards are not deleted either. Relevance is decided by events, time, entities, and user experience together.
Current state is never a vague one-liner and never a full biography. Default five blocks:
Each block gets 1–3 high-density entries with expandable key examples and verbatims — never core-only, never everything crammed onto the front page.
Questions the model raised, the user's "let's see in a few days", the other side not having replied, pending decisions, items to confirm — all must enter memory/v2/followups.jsonl with at least:
due_at or an explicit due_rule;Every time the skill runs, first check follow-ups that are due or near due (default 3-day window). When due, ask proactively — but always with context:
On <date> you mentioned: …
At the time we expected: …
It's check-in time now.
How did it turn out?
If the current message contradicts the archive, list both conflicting facts, dates, sources, and the delta before asking — never pop a context-free question.
Some users freeze in front of an empty archive. When the user asks what to share ("what should I tell you?"), seems unsure how to begin, or the archive is freshly initialized, run python scripts/conversation_starters.py (JSON output) and pick one starter — ranked by due follow-ups first, then the emptiest domain — and ask it warmly, in your own words.
Whenever the current user message contains personal experience, state, feelings, self-evaluation, relationships, decisions, corrections, long-term preferences, or asks "why am I like this", the complete current user message must be saved as a new immutable capture — successfully — before any survey, probe, deep read, derived record, causal analysis, or answer. A previous turn's capture, an old summary, current-conversation, or model memory is never a substitute.
The execution order is fixed:
content-first preflight receipt → capture bound to receipt (read-back verified)
→ survey/probe/deep → derived records/hypotheses → finalize
→ session_check --turn-id → answer / claim update
The receipt is an auditable fact, not an advisory prompt: when requires_personal_understanding=true, capture, finalization, and session_check --turn-id are all mandatory and fail closed. If capture fails, stop all personal-understanding analysis and report the failure explicitly; never answer first and backfill later. If capture succeeds but no derived record exists yet, the answer must clearly distinguish "verbatim saved" from "not yet written into experience/state cards" — never present a raw capture as a fully updated archive.
This gate applies to messages that explicitly mention the personal archive, the skill, memory, verbatims, or "remember" — and equally to personal experiences, states, feelings, relationships, preferences, or decisions supplied through a rewrite, edit, translation, summary, or image-review request. Task form never overrides personal material. Pure technical work, configuration, debugging, project maintenance, and maintenance of this skill's rules do not create receipts, captures, or derived records.
Low-information messages which are also content-classified as personal (for example, "kind of lost" or "hard to say") are bound by two contracts at once: answers must feel natural (see the low-signal response contract), yet the gate still demands capture. A bare "ugh" does not enter the archive by itself. To keep chat from turning into a retrieval ceremony, low-signal personal turns run in this order:
no-derivation-needed) within the same turn and run session_check; if the user follows up with substantive content, escalate to the full flow.The fast path relaxes the timing of reads and derivation — never the verbatim capture or the closure itself.
Prefer the MCP tools (personal_catalog, personal_retrieve, personal_session_check, …) for reads and writes; they carry read-preflight capture validation. If no personal_* tools exist in the current session, this client has not registered the local MCP service: run python scripts/install_mcp.py --auto (idempotent, safe to repeat), then ask the user to restart the session; until registered, the CLI scripts perform the same work.
v2 retrieval is neither "stuff the whole archive into the model" nor keyword search. It is three layers of divergence:
Read the compact catalog only — never full verbatims:
survey is a compact routing map without the full legacy record list; use catalog_context.py --view routing --query <message> to expand legacy catalogs per domain, or --view full for the complete catalog.
The model picks one or more entries:
Then read those derived cards and expand:
Expansion reads only the necessary range while keeping small details reachable via cards, reducing missed recall for minor figures. Every timeline entry in probe output carries an evidence_fidelity count (how much verbatim vs. summary debt backs it); claims resting on summary debt must be disclosed to the user as "this part comes from an old summary, not verbatim". Each retrieval's decision trace appends to memory/v2/traces/ — replay it when recall misses or mis-attribution happens.
Only when the answer needs exact facts, dates, attribution, contradictions, relationships, the user's original meaning, or causal explanation do we read the corresponding verbatim fragments. Legacy summaries remain summary debt — they never pose as original text in the deep stage.
When the user says "I forget" or "we talked about something like this before", do not demand keywords and do not declare "nothing found". Descend the ladder:
before_ids/after_ids time neighbors forward and backward;retrieve_v2.py --window 2025-03 (or start:end), like flipping through an old photo album, and let the user claim candidates;Demoted passing-level records stay reachable on all three paths — entity, keyword, and time window. Demotion only removes them from the standing map; it never makes them unreachable.
Causal interpretation is its own large undertaking — it never runs wild inside ordinary fact retrieval. A candidate hypothesis carries at least:
claim: what it explains;mechanism: through what process;supports: supporting evidence;contradicts: counterexamples and limits;alternatives: competing explanations;scope: in which times, scenes, and relationships it holds;confidence: confidence level;status: candidate: candidate by default — never treated as fact.Trigger conditions:
Generation steps:
candidate pattern → mechanism sketch → supporting evidence → counterexamples/limits → competing explanations → user confirms / keep observing
A single event never yields a stable cause. Causal hypotheses enter deep reads only when the current question needs explanation; ordinary fact questions never auto-load them.
The archive owner has explicitly allowed the local skill to read private / highly-private content when relevant. Sensitivity is not a reason to hide, demote, or archive.
But relevance filtering stays:
Relaxing privacy reading is not abolishing boundaries — otherwise you are not understanding the user better, you are dumping the archive into every answer.
Structural validation no longer just prints "pass". scripts/validate_memory.py has three outcomes:
clean: no errors, no warnings;warnings: structurally usable, but there is summary debt, source gaps, date gaps, pending follow-ups, or entity connection issues;failed: hash errors, duplicate IDs, orphaned references, relation cycles, corrupt JSONL, or unacceptable schema errors.Strict mode --strict treats warnings as failures too — for migration acceptance.
review_v2.py --deep --json produces a semantic review package checking:
Deep review may output warnings and material gaps, but never invents lost verbatims back into existence. Structural cleanliness is not semantic correctness; review must come with a risk report.
scripts/capture_user_update.py: save the complete user verbatim first (for very long messages prefer --stdin or --file to dodge command-line length limits);scripts/preflight_context.py and scripts/turn_receipts.py: create, read, and audit immutable turn receipts;scripts/capture_attachment.py: store or SHA256-deduplicate raw attachments and register pending captures;scripts/derivation_ledger.py: maintain capture→records state and link audits; --repair rebuilds the projection from immutable capture metadata and record references;scripts/finalize_capture.py: complete a derivation or record the concrete "nothing to derive" reason;scripts/catalog_context.py: v2 global survey;scripts/retrieve_v2.py: v2 probe/deep;scripts/followup_check.py: follow-up checks;scripts/review_v2.py --deep: deep structure/fidelity/semantic review package;scripts/validate_memory.py: failed/warnings/clean three-state validation;scripts/session_check.py --turn-id <turn-id>: the hard gate before answering or claiming "the archive is updated" (receipt + structure + derivation closure + v2 integrity; non-zero exit on failure);scripts/salience_review.py: quarterly salience review, demoting long-unconfirmed imported weights to passing level (see references/review-and-feedback-loops.md);scripts/record_feedback.py: record how answers that relied on memory landed (helpful/missed/corrected); review_v2 --deep aggregates frequently corrected memories (see references/review-and-feedback-loops.md);scripts/rebuild_views.py: rebuild legacy compatibility views and v2 derived views;scripts/backup_archive.py: SHA256-manifested local backups, auto-mirrored to a second location from memory/backup-config.json (see references/maintenance-and-durability.md; after important updates, before migrations, and at least weekly);scripts/init_archive.py: bootstrap a fresh archive skeleton (directories + generic domain branches) on a brand-new install; idempotent, run once before first use;scripts/install_mcp.py: detect AI clients on this machine and register the local MCP service (idempotent; run once after changing machines or pasting the skill into a new client);scripts/mcp_server.py: local MCP read/write entry;dashboard/: the v2 visual audit panel.maintenance hints in preflight / session_check output are the only maintenance state to watch: when backups are overdue (backup.due: true), run scripts/backup_archive.py after the current task and before ending the session; when an answer that relied on memory drew an explicit correction/confirmation, record feedback per references/review-and-feedback-loops.md (never record without quotable verbatim evidence);The panel exists so the owner can check whether the skill follows its own rules. The front page offers status and count entries only; details live in the timeline, entity, context, source, follow-up, and diagnostics pages.
The diagnostics page must show:
SKILL.md, references, scripts, and memory/v2;clean, warnings, failed);Every list click uses its own ID. Never bind multiple entries to one default target. Entity redirects must show old ID, canonical ID, and merge source.