decision
ADR-0028: Profile-aware global-brain retrieval + content applicability taxonomy
ADR-0028 (**Accepted-with-conditions** (2026-06-25) — `ai-engineer` APPROVE-WITH-CHANGES (folded below) + `ceo-blair` APPROVE-WITH-CONDITIONS. **Phase 1** (content metadata) and the **boost-only** retrieval path are cleared to build on staging now. **Hard-filtering, the classification component, and prod go-live are gated** on counsel (Allen) confirming the ADR-0026 sensitive-vertical predicate governs retrieval too + ruling on the "no new PII" classification claim, the shared ADR-0026 predicate landing, and the eval gate. See the Review log., 2026-06-25): Profile-aware global-brain retrieval + content applicability taxonomy.
Status: Accepted-with-conditions (2026-06-25) — ai-engineer APPROVE-WITH-CHANGES (folded below) + ceo-blair APPROVE-WITH-CONDITIONS. Phase 1 (content metadata) and the boost-only retrieval path are cleared to build on staging now. Hard-filtering, the classification component, and prod go-live are gated on counsel (Allen) confirming the ADR-0026 sensitive-vertical predicate governs retrieval too + ruling on the “no new PII” classification claim, the shared ADR-0026 predicate landing, and the eval gate. See the Review log.
Date: 2026-06-25
Deciders: Seth Shoultes (Lead Architect), Blair Williams (CEO)
Author: Seth Shoultes
Context
The global brain now holds curated playbooks (ADR-0026), de-identified
primary_research, and the hive_docs substrate. Today, retrieval
(src/memberintel/api/retrieval/search.py) is vector kNN over a user-tenant +
global union (global memory excluded, parent-document dedup) — with no
personalization by the customer’s business profile.
But the advisor’s value is profile-specific advice. The playbooks are largely
archetype-driven: “default to annual billing” is a mass-market move;
“gate high-ticket behind an application” is a high-ticket move — true whether
the operator is in fitness or finance. Serving every operator the same
undifferentiated set dilutes the advisor and occasionally gives actively-wrong
advice (telling a $5K-mastermind coach to discount an annual SKU).
We already have a data-grounded taxonomy from the Connect Intelligence analysis:
8 industries (finance, education, health, media, coaching, fitness, tech, faith),
11 archetypes (association, saas-tool, coaching, media-paywall, paid-community,
content-subscription, course-academy, offline-service, certification,
donation-nonprofit, hybrid-ascension), 5 business models (recurring, mixed,
one-off, high-ticket, annual-prepay), and scale bands ($100K → $10M+).
Three distinct needs fall out: (a) tag content with who it applies to;
(b) classify the customer’s profile; (c) match at retrieval time.
Decision
Adopt a two-axis content model + profile-aware retrieval, delivered in three
phases.
1. Two orthogonal axes on brain content. Keep category (functional — what
the move is: pricing / churn / acquisition / …). Add an applicability layer
(who it’s for): industry, archetype / business_model, optional scale.
- Controlled vocabularies, one source of truth — a taxonomy module (mirroring
KNOWN_CATEGORIESand theTIERSdict), enforced by the playbook validator and
reused by profiling and retrieval. No free-form industry strings. - Default
industry: [all]— most playbooks are cross-industry; tag a specific
industry only when a play genuinely is one. Archetype /business_modelis the
primary match axis; industry is secondary (tone + examples + the
sensitive-vertical synergy below). hive_docssubstrate stays untagged (industry: [all]); only curated content
carries applicability.
2. Customer profile classification. Derive the customer’s
industry / archetype / business_model / scale from synced MemberPress data
(memberships, pricing, transaction patterns — already available via
src/memberintel/api/brain/context.py) plus intake signals, and store it on the
profile with a confidence signal (drives the retrieval fallback below).
Classification is deterministic derivation from billing data — never a
per-query LLM call; if an LLM assist is ever added it runs on Haiku, batched, at
most once per sync_site(), re-deriving on that same trigger so the profile can’t
go stale. The “no new PII” claim is a counsel question to verify, not assert
(a derived business classification is a new inference about a customer) — see the
Review-log condition.
3. Profile-aware retrieval. Applicability match is a post-retrieval score
re-rank on the global leg — not a SQL WHERE predicate that could silently
zero out the global brain on a mis-classification. Boost is the only
personalization mechanism; the only thing allowed to hard-filter is the
sensitive-vertical guard (a safety exclusion, not a personalization knob), which
reuses the identical counsel-gated predicate from
ADR-0026 — no second definition of
“sensitive.” Until that predicate lands, this ships boost-only, no
retrieval-time hard filter. So the boost isn’t cosmetic, widen the global-leg
over-fetch (or add a mild SQL-side applicability tiebreaker) so a strongly-applicable
chunk isn’t cut by raw cosine before the re-rank sees it. Customer-brain
(tenant_id=<user>) retrieval is unchanged.
Consequences
Positive:
- Advice matches the operator’s actual business — the moat content is targeted,
not generic, and we stop serving confidently-wrong cross-profile advice. - One vocabulary is reused three ways: content tagging, customer profiling, and the
sensitive-vertical guard (health / faith already overlap the industry list). - Phase 1 is additive and reversible — pure metadata, no behavior change.
Negative / costs:
- Profile classification can be wrong; a mis-tagged customer gets mis-targeted
advice. Mitigation: a confidence threshold with fallback to unfiltered
retrieval, and boost-over-hard-filter so adjacent advice isn’t hidden. - Retrieval gains a metadata predicate on the global leg — minor query cost now;
JSONB-vs-column indexing to revisit at scale (echoes ADR-0026 Open Question 2). - Controlled-vocabulary maintenance discipline (don’t let the enums sprawl).
Neutral / follow-ups:
- Ties to ADR-0015 (customer
brain — where the profile lives) and ADR-0026
(global brain — what’s tagged). - The industry vocabulary doubles as the counsel-owned sensitive-vertical exclusion
list. - Eval coverage is a release gate (per CLAUDE.md — this is a retrieval-surface
change). Required before Phase 3 merge: a fixed (profile, query) →
expected-applicable-playbook eval set proving relevant-profile lift, and a
regression test that the low-confidence fallback returns the same result set as
today’s unfiltered retrieval.
Alternatives considered
- Pure semantic matching (rely on embeddings + the customer’s SOUL/BIBLE in the
query). Rejected as the sole mechanism — embeddings capture topic, not reliably
“this applies only to associations”; explicit applicability is more reliable and
auditable. Semantic + metadata together is the design. - Overload
categorywith industry/archetype. Rejected — conflates two
orthogonal axes and fragments the functional taxonomy. - Free-form industry tags. Rejected — fragments retrieval; the data-grounded
controlled vocab is the source of truth. - Hard filter only. Rejected — over-filtering hides useful adjacent advice;
default to boost, reserve hard-exclude for genuinely wrong or sensitive content.
Open questions
- Confidence threshold needs a number and a measurement — the signal’s
scale, the value that trips the unfiltered fallback, and the eval that calibrates
it. “Confidence-gated” is a vibe until this is pinned. - Re-rank placement vs. the over-fetch in
search.py; JSONB predicate vs
promoting applicability to columns at scale (echoes ADR-0026 OQ2). - Scale-band: ship as a stored signal but not a boost axis in V1 (YAGNI);
promote to a match axis only if evals show archetype alone mis-targets. - Where the customer profile lives — extend
user_souls/site_contextsvs a
dedicated classification field (Phase 2 design). Tie re-derivation to
sync_site()so a customer who pivots (courses → coaching) isn’t stale-profiled.
Review log
- 2026-06-25 — Drafted (Seth). Pending
ai-engineerreview →ceo-blair
approval. - 2026-06-25 —
ai-engineerreview: APPROVE-WITH-CHANGES (folded into the
Decision): (a) boost = post-retrieval re-rank, only the sensitive-vertical guard
may hard-filter; (b) that filter reuses ADR-0026’s counsel-gated predicate —
boost-only until it lands; (c) eval coverage is a release gate incl. the
low-confidence==unfiltered regression test; (d) widen the over-fetch so boost
isn’t cosmetic. Classification must be deterministic (no per-query LLM) to stay
cost-neutral — confirmed ~$0 added per query (pre-LLM DB re-rank; tokens to the
model unchanged or slightly reduced). Full review:
reviews/2026-06-25-adr-0028-profile-aware-retrieval.md. - 2026-06-25 —
ceo-blairgate: APPROVE-WITH-CONDITIONS. Green to build the
boost-only path on staging now. Before the classification component / any
hard-filter: (1) Allen confirms in writing that the ADR-0026
sensitive-vertical predicate governs both write-path and retrieval-time
filtering; (2) Allen rules whether a derived business-archetype classification
is “no new PII” + any consent-language impact (blocks the classification
component, not boost-only retrieval); (3) Seth’s eval-coverage plan is the
named release gate; (4) boost-only ships first — hard-filter off until the
shared ADR-0026 predicate lands. Cost target held; SPEC §4 honesty clean (ranking
over our own brain, not training on customer data). Status → Accepted when
(1)+(2) clear. - 2026-06-25 — Copilot review (PR #193). Addressed: corrected the Context
retrieval description (user+global union, memory-excluded, dedup — not “filtered
only by tenant/collection”) and dropped the brittle “21” count; normalized
applicability example syntax (industry: [all]list form;business_model
underscore).