Skip to main content

brain-backfill

Source-led first-run or large historical Local Brain import. Use when setting up a new brain from Gmail/GWS, Granola, WhatsApp, Reflect notes, Calendar, contacts, or other personal data sources, especially when the user asks for a comprehensive backfill.

소스 정보

저장소
team-reflect/local-brain
최근 소스 활동
2026년 6월 22일 21:14
감지된 SKILL.md 언어
영어
스타
11
포크
2

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
brain-backfill
description
Source-led first-run or large historical Local Brain import. Use when setting up a new brain from Gmail/GWS, Granola, WhatsApp, Reflect notes, Calendar, contacts, or other personal data sources, especially when the user asks for a comprehensive backfill.
# Local Brain Backfill Use this after reading `skills/brain/SKILL.md`. This skill is for first setup or large historical imports where coverage matters. The goal is a useful typed personal intelligence database, not a dump of every byte. ## Non-Negotiables 1. Verify the target brain and pass it to every write: ```bash export BRAIN_ROOT="/path/to/brain-folder" brain --brain "$BRAIN_ROOT" --json doctor brain --brain "$BRAIN_ROOT" path brain --brain "$BRAIN_ROOT" --json contract ``` 2. Use only the `brain` CLI for writes. Do not mutate SQLite directly. 3. Enumerate source records first. Keyword search is a filter, not a coverage strategy. 4. Keep a local scratch ledger outside the brain DB with every source record's disposition. 5. Treat staged completion as mandatory: raw record, transcript/text, AI note, facts, links, evidence-backed tasks/memories, tags, chunks, finalize. 6. People need conservative headlines and affiliations during the import, not as unspecified cleanup. 7. Organizations need compact headlines and, when evidence supports it, `brain enrich organization` profile rows during the import. 8. Attach imported files as assets and provide searchable extracted text when useful; binary PDFs/images are otherwise metadata-only. 9. For people and organizations, `--external-id` must identify that person/org itself. Never use a Gmail thread/message id, meeting id, event id, note id, or other source-record id as a person/org external id. 10. Completion requires participant normalization: run the participant audit, promote recurring real people, and rerun the fail gate before final report. 11. Skip deliberately: secrets, passwords, one-time links, medical/financial boilerplate, promos, alerts, receipts, and private material usually do not belong in the brain. Do not redact imported source bodies; if a source record should not be stored locally, skip the whole record and ledger the reason. 12. User corrections and clarifications are trusted manual evidence. Store them as small manual evidence records, add source-keyed facts, update typed profiles/tags/affiliations through the CLI, and keep import audit clean. ## Setup ```bash brain --brain "$BRAIN_ROOT" --json import-context --limit 300 brain --brain "$BRAIN_ROOT" --json self show brain --brain "$BRAIN_ROOT" --json source ensure --slug gmail --name Gmail brain --brain "$BRAIN_ROOT" --json source ensure --slug granola --name Granola brain --brain "$BRAIN_ROOT" --json source ensure --slug reflect_notes --name "Reflect Notes" brain --brain "$BRAIN_ROOT" --json source ensure --slug google_calendar --name "Google Calendar" brain --brain "$BRAIN_ROOT" --json source ensure --slug google_people --name "Google People" brain --brain "$BRAIN_ROOT" --json source ensure --slug whatsapp --name WhatsApp ``` Before starting source passes, inspect the returned `projects` and `counts.projects`. If no projects exist, do not continue directly into import writes. First identify the user's core project boundaries from self context, source metadata, and high-signal source records such as emails, calendar events, notes, meetings, and contacts. Present a compact candidate project list with the evidence that supports each boundary, get explicit user sign-off, then create only the approved projects with `brain add project` before proceeding. If self is missing or has no handles, register known user emails before importing email/calendar data: ```bash brain --brain "$BRAIN_ROOT" --json self set \ --full-name "Alex MacCaw" \ --email alex@maccaw.org --email alex@picardo.health ``` After project sign-off and self setup, rerun `import-context` and save a baseline snapshot from that fresh output before importing. Do not reuse the earlier setup output. ```bash brain --brain "$BRAIN_ROOT" --json import-context --limit 300 ``` ```text baseline_projects=<count> baseline_people=<count> baseline_orgs=<count> accepted_projects=<ids/names from import-context> ``` ## Ledger Use a scratch file such as `.codex-imports/backfill-ledger.tsv`: ```text source external_id date title status project reason local_record ``` Also keep compact normalization ledgers: ```text person_candidate source handle_or_name count action person_id_or_reason org_candidate source domain_or_name count action org_id_or_reason ``` Statuses: - `imported` - `refreshed` - `duplicate` - `skipped` - `needs_review` - `suggested` - `incomplete` Final reports must include considered/imported/refreshed/duplicate/skipped/ needs-review/incomplete counts by source and notable gaps. Source workers must also report person/org records created and unresolved person/org candidates. For every bounded source pass, create a pass directory under `.codex-imports/` before importing. Keep the pass auditable and resumable: ```text <pass-name>/ manifest.jsonl every fetched source record and local raw/text paths review-queue.jsonl compact evidence for LLM/manual decisions decisions.jsonl import/skip/duplicate/needs_review with reason decisions.tsv human-readable decision ledger import-ledger.tsv attempted imports and finalize results report.md query/window/cap/counts/normalization caveats raw/ raw provider JSON text/ readable source text used for imports ``` Before marking a source record as fresh, dedupe against every prior ledger shard and pass-specific `import-ledger.tsv`, not only the first backfill ledger. Report provider result estimates, explicit caps, fetched count, imported count, and the unreviewed remainder. ## Parallelization For large backfills, use subagents/workers when available. Split independent import lanes by source and month. After import, use subagents for read-only normalization/audit candidate lanes such as people candidates, org/domain candidates, and project surprises. Every subagent/worker must: - receive the same `BRAIN_ROOT`; - read `brain --json import-context` and the read-first context at start; - maintain its own disjoint ledger shard. Import workers must: - own a disjoint write scope with no overlapping source records; - write through the CLI only; - use source identity for idempotence; - use `--refresh` for routine source-backed reimports, and `--replace-body` only when intentionally overwriting stale imported body text; - run `brain --json import finalize --record kind:id` on every imported record, adding only narrow explicit waivers when source data is truly absent; - report incomplete records instead of hiding them. Normalization/audit workers must: - avoid writes; they produce candidate ledgers only; - own a disjoint read-only candidate scope, such as people, org/domain, or project-surprise candidates; - audit recurring unresolved participants, domains, and project count surprises; - report unresolved participants, unresolved domains, and recommended actions. The main coordinator merges ledger shards, performs any people/org/affiliation normalization writes through the CLI, then runs one global audit. Use `brain import participants audit/promote` and `brain repair ...` commands for participant normalization rather than direct SQLite writes. ## Source Passes ### Projects And Boundaries Start from accepted projects in `import-context`. Treat the project inventory as a gate, not background context: if `counts.projects` is zero or `projects` is empty, pause the backfill and figure out the user's core projects before creating durable records. To identify initial project candidates, inspect enough source context to see the real workstreams: correspondent domains, recurring meeting titles, calendar clusters, note paths/headings, contact affiliations, and repeated subject stems. This discovery may require reading selected high-signal emails, meetings, notes, or events, but it is still a discovery pass: ledger what was considered and do not import records yet except for necessary source setup/self identity. Present the user with a compact sign-off list: candidate name, one-sentence boundary, supporting evidence, and any obvious non-goals or merge/split choices. Group each company/product as one project unless the user explicitly asks for subprojects. After the user approves boundaries, create those projects with `brain add project` and link later imports to them. For any later source record that hints at an unapproved project boundary, do not auto-create it during import; use `brain suggest project` with evidence. ### Granola Enumerate all meetings in the date window. For each high-signal meeting: ```bash brain --brain "$BRAIN_ROOT" --json import interaction --kind meeting \ --title "Granola: <title>" \ --summary "<concise digest>" \ --source granola --external-id <meeting-id> \ --participant "attendee:Name <email>" \ --link project:<id> brain --brain "$BRAIN_ROOT" --json import transcript \ --interaction <interaction-id> \ --text-file transcript.txt \ --source granola --external-kind transcript --external-id <meeting-id> brain --brain "$BRAIN_ROOT" --json add ai-note \ --kind summary --interaction <interaction-id> \ --title "Meeting summary" --text-file summary.md --source granola \ --evidence interaction_transcript:<transcript-id>~"<short distinctive quote>" ``` Then add facts, tasks, memories, and tags with evidence. Skip meetings that are private, sensitive, pure scheduling, demos with no durable signal, or already represented elsewhere; record the reason. ### Gmail / GWS Default Gmail strategy: run `from:me` first. Sent threads are usually denser relationship signal than broad keyword search because they capture what the user chose to reply to, introduce, approve, explain, or coordinate. Treat it as a bounded source pass, not as the whole backfill: ```text pass_name=from-me-gmail query=from:me after:<YYYY/MM/DD> before:<YYYY/MM/DD> cap=<explicit number, e.g. 500> ``` After `from:me`, add narrower passes as needed: `is:important`, recurring correspondents/domains, attachment-heavy project threads, and explicit user queries. Do not rely only on project keywords. For each Gmail pass: 1. Page thread/message metadata. 2. Fetch full raw thread JSON and readable thread text into the pass directory. 3. Build a compact review queue from subject, dates, participants, labels, message count, attachments, snippets, and text excerpts. 4. Dedupe against previous ledgers and source identities. 5. Cluster by correspondent domain, sender/recipient, subject stem, known projects, attachments, and thread depth. 6. Review high-signal threads case by case. 7. Import full readable thread text as `interaction --kind email` when the source record is worth storing. 8. Preserve participants, source identity, project links, AI note, facts, tags, and evidence-backed tasks/memories. Example: ```bash brain --brain "$BRAIN_ROOT" --json import interaction --kind email \ --title "Gmail: <short subject>" \ --summary "<digest>" \ --text-file full-thread.md \ --source gmail --external-kind thread --external-id <thread-id> \ --participant "from:Name <email>" --participant "to:Alex <email>" \ --link project:<id> ``` Import sent threads that carry durable project, relationship, obligation, decision, strategy, introduction, approval, or vendor coordination signal. Skip credentials, codes, receipts, promos, alerts, commodity confirmations, calendar noise, self-authored daily digests, long quoted chains, and legal/medical/ family/private material unless the user has explicitly approved it or it clearly belongs to an accepted project and is worth storing as complete local evidence. Use `--refresh` for repeat passes over the same thread so unchanged bodies stay idempotent. ### Reflect Notes Enumerate every note in scope by path/date. For each note choose one: - full `import document` when mostly reference material; - `skipped` with a concrete reason when project signal is mixed with private material that should not be stored locally; - `needs_review` when sensitive but likely important. Use stable source identity: ```bash brain --brain "$BRAIN_ROOT" --json import document \ --title "Reflect: <note title>" \ --text-file note.md \ --source reflect_notes --external-kind note --external-id <stable-note-id> \ --original-path "$HOME/Documents/reflect-maccman2/<note>.md" \ --link project:<id> ``` ### Calendar Enumerate events. Import only meaningful project/life context that is not already represented by Granola or email: ```bash brain --brain "$BRAIN_ROOT" --json import interaction --kind event \ --title "Calendar: <event title>" \ --occurred-at <start> --ended-at <end> \ --location "<venue/address>" \ --text-file full-calendar-event.txt \ --metadata-json-file raw-google-calendar-event.json \ --event-json-file event-details.json \ --source google_calendar --external-id <event-id> \ --original-url "<provider-url>" \ --participant "attendee:Name <email>" \ --self-participant "attendee:You <email>" \ --link project:<id> ``` Use `event` for travel, lodging, reservations, reminders, all-day blocks, and non-meeting schedule context. Use `meeting` for people-centered appointments. If the calendar body only says "see Gmail for details", fetch and import the linked Gmail source or leave the event incomplete with `--raw-text-unavailable` and a ledger note. ### iMessage / Apple Messages For local Apple Messages backfills, treat `~/Library/Messages/chat.db` as the source of truth and read it with SQLite in read-only mode. Ensure a dedicated source first: ```bash brain --brain "$BRAIN_ROOT" --json source ensure \ --slug imessage --name iMessage ``` Import one Brain interaction per Apple `chat`, not one interaction per message. Use `--kind message`, `--source imessage`, `--external-kind chat`, and a stable `--external-id` such as `chat.guid`. Keep a per-chat ledger and preserve the complete recovered transcript in the interaction body. Apple Messages has two important text paths: - `message.text` contains only part of the readable history. - many text messages only appear in `message.attributedBody`; extract that text before deciding a row is blank. Convert Apple timestamps as nanoseconds since `2001-01-01T00:00:00Z`. Preserve reactions, replies, system rows, and empty/media-only rows as transcript lines when they carry context. For attachments, include filenames, MIME types, sizes, and local paths in the transcript and metadata. Do not bulk-copy every image, video, sticker, or audio file into Brain unless the user explicitly asks for binary asset import; message media can be huge and is often not searchable without a separate extraction pass. Use local Contacts/AddressBook data to enrich chat handles into names when the match is safe, but keep opaque phone/email handles as unresolved participants until the participant audit supports promotion. After import, add an `iMessage` tag, a concise archive AI note for each chat, finalize with narrow waivers when the pass intentionally skips project/action/fact extraction, then run participant audit and `merge person --dry-run` / `merge person` for duplicate contact shells. ### WhatsApp For local WhatsApp backfills, copy the source database and its `-wal` / `-shm` companions into the pass directory before reading it. Common macOS sources are under `~/Library/Group Containers/group.net.whatsapp.WhatsApp.shared/`, with `ChatStorage.sqlite` as the main SQLite database. Treat the copied database as read-only source material and write to Brain only through the CLI: ```bash brain --brain "$BRAIN_ROOT" --json source ensure \ --slug whatsapp --name WhatsApp ``` Inspect the schema before extraction; WhatsApp Core Data table names vary by version. Common useful tables include `ZWAMESSAGE`, `ZWACHATSESSION`, `ZWAGROUPMEMBER`, `ZWAMEDIAITEM`, and `ZWAPROFILEPUSHNAME`. Convert WhatsApp Core Data timestamps as seconds since `2001-01-01T00:00:00Z` by adding `978307200` seconds. For small or high-signal chats, import one interaction per chat. Use one interaction per chat-month when a transcript would exceed roughly 10,000 messages or 5 MB of Markdown, or when one chat would dominate search chunks and summaries: ```bash brain --brain "$BRAIN_ROOT" --json import interaction --kind message \ --title "WhatsApp: <chat name> (<YYYY-MM>)" \ --summary "<concise archive summary>" \ --text-file transcript.md \ --metadata-json-file metadata.json \ --source whatsapp --external-kind chat_month \ --external-id "<chat-jid>:<YYYY-MM>" \ --participant "sender:<display name or handle>" \ --link project:<id> ``` Preserve the full readable transcript in the body: local timestamp, sender, text, deleted/system markers, media captions, media filenames/paths, quoted reply context when available, and message ids or stanza ids in metadata. Do not bulk-import WhatsApp media binaries by default; record media metadata and local paths, then attach selected files only when the user explicitly wants binary assets or the file is clearly durable evidence. Participant handling is the fragile part. For direct chats, prefer phone-backed JIDs when present. For group chats, sender identity usually comes from group member rows such as `ZMEMBERJID`, not the group chat JID. Preserve source-native handles like `<phone>@s.whatsapp.net`, group JIDs, and opaque `@lid` handles as participants. Use contacts, push names, repeated context, and phone numbers to promote safely; do not create people for every group member. Ledger unresolved LID-only handles and recurring group participants for the final participant audit. After import, add a `WhatsApp` tag, source-keyed AI notes, facts/tasks/memories only where evidence is durable, and finalize each interaction. For archive-only chat-month imports, use narrow waivers such as `--no-derived-actions`, `--no-extracted-facts`, or `--no-project-or-task-link` rather than inventing intelligence. Run `brain import participants audit --source whatsapp` and report unresolved handles, promoted people, relinks, and skipped media. ### Contacts And People Import trusted contacts with `brain add person` or cautious senders with `brain add person-from-email`. When evidence supports it, include headline, phone, location, organization, title, and current-employer hints at creation time
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기