Veritas
by Lsyedibrahim
README.md
# Veritas
An AI-powered data investigation workspace for Product Managers, combining structured investigation workflows with a collectively maintained three-tier data catalog.
## What This Is
Two things working together:
1. **Investigation MCP Server** -- a custom MCP server that provides investigation lifecycle tools (start, continue, capture, close), three-tier catalog management (local/community/curated), and a self-improving memory system
2. **Data Investigation Framework** -- a structured workflow for running multi-session analyses with persistent context, findings tracking, and institutional knowledge that compounds over time
3. **Agent Memory System** -- behavioral learning that enables the AI agent to remember corrections, preferences, and workflow patterns across sessions, with a promotion pipeline for turning recurring patterns into permanent rule improvements
Data access (SQL queries, schema discovery, profiling) is handled by the **official Databricks MCP server**, which runs alongside the investigation MCP server. This separation means adding new data sources (Dynatrace, Amplitude, etc.) is just adding another MCP server entry.
## Quick Start
Setup takes ~5 minutes. See [GETTING_STARTED.md](GETTING_STARTED.md) for the full guide with screenshots, or follow the quick version:
### 1. Clone and run setup
```bash
git clone https://github.com/hertzcorp/htzd-databricks-mcp.git
cd htzd-databricks-mcp
```
**Mac / Linux:** `./setup.sh` | **Windows (PowerShell):** `.\setup.ps1`
The script checks prerequisites, installs dependencies, then asks you a few questions: your name, email, Databricks HTTP path, and a personal access token. It shows you the exact links to copy each value. One run — no editing files.
### 2. Restart Cursor and approve MCP servers
Restart Cursor (Mac: Cmd+Q | Windows: Alt+F4, then reopen). When it starts, click **"Start"** on the two MCP server prompts at the bottom of the screen. This is a one-time approval -- all tools are pre-approved after that.
### 3. Start asking questions
Open the Chat panel (Mac: Cmd+Shift+I | Windows: Ctrl+Shift+I) and try:
- "What tables do we know about?" -- browse the team's data catalog
- "Start investigation" -- begin a tracked multi-session analysis
- "What data do we have on billing?" -- search the catalog for relevant knowledge
- "Deep investigate: why is contact rate rising?" -- autonomous recursive investigation
- "Deep index" -- crawl Databricks lineage to build the table knowledge base
See [docs/ONE-PAGER.md](docs/ONE-PAGER.md) for a quick reference of all features with end-to-end examples.
## Project Structure
```
.
├── src/investigation_mcp/ # Investigation MCP server
│ ├── server.py # MCP server entry point (24 tools)
│ └── tools/ # Tool implementations
│ ├── investigation.py # Start, continue, capture, close investigations
│ ├── catalog_index.py # Catalog reading: index, entries, health, context
│ ├── catalog_local.py # Local entry capture + preferences
│ ├── catalog_sharing.py # Share local entries to community via PR
│ ├── catalog_curation.py # Curator tools: review, approve, reject
│ ├── memory.py # Agent memory: capture, load, reinforce, review, apply
│ ├── _git_helpers.py # Shared git utilities
│ └── catalog_management.py # Legacy catalog tools (deprecated)
├── data-catalog/ # Three-tier data catalog
│ ├── curated/ # Reviewed, authoritative knowledge (team-shared)
│ ├── community/ # Unvetted contributions from team members (team-shared)
│ ├── local/ # Personal notes, auto-captured (gitignored)
│ ├── _deep_index/ # Pre-computed table knowledge base (team-shared)
│ ├── _schema.yaml # Entry type definitions
│ └── _curators.yaml # Approved catalog curators
├── investigations/ # Tracked analyses (gitignored except templates + index)
│ └── _templates/ # Templates for new investigations
├── docs/
│ ├── hertzcorp-architecture/ # Hertz system architecture references
│ ├── adoption/ # Adoption strategy and growth plans
│ ├── workshop/ # Workshop facilitator guide and slide assets
│ ├── ONE-PAGER.md # Quick feature reference
│ ├── SPEC.md # Technical specification
│ └── PATTERNS.md # Architectural patterns
├── .cursor/
│ ├── memory/ # Agent behavioral memory (gitignored)
│ │ ├── corrections/ # Behavioral corrections (YAML)
│ │ ├── preferences/ # Style and output preferences (YAML)
│ │ ├── patterns/ # Detected workflow patterns (YAML)
│ │ └── reflections/ # Session retros (Markdown)
│ ├── rules/ # Cursor rules
│ │ ├── analysis-principles.mdc # 8 data analysis principles
│ │ ├── memory.mdc # Agent memory behavior (when to capture/load/cite)
│ │ ├── pm-guardrails.mdc # Prevents AI from modifying protected files
│ │ ├── first-run.mdc # Welcome experience for new users
│ │ └── ... # Development workflow rules
│ ├── hooks/
│ │ └── memory-flush.py # Advisory: remind to capture learnings at session end
│ └── skills/
│ └── data-investigation/ # Investigation workflow skill
├── ideation/ # Product concepts and drafts (gitignored)
├── scripts/ # Standalone analysis scripts
├── .github/
│ └── workflows/
│ └── catalog-validation.yml # CI: validates catalog entries on PR
├── setup.sh # Onboarding wizard
├── GETTING_STARTED.md # PM-friendly setup guide
└── pyproject.toml # Package: investigation-toolkit
```
## Three-Tier Data Catalog
The catalog is the institutional knowledge layer. It grows with every investigation.
| Tier | Location | Shared? | Trust Level | How It Gets There |
|------|----------|---------|-------------|-------------------|
| **Local** | `data-catalog/local/` | No (gitignored) | Personal notes | AI auto-captures during investigations |
| **Community** | `data-catalog/community/` | Yes (via PR) | Unvetted | PM shares via `share_to_catalog` tool |
| **Curated** | `data-catalog/curated/` | Yes (via PR) | Authoritative | Curator promotes from community |
**Knowledge lifecycle:**
```
Investigation discovers knowledge
-> AI auto-captures to local/ (continuous, silent)
-> PM selects what to share ("share this with the team")
-> share_to_catalog creates PR to community/ (CI validates, approver merges)
-> Curator reviews community entries (review_pending)
-> Curator promotes to curated/ (approve_entry) or rejects (reject_entry)
```
**The AI reads all three tiers** with trust ordering: curated (high confidence) > community (hints, verified before use) > local (personal recall).
## Investigation Framework
### How It Works
Say "start investigation" in Cursor chat to begin a tracked analysis. The framework:
1. **Discovery** -- loads the catalog, refines the question, finds the right tables
2. **Analysis** -- runs queries via Databricks MCP, auto-captures discoveries to local catalog
3. **Validation** -- samples raw records, confirms field semantics, checks system behavior
4. **Capture** -- saves findings, presents unshared catalog entries for sharing
5. **Close** -- marks complete, prompts for catalog sharing
Investigations persist across sessions. Say "continue investigation" to resume where you left off.
## Agent Memory System
The agent learns from your corrections and preferences over time through two paths:
**Soft path (immediate):** Corrections and preferences are saved to `.cursor/memory/` and loaded into context at the start of future sessions. The agent adjusts its behavior based on past learnings without any structural changes.
**Hard path (permanent):** When a correction recurs 3+ times across sessions, the agent detects the pattern and proposes a permanent change to the workflow rules or investigation skill. You approve before anything changes. Platform-scope proposals create a PR for team review.
| What | How |
|------|-----|
| Correct the agent | It calls `capture_memory` automatically -- remembered next session |
| Same correction 3x | Pattern detected, proposed as a rule change at session end |
| Approve a proposal | `apply_proposal` edits the rule file (personal) or creates a PR (platform) |
| Wrong promotion | Agent detects contradiction and proposes rollback |
| Check system health | `memory_stats` shows counts, averages, maintenance status |
**Memory is personal and gitignored.** Each PM's agent learns independently. Improvements that benefit everyone flow through the PR-based promotion pipeline.
### Analysis Principles
The `.cursor/rules/analysis-principles.mdc` rule enforces eight principles:
1. **Ground truth first** -- sample raw records before aggregating
2. **Profile before joining** -- verify field contents, don't assume from names
3. **Ask about system behavior early** -- domain knowledge shapes data interpretation
4. **Correlation is not causation** -- prevalence on a record does not equal cause
5. **Explicit assumptions** -- every volume estimate needs a stated deflection rate
6. **Hypotheses before conclusions** -- present as "data suggests" until validated
7. **Flag observability gaps** -- generic error codes need decomposition, not sizing
8. **Signal catalog trust level** -- indicate whether knowledge is curated, community, or local
## Commands Reference
### Investigation Commands
| Command | What It Does |
|---------|-------------|
| `start investigation` | Create a new tracked investigation |
| `continue [name]` | Resume a previous investigation with full context |
| `capture findings` | Save findings and offer to share catalog entries |
| `close investigation` | Mark complete, prompt for final catalog sharing |
| `list investigations` | Show active and recent investigations |
### Catalog Commands
| Command | What It Does |
|---------|-------------|
| `What tables do we know about?` | Load catalog index -- shows all entries across tiers |
| `What do we know about [topic]?` | Load entries for a specific domain or subject |
| `share this with the team` | Share a local catalog entry to community via PR |
| `catalog health` | Show catalog metrics: backlog, coverage, stale entries |
| `retry pending shares` | Retry shares that failed due to connectivity |
### Curator Commands
| Command | What It Does |
|---------|-------------|
| `review catalog` | Show pending community entries grouped by domain |
| `approve [entry]` | Promote a community entry to curated (curator-only) |
| `reject [entry]` | Remove a community entry with optional reason |
## MCP Tools Reference
### Investigation MCP (Custom)
| Tool | Description |
|------|-------------|
| `start_investigation` | Create investigation folder with templates |
| `continue_investigation` | Load investigation context and resume |
| `capture_findings` | Save findings, prompt for catalog sharing |
| `close_investigation` | Mark complete, final catalog check |
| `list_investigations` | List active/completed investigations |
| `load_catalog_index` | Lightweight index of all catalog entries |
| `get_catalog_entries` | Full content for entries matching filter |
| `get_data_context` | Read curated domain knowledge |
| `catalog_health` | Catalog metrics and health summary |
| `add_local_entry` | Capture a discovery to local catalog |
| `share_to_catalog` | Share local entry to community via PR |
| `retry_pending_shares` | Retry failed shares from offline sessions |
| `review_pending` | Summarize unreviewed community entries |
| `approve_entry` | Promote community entry to curated (curator-only) |
| `reject_entry` | Remove community entry (curator-only) |
| `get_preferences` | Read learned preferences |
| `save_preference` | Save a preference for future sessions |
| `capture_memory` | Capture a correction, preference, or pattern to memory |
| `load_relevant_memories` | Load scored, filtered memories for current context |
| `reinforce_memory` | Reinforce an existing memory when same correction recurs |
| `learning_review` | Generate end-of-session learning summary with proposals |
| `capture_reflection` | Write a structured session retro to memory |
| `apply_proposal` | Apply approved proposal to rule/skill file (or create PR) |
| `memory_stats` | Report memory system health and run maintenance |
### Official Databricks MCP (Data Access)
Data access tools are provided by the official Databricks MCP server:
| Tool | Description |
|------|-------------|
| `list_catalogs` | List Unity Catalog catalogs |
| `list_schemas` | List schemas in a catalog |
| `list_tables` | List tables in a schema |
| `describe_table` | Get column details |
| `execute_sql` | Run SQL queries |
| `sample_data` | Get sample rows |
| `profile_table` | Generate data quality profile |
## Tips for Better Results
**At the start of an investigation:**
- The AI loads the catalog automatically. For new domains without curated entries, tell the AI what tables to use.
- Share system context early -- how key systems behave, known data quirks, business rules.
- State a hypothesis: "I think X is caused by Y" is more productive than "Tell me about X."
**During analysis:**
- Challenge aggregate findings. Ask "Have you looked at actual records?"
- When the AI presents a volume estimate, ask about the assumption: "What deflection rate?"
- The AI auto-captures gotchas, joins, and terms to your local catalog as it discovers them.
**At the end of a session:**
- Say "capture findings" to save progress. The AI presents unshared catalog entries for sharing.
- Choose which discoveries to share with the team. The AI handles the PR.
**For executive deliverables:**
- Ask the AI to create a separate brief rather than editing findings.md.
- Push back on oversimplified narratives. Ask for sub-problems.
- Request an assumptions and limitations section.
## Extending with Additional MCP Servers
Adding a new data source is just adding an entry to `.cursor/mcp.json.template`:
```json
{
"mcpServers": {
"dynatrace": {
"command": "npx",
"args": ["-y", "@dynatrace-oss/dynatrace-mcp-server@latest"],
"env": {
"DT_URL": "{{DT_URL}}",
"DT_TOKEN": "{{DT_TOKEN}}"
}
}
}
}
```
The investigation MCP and catalog are source-agnostic. The catalog's `system` field tracks which data source knowledge came from.
## Running Scripts
Legacy standalone analysis scripts can be run from the repo root. Note: some older scripts may reference the previous `databricks_mcp` package which has been renamed to `investigation_mcp`. See the scripts directory for details.
## Troubleshooting
### "MCP server not showing in Cursor"
- Run `./setup.sh --test-only` to validate configuration
- Restart Cursor completely (Cmd+Shift+P > "Reload Window")
- Check `.cursor/mcp.json` exists and has correct paths
### "Setup fails at connection test"
- Verify your Databricks workspace URL includes `https://`
- Check that your personal access token hasn't expired
- Ensure your SQL Warehouse is running
- Try `./setup.sh --no-test` to skip validation, fix credentials in `.env`, then `./setup.sh --test-only`
### "Table not found"
- Check the full table path (catalog.schema.table)
- Use `load_catalog_index` to see what the team knows about
- Verify you have access to the table in Databricks
## Security Notes
- Databricks tokens stored in `.env` (gitignored, never committed)
- Local catalog entries are gitignored (personal to each user)
- Community catalog entries go through PR review before merging
- CI scans catalog PRs for secrets and PII patterns
- PM guardrails rule prevents AI from modifying protected files (rules, skills, curated catalog) -- exception: `apply_proposal` during approved learning reviews
- Agent memory files are gitignored (personal behavioral learnings never pushed to remote)
- Memory promotions to rule files require explicit human approval; platform-scope changes go through PR review
- Curator authorization enforced programmatically via `_curators.yaml`
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessSyncing