--- name: ref-ingest description: The single entry point for incoming information of ANY kind about a reference entity (a person, org, product, engagement, or watched competitor). Extracts entity facts, RESOLVES them to the one existing canonical note (never duplicating), reconciles new-vs-old, and upserts (overwrite body, re-stamp as_of, append Change Log), then reindexes. Extends manage-reference-data with entity resolution + reconciliation + the market-vs-CRM automation split. Company is the default scope. NEVER writes any provenance but reference; NEVER crystallizes/lifecycle-classifies/promotes a record into an insight. automation: gated allowed-tools: [Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion, Skill] user-invocable: true argument-hint: "[scope=Company] [--source ] [--no-reindex]" metadata: version: "1.1" created: 2026-07-08 author: Cornelius changelog: - "1.1: Fix — Step 3 named a phantom agents-as-product/ sub-scope; type: agent notes live in products/. Corrected." - "1.0: Initial version — extract→resolve→reconcile→gate→upsert entry point for the Company reference family; overwrite-only market branch invariant; composes ref-supersede; grows manage-reference-data" --- # Ref Ingest > ℹ️ **First, set expectations:** before anything else, print one short line with this skill's version and its most recent change — the top entry of `metadata.changelog` above — e.g. `ref-ingest v1.0 — recent: initial version`. Then proceed. The **one operation every input funnels through** for a reference scope: `incoming info → resolve → reconcile → upsert`. It grows the manual single-upsert `manage-reference-data` with the two load-bearing hard parts — **entity resolution** (is this new "Reply" the existing `Reply.io`?) and **reconciliation** (new fact contradicts old → overwrite / supersede-with-history / flag) — plus the **automation split by scope**. **Read first (authoritative — this skill enforces, does not restate):** - `resources/layered-brains/COMPANY-BRAIN-SCHEMA.md` → "The update model", "The two axes" (sub-scope routing + `type:`/`relationship:` enums), "Automation boundary — split by scope". - `resources/layered-brains/REFERENCE-SCOPE-SCHEMA.md` → the reference-kind frontmatter contract. - `.claude/skills/manage-reference-data/SKILL.md` → the seed upsert (Step 0 scope check + the frontmatter template). This skill is its richer successor; it does not duplicate the contract. ## Composes - `/ref-supersede` — when reconciliation finds a **validity transition** that needs a prior snapshot (contract renewal, role/price change), hand off instead of overwriting. **Never invoked on the market/autonomous branch** (see the invariant). ## State Dependencies | Source | Location | Read | Write | Description | |--------|----------|------|-------|-------------| | Company family | `Brain/Company/{people,orgs,products,engagements,market}/*.md` | ✓ | ✓ | Entity notes (one note = one entity) | | Scope registry | `resources/local-brain-search/memory_config.py` | ✓ | | Confirm reference-kind | | LBS index | `resources/local-brain-search/data/` | ✓ | ✓ (reindex) | FAISS + graph; reindexed after a write | | Search wrappers | `resources/local-brain-search/run_search.sh` | ✓ | | Entity-resolution search under a `core,Company` mount | ## The automation split (load-bearing) | Sub-scope | Writer | This skill | |-----------|--------|------------| | `market/` (watched competitors/ecosystem) | autonomous | **auto-overwrite, no gate** — reference facts sit outside the `encountered→endorsed` gate | | `people/ orgs/ products/ engagements/` (transacted CRM) | curated | **human-gated** — present the diff, get approval before writing | **Invariant (what makes any autonomous caller safe):** the `market/` branch is **overwrite-only** — it never opens an approval gate and **never calls `/ref-supersede`**. A validity transition in `market/` that would need a snapshot is *flagged for a human `ref-supersede`*, not auto-run. So a scheduled caller (e.g. `ref-refresh`, or domain-watch in 9e) that routes market items here always takes a gate-free path. --- ## Process ### Step 1 — Resolve the scope + confirm reference-kind ```bash cd resources/local-brain-search SCOPE="${scope:-Company}" ./venv/bin/python - "$SCOPE" <<'PY' import sys, memory_config as mc f = sys.argv[1] print("kind:", mc.scope_kind(f), "| is_reference:", mc.is_reference_scope(f)) PY ``` If `is_reference` is False → **stop** (this skill only writes reference scopes). See the schema doc's "Adding a new reference scope". ### Step 2 — Extract candidate entity facts From the incoming info (the user in conversation · a document/contract/deck/call · a domain-watch market signal · another agent's report), pull the **atomic facts about one real-world entity**: display name + aliases, `type:`, the relation to us (`relationship:`), body facts, and any term-bearing fact (a contract window, a role start, a price effective date). ### Step 3 — Route to the sub-scope (watch vs transact) Apply the partition rule from COMPANY-BRAIN-SCHEMA "The two axes": - an entity you **watch** (competitor, competitor product, ecosystem player) → `market/` - an entity you **own or transact with** (self, client, prospect, partner, vendor, your offering, internal agent, a deal) → `people/ orgs/ products/ engagements/` by `type:`. The internal agent workforce (`type: agent`) lives in `products/` alongside own products — there is no separate `agents/` sub-scope. - `type:`/`relationship:` values MUST come from the schema doc's enum (person·organization·product·agent·engagement·interaction × the relationship axis). Never invent a value. ### Step 4 — ENTITY RESOLUTION (never duplicate) Find the one canonical note this fact belongs to before writing: ```bash # semantic: does an entity like this already exist in the family? BRAIN_READ_SCOPE=core,Company resources/local-brain-search/run_search.sh "" --limit 8 --json # exact/alias: title + body match grep -rilE "||" Brain/Company/ ``` - **Match found** → this is an *update* to that note. Use its exact path. - **Ambiguous** (2+ plausible matches, e.g. "Reply" vs "Reply.io") → present the candidates and ask which entity this is (`AskUserQuestion`); do NOT guess a new note into existence. - **No match** → genuinely new entity → *add*. ### Step 5 — RECONCILIATION (new fact vs old) Compare the incoming fact to the note's current body: | Situation | Action | |-----------|--------| | New fact **corrects/refreshes** an existing fact (same validity window) | **overwrite** the body (Step 6) | | A **validity window closed** and a full prior snapshot matters (contract renewed, role changed, price re-termed) | hand to **`/ref-supersede`** — *CRM only; on `market/` flag for a human instead* | | New fact **contradicts** old with no clear winner | **flag** — surface both, ask; do not silently overwrite | ### Step 6 — Automation gate + upsert - **`market/`** → proceed (no gate). **CRM sub-scopes** → show the before/after diff and get explicit approval (`AskUserQuestion`) before writing. - Write the note with the reference frontmatter contract (copy the template from `manage-reference-data` Step 2 — do not restate it here). On update: **overwrite the body** (current truth), preserve `created`/`created_by`, re-stamp `as_of` + `updated` to today, bump `updated_by` to your model. Append a `## Change Log` line: ```markdown ## Change Log - 2026-07-08 — (source: ) ``` - **Going forward only:** for a term-bearing fact, add `valid_from:`/`valid_until:`. **Do NOT** backfill these onto notes that lack them — incremental adoption. ### Step 7 — Reindex (unless deferred) ```bash cd resources/local-brain-search && ./run_index.sh && ./run_daemon.sh restart # daemon on :7437, RESTART not reload ``` Content-hash detection → a changed note triggers a **full FAISS rebuild** (minutes). Reference notes are **BDG-excluded**, so **no `run_brain_graph.sh bootstrap` is needed**. If invoked with `--no-reindex` (batch mode, e.g. by `ref-refresh` over many market items), **skip this step** and let the batch caller reindex once at the end. --- ## Verification - **Round-trip:** after an add/overwrite + reindex, the entity **surfaces under a mount** and is **absent unmounted**: ```bash BRAIN_READ_SCOPE=core,Company resources/local-brain-search/run_search.sh "" --limit 5 --json # present resources/local-brain-search/run_search.sh "" --limit 5 --json # absent (core default) ``` - **Learn-gate held:** `md5 resources/local-brain-search/data/q_values.json` is byte-identical before and after (a mounted read trains nothing). - **Audit trail:** the note has a new `## Change Log` line; the body is the current truth (no append-only drift); `as_of` = today. - **No duplicate:** exactly one note exists for the entity (`grep -ril "" Brain/Company/` returns one canonical file). ## This skill must refuse to - Write into a non-reference / core / cognitive folder, or set any `provenance` but `reference`. - **Create a duplicate** entity note when resolution finds (or is unsure of) an existing one. - **Auto-supersede or gate-skip on a CRM sub-scope**, or run `/ref-supersede` on the `market/` branch. - Crystallize, lifecycle-classify, synthesis-pulse, or **promote a record into an endorsed cognitive insight** — that crossing stays the human `encountered → endorsed` act.