# KB Intelligence Hub — Design

**Date**: 2026-02-14
**Location**: `kb/`
**Port**: 7960 (kb.localhost)
**Status**: Design

## Purpose

A unified intelligence app with two tabs: **Ask** (research agent) and **Build** (dossier builder). Ask is the consumer-facing entry point — you ask questions about companies, people, industries. Build is the engine — it creates structured dossiers on any entity type. Ask uses Build as a tool, triggering assessments as needed to answer questions.

## Tab 1: Ask (Research Agent)

Chat interface backed by an LLM agent with tools. User asks open-ended questions grounded in assessed data + live web search.

### Example Interactions

- "Find the best SiC power companies under $2B" → discovers candidates, runs lightweight assessments, ranks
- "Who is the strongest CEO in small-cap Japanese semis?" → queries existing dossiers, builds missing ones, synthesizes
- "Compare ROHM vs Allegro on talent" → pulls existing data, fills gaps, renders comparison
- "Build an investment thesis for SiTime" → triggers Build for investment_thesis entity type
- "What supply chain risks does Lasertec face?" → queries supply chain DB + company dossier

### Agent Tools

1. **search_dataset** — query existing dossiers/profiles by keyword, dimension, rating
2. **build_entity** — trigger a Build (company/person/thesis) and wait for results
3. **web_search** — fresh web search for current information
4. **compare** — structured comparison of 2+ entities on specific dimensions
5. **supply_chain** — query supplier/customer/competitor relationships

### Context Injection

Before answering, the agent loads relevant dossier excerpts from the dataset as context. Direct JSON loading (not vector DB) — sufficient at current dataset scale (<1000 entities). If scale demands it later, add embedding-based retrieval.

### Chat Persistence

Chat history persisted per session. Can build on previous questions within a session.

## Tab 2: Build (Universal Dossier Builder)

Interactive interface for creating/steering entity assessments. Works on any entity type.

### Entity Types

**company** (exists — from `intel/companies/semi/`):
- Stages: source_discovery, innovation_pace, founder_deep_dive, crisis_resilience, talent_assessment
- Standard: profile, tftf, competitive
- Data: `intel/companies/semi/data/{slug}/`

**person** (planned — extends `intel/people/`):
- Stages: web_presence, career_trajectory, decision_track_record, network_influence, public_signal, academic_prowess, engineering_prowess, publication_footprint, media_footprint
- Data: `intel/people/data/{slug}/`
- Note: Not all stages apply to every person — stage selection depends on person type (founder, academic, engineer, exec). Presets handle this.

**investment_thesis** (new):
- Stages: profile, bull_case, bear_case, catalyst_map, comparable_analysis, risk_matrix
- Data: `kb/data/thesis/{slug}/`

### Entity Type System

Each entity type defines:
- **stages**: ordered list of assessment functions `(subject, context) → dict`
- **renderer**: stages → markdown → HTML dossier
- **data_dir**: where results are stored
- **schema**: expected JSON structure per stage (for validation)

### UI Layout

- Top: entity type selector (radio) + subject input + optional context/hints
- Middle: stage cards — status (pending/running/done/error), run button, collapsible result
- Bottom: rendered dossier (live-updating as stages complete)
- Sidebar: previously built entities for quick re-access

### Key Interactions

- Run all stages at once or cherry-pick individual ones
- After reviewing a stage result, re-run with refined prompt/focus
- Compare current entity side-by-side with another

## Data Layer

### Shared Data Access (`kb/data_access.py`)

```python
list_entities(type="company", filters={"country": "Japan"}) → [EntitySummary]
get_entity("company", "sitime") → dict  # all stage JSONs
search("SiC power", types=["company", "person"]) → [SearchResult]
get_relationships("rohm-semiconductor") → [Relationship]  # from supply chain DB
```

### No Data Duplication

Reads from existing locations:
- `intel/companies/semi/data/` — company assessments
- `intel/people/data/` — people profiles
- `tools/supplychain/supplychain.db` — supply chain graph
- `kb/data/thesis/` — investment theses (new)
- SEC EDGAR via `edgartools` — 10-K risk factors, DEF 14A exec comp, Forms 3/4 insider trading, XBRL financials
- PatentsView API — patent citation networks, filing velocity
- Finnhub — earnings call transcripts (free tier)

### HTML Reports

Per-entity HTML dossiers served via static.localhost. Generated by the Build pipeline and linked from the app.

## File Structure

```
kb/
  app.py              — Gradio app (2 tabs: Ask, Build)
  entity_types.py     — Entity type registry
  data_access.py      — Shared data layer
  ask/
    ui.py             — Ask tab UI (chat interface)
    agent.py          — LLM agent with tools
    tools.py          — Agent tool definitions
  build/
    ui.py             — Build tab UI
    runner.py         — Stage execution engine
  data/
    thesis/           — Investment thesis dossiers
```

## Lenses

The same entity data can be viewed through different **lenses** depending on purpose. A lens selects which dimensions matter, how to weight them, and what questions to highlight.

### Concept

A lens is a named configuration:
```python
Lens(
    name="investor",
    entity_types=["company", "person", "investment_thesis"],
    dimensions=["innovation_pace", "crisis_resilience", "founder_deep_dive", "competitive"],
    weights={"innovation_pace": 0.3, "founder_deep_dive": 0.3, "crisis_resilience": 0.2, "competitive": 0.2},
    questions=[  # questions this lens cares about
        "Is the company accelerating or decelerating?",
        "Can the CEO build and retain a world-class team?",
        "What's the kill shot bear case?",
    ],
    summary_prompt="Summarize this entity from an investor's perspective...",
)
```

### Example Lenses

| Lens | Focus | Entity Types |
|------|-------|-------------|
| **investor** | Innovation pace, CEO quality, moat, catalysts | company, thesis |
| **recruiter** | Culture, talent density, compensation, retention | company, person |
| **competitor** | Market position, technology gaps, talent poaching risk | company |
| **acquirer** | Integration risk, IP value, key-person dependency | company, person |
| **supply_chain** | Supplier concentration, geographic risk, alternatives | company |

### Implementation

Lenses are declarative configs (YAML or Python dataclass). The data layer is lens-agnostic — lenses are applied at render time:
- **Build tab**: lens selector changes which stages are default-selected and how results are summarized
- **Ask tab**: lens is injected into the agent's system prompt so it prioritizes the right dimensions
- **HTML reports**: lens determines section ordering and which highlights appear in the summary card

Lenses don't change what data is collected — they change what's emphasized and how it's presented.

## Data Viewer (Dev Interface)

A raw data browser for development and debugging. Separate from the consumer-facing Ask/Build tabs.

### Purpose
- Browse all entities across all types
- Inspect raw stage JSONs
- See what's been built, what's missing, what failed
- Trigger rebuilds of stale or failed stages
- Monitor data freshness and coverage

### UI
Could be a third tab ("Data") or a separate lightweight page. Shows:
- Entity table: type, name, ticker, stages completed, last assessed, data freshness
- Click-through to raw JSON per stage
- Bulk actions: rebuild all stale, export, delete

### Capability Exposure
The system should expose what it **can** build, so users (and the Ask agent) know what to request:
```python
get_capabilities() → {
    "company": {
        "stages": ["source_discovery", "innovation_pace", ...],
        "description": "Deep assessment of semiconductor companies",
    },
    "person": {
        "stages": ["web_presence", "career_trajectory", ...],
        "description": "Leadership and track record assessment",
    },
    ...
}
```
This registry is injected into the Ask agent's tool descriptions so it knows what builds are available.

## Identity Resolution

### Problem
The same entity appears under different names across sources:
- "ROHM Co., Ltd." / "ROHM Semiconductor" / "ローム株式会社" / ticker 6963.T
- "Rajesh Vashist" / "R. Vashist" / "CEO of SiTime"

### Approach

**Entity registry** (`kb/identity.py`):
```python
@dataclass
class EntityIdentity:
    canonical_name: str       # "ROHM Semiconductor"
    slug: str                 # "rohm-semiconductor"
    entity_type: str          # "company"
    aliases: list[str]        # ["ROHM Co.", "ローム", "ROHM"]
    identifiers: dict         # {"ticker": "6963.T", "cik": "...", "linkedin": "..."}
    relationships: list[str]  # ["person:isao-matsumoto"]  (cross-type links)
```

**Resolution flow**:
1. User enters "ROHM" → fuzzy match against aliases → resolve to canonical entity
2. When building, new aliases discovered by LLM are added to the registry
3. Cross-type links: company ↔ person (CEO, founders, key hires), company ↔ company (supply chain)

**Storage**: SQLite table in `kb/data/identity.db` — lightweight, queryable, no external dependencies.

## Build Prioritization

### Problem
With 100+ companies in the universe, which ones deserve deep dossiers first?

### Approach: Priority Scoring

A lightweight pre-screen that runs before deep assessment:
```python
@dataclass
class PriorityScore:
    entity: str
    score: float              # 0-1, higher = build first
    signals: dict             # what contributed to the score
    estimated_cost: float     # LLM cost to build full dossier
    staleness_days: int       # days since last assessment (0 if never)
```

**Priority signals** (company example):
- **Novel**: never assessed before → high priority
- **Stale**: assessed >30 days ago + significant news since → re-assess
- **Promising**: high TFTF score, accelerating trajectory → build deeper
- **Requested**: user or Ask agent explicitly requested → highest priority
- **Connected**: linked to other high-priority entities via supply chain or people → boost

**Batch prioritizer**: Given a universe list, scores all entities and returns a build queue. The Ask agent can invoke this: "What should we assess next?"

## Gym Integration

### What Gyms Are
Gyms (`kb/wisdom/`, `explorations/problem_solving_gym/`) are iterative improvement loops: generate → evaluate → improve. The KB hub can leverage this pattern in two ways:

### 1. Assessment Quality Gym
Use the gym pattern to improve assessment quality over time:
- **Generate**: Run assessment stages on a company
- **Evaluate**: Score the assessment on specificity, evidence quality, accuracy (LLM-as-judge or human review)
- **Improve**: Use evaluation feedback to refine prompts, add follow-up questions, fill evidence gaps
- **Iterate**: Re-run improved assessment

This means assessment prompts are not static — they evolve based on evaluation. The gym tracks which prompt versions produce the best assessments.

### 2. Question-Answering Gym
Improve the Ask agent's answer quality:
- **Generate**: Agent answers a research question
- **Evaluate**: Was the answer grounded? Did it cite sources? Did it trigger the right builds?
- **Improve**: Adjust agent system prompt, tool selection, context injection
- **Iterate**: Re-answer with improved config

### Integration Points
- `kb/gym/` — assessment gym configs and runs
- Gym results feed back into prompt templates (assessment stages reference latest-best prompts)
- Gym evaluation scores stored alongside dossiers for quality tracking

## Learning DB Integration

### What Learning DB Is
`learning/` — memory system with pgvector, session review, pattern discovery. Stores evidence-backed principles and gotchas.

### How KB Leverages It

**Write path** (KB → Learning DB):
- When an assessment reveals a surprising pattern (e.g., "all SiC companies have the same supply chain bottleneck"), extract it as a learning
- When the Ask agent discovers that certain question types need specific builds, record as a principle
- When a prompt revision improves assessment quality (via gym), record the improvement pattern

**Read path** (Learning DB → KB):
- Before building a company assessment, check learnings for relevant domain knowledge (e.g., "Japanese semi companies: always check METI filings")
- Before answering an Ask question, inject relevant learnings as context
- Assessment prompts can reference accumulated domain expertise

### Trigger
Use the `principles` skill pattern: after non-trivial assessments or Ask sessions, fork a session to extract generalizable learnings. The KB becomes a source of institutional knowledge about industries, not just individual companies.

## Architecture Layers (Summary)

```
┌─────────────────────────────────────────────────┐
│  Ask (research agent)   │  Build (dossier UI)   │  ← Consumer-facing
├─────────────────────────────────────────────────┤
│  Lenses (investor, recruiter, acquirer, ...)    │  ← Perspective layer
├─────────────────────────────────────────────────┤
│  Entity Types (company, person, thesis, ...)    │  ← Schema layer
├─────────────────────────────────────────────────┤
│  Identity Resolution  │  Build Prioritization   │  ← Intelligence layer
├─────────────────────────────────────────────────┤
│  Data Access (read/write across all sources)    │  ← Data layer
├──────────┬──────────┬──────────┬────────────────┤
│ companies│  people  │ supply   │ thesis │ ...   │  ← Storage
│ semi/data│  data/   │ chain DB │ kb/data│       │
└──────────┴──────────┴──────────┴────────────────┘
         ↕                    ↕
    Gym (quality          Learning DB
    improvement)          (institutional
                          knowledge)
```

## Future: Supply Chain Integration

When building a company dossier, optionally pull supplier/customer relationships from `tools/supplychain/` and include in competitive/crisis analysis. The supply chain lens surfaces this automatically.

## Constraints

- Gradio app, consistent with other rivus apps (HUP reload, footer, CSS patterns)
- LLM calls use `lib/llm/call_llm` with web search grounding
- Must handle concurrent stage execution (async)
- Japan companies: English sources first, Japanese when needed
- Entity types are extensible — adding a new type should be adding one file, not refactoring
- Lenses are declarative configs, not code changes
- Identity resolution is best-effort, not blocking — unknown entities get built, resolution happens in background
- Build prioritization is advisory — user can always override and build anything

## Implementation Phases

### Phase 1: Foundation (current session scope)
- Per-company HTML dossiers ✅ (done)
- Comparative report ✅ (done)
- Static hosting ✅ (done)

### Phase 2: App Shell
- Gradio app with Ask + Build tabs
- Build tab wired to existing `semi/assess.py` stages
- Data access layer reading from existing data dirs
- Capability exposure (what can be built)

### Phase 3: Ask Agent
- Chat interface with tool-use LLM
- Tools: search_dataset, build_entity, web_search, compare
- Context injection from existing dossiers

### Phase 4: Intelligence Layer
- Identity resolution (alias matching, cross-type links)
- Build prioritization (scoring, queue)
- Lenses (investor, recruiter, etc.)
- Data viewer (dev tab)

### Phase 5: Learning Loop
- Gym integration (assessment quality, Q&A quality)
- Learning DB read/write
- Prompt evolution based on gym results
- Person entity type (extends intel/people/)

### Phase 6: Extended Entity Types
- Investment thesis
- Industry/sector analysis
- Supply chain deep integration
