Create Investigation
Investigations are one-off analyses of something in Ethereum.
Golden Rules:
- They must use a fixed time range for the data so that the analysis is reproducible.
- Agents must actually check the data - do not make up conclusions. It's better to not write a conclusion than to write a conclusion that is not supported by the data.
- Ask the user for clarifying questions. Be thorough.
Requirements to Gather
- Title: Investigation title (e.g., "Head Vote Accuracy by Entity Type")
- Slug: URL-safe identifier (e.g., "head-accuracy-by-entity")
- Description: Brief description for SEO and sidebar hover
- Author: Username from supported list (samcm, parithosh, pk910, savid, skylenet, mattevans, qu0b, barnabasbusa, ethpandaops)
- Tags: Relevant tags for categorization
- Network: mainnet, sepolia, hoodi, etc.
- Time Range: Fixed start and end dates (investigations MUST use fixed time ranges for reproducibility)
- Research Question: The specific question being investigated
File Structure
Create the investigation at pages/YYYY-MM/{slug}/index.md where YYYY-MM is the current year-month.
If the year-month folder doesn't exist, create pages/YYYY-MM/index.md:
---
title: YYYY Mon
sidebar_position: 1
---
Investigations from Month Year.
Page Template
---
title: {Title}
sidebar_position: {N}
description: {Brief description}
date: {YYYY-MM-DDTHH:MM:SSZ}
author: {username}
tags:
- tag1
- tag2
---
<script>
import PageMeta from '$lib/PageMeta.svelte';
import Section from '$lib/Section.svelte';
import SqlSource from '$lib/SqlSource.svelte';
</script>
<PageMeta
date="{YYYY-MM-DD}"
author="{username}"
tags={["tag1", "tag2"]}
description="{Brief description}"
networks={["Ethereum Mainnet"]}
startTime="{YYYY-MM-DD}T00:00:00Z"
endTime="{YYYY-MM-DD}T23:59:59Z"
/>
```sql query_name
SELECT ... FROM xatu_cbt.table_name
Question
{The specific research question being investigated}
Background
{Context and explanation of concepts. Use bold for key terms being defined.}
Investigation
When {Action}
{Explanation of what this analysis shows}
<LineChart
data={query_name}
x="x_column"
y={["Series 1", "Series 2", "Series 3"]}
sort=false
title="Chart Title"
yFmt="num2"
chartAreaHeight=400
yMax=100
colorPalette={['#2563eb', '#ea580c', '#16a34a']}
echartsOptions={{
title: {left: 'center'},
grid: {bottom: 50, left: 70, top: 60, right: 120},
xAxis: {type: 'category', name: 'X Axis Label', nameLocation: 'center', nameGap: 35},
yAxis: {min: 0, max: 100},
legend: {show: true, right: 10, orient: 'vertical', top: 'center'},
series: [
{name: 'Series 1', lineStyle: {width: 3}},
{name: 'Series 2', lineStyle: {width: 2}},
{name: 'Series 3', lineStyle: {width: 2}}
],
graphic: [{
type: 'text',
left: 15,
top: 'center',
rotation: Math.PI / 2,
style: {
text: 'Y Axis Label',
fontSize: 12,
fill: '#666'
}
}]
}}
/>
Takeaways
- Key finding 1
- Key finding 2
- Key finding 3
Critical Rules
SQL queries MUST be at top level - Not wrapped in HTML elements or Sections. Evidence's preprocessor won't process them otherwise.
Fixed time range required - PageMeta MUST have startTime and endTime props for reproducibility.
Escape < and > in prose - Use inline code backticks: `z < 0` not z < 0.
Charts require three labels:
title prop (centered via title: {left: 'center'})
- X-axis label via
xAxis: {name: '...', nameLocation: 'center', nameGap: 35}
- Y-axis label via
graphic element (NOT yAxis.name which doesn't center properly)
Action-based section headers - Use "When Attesting" not "Attester Analysis".
No "Analysis" suffix in titles - "Analysis" is implied; use "RPC Snooper Overhead" not "RPC Snooper Overhead Analysis".
Don't repeat header - The title from frontmatter is already rendered by the layout.
Sort time series data ascending - SQL queries for charts MUST include ORDER BY date_column ASC to ensure data is sorted chronologically. Charts will display incorrectly if data is not sorted.
Use high-contrast colors - Multi-line charts MUST use colorPalette with high-contrast colors. Recommended palette:
- Red:
#dc2626
- Blue:
#2563eb
- Purple:
#9333ea
- Green:
#16a34a
- Orange:
#ea580c
Example: colorPalette={['#2563eb', '#ea580c', '#16a34a']}
Line styling for emphasis - Make the primary metric line thicker (width: 3), use dashed lines for secondary metrics like averages/means:
series: [
{name: 'Primary', lineStyle: {width: 3}},
{name: 'Secondary', lineStyle: {width: 2, type: 'dashed'}}
]
Reference lines with markLine - For horizontal reference lines (e.g., "random chance"), use markLine NOT a separate series (which corrupts the x-axis). Position label inside the chart:
series: [{
markLine: {
silent: true,
symbol: 'none',
label: {show: true, position: 'insideEndTop', formatter: 'Label text'},
lineStyle: {type: 'dashed', color: '#888'},
data: [{yAxis: 0.56}]
}
}]
Human-readable SQL column names - Use column aliases that will appear nicely in chart legends:
SELECT
hour,
round(avg(our_time)) as "Our Node",
round(avg(median_time)) as "Network Median"
Don't describe chart features that don't exist - Never claim "tight IQR band", "green for negative values", or specific colors in prose unless the chart actually shows them. Verify visually before writing conclusions.
Per-block comparisons for timing analysis - When comparing timing between nodes, calculate metrics per-block first, then aggregate. Don't compare raw averages across all data which can be misleading.
SQL Source Files
For reusable queries, create sources/xatu_cbt/{query_name}.sql:
SELECT
date_column,
column1,
column2
FROM xatu_cbt.table_name
WHERE slot_start_date_time >= '2025-12-21'
AND slot_start_date_time < '2026-01-21'
ORDER BY date_column ASC
Then reference in the page:
SELECT * FROM xatu_cbt.{query_name}
Available Chart Types
LineChart, BarChart, AreaChart, ScatterPlot, DataTable, BigValue, Value
1---2name: create-investigation3description: Create a new Ethereum data investigation page in the notebooks repo. Use when the user wants to add a new investigation, analysis, or research page that queries Xatu/ClickHouse data and visualizes findings with charts.4---56# Create Investigation78Investigations are one-off analyses of something in Ethereum. 910## Golden Rules:11- They must use a fixed time range for the data so that the analysis is reproducible.12- Agents must actually check the data - do not make up conclusions. It's better to not write a conclusion than to write a conclusion that is not supported by the data.13- Ask the user for clarifying questions. Be thorough.1415## Requirements to Gather16171. **Title**: Investigation title (e.g., "Head Vote Accuracy by Entity Type")182. **Slug**: URL-safe identifier (e.g., "head-accuracy-by-entity")193. **Description**: Brief description for SEO and sidebar hover204. **Author**: Username from supported list (samcm, parithosh, pk910, savid, skylenet, mattevans, qu0b, barnabasbusa, ethpandaops)215. **Tags**: Relevant tags for categorization226. **Network**: mainnet, sepolia, hoodi, etc.237. **Time Range**: Fixed start and end dates (investigations MUST use fixed time ranges for reproducibility)248. **Research Question**: The specific question being investigated2526## File Structure2728Create the investigation at `pages/YYYY-MM/{slug}/index.md` where YYYY-MM is the current year-month.2930If the year-month folder doesn't exist, create `pages/YYYY-MM/index.md`:31```markdown32---33title: YYYY Mon34sidebar_position: 135---3637Investigations from Month Year.38```3940## Page Template4142```markdown43---44title: {Title}45sidebar_position: {N}46description: {Brief description}47date: {YYYY-MM-DDTHH:MM:SSZ}48author: {username}49tags:50 - tag151 - tag252---5354<script>55 import PageMeta from '$lib/PageMeta.svelte';56 import Section from '$lib/Section.svelte';57 import SqlSource from '$lib/SqlSource.svelte';58</script>5960<PageMeta61 date="{YYYY-MM-DD}"62 author="{username}"63 tags={["tag1", "tag2"]}64 description="{Brief description}"65 networks={["Ethereum Mainnet"]}66 startTime="{YYYY-MM-DD}T00:00:00Z"67 endTime="{YYYY-MM-DD}T23:59:59Z"68/>6970```sql query_name71SELECT ... FROM xatu_cbt.table_name72```7374<Section type="question">7576## Question7778{The specific research question being investigated}7980</Section>8182<Section type="background">8384## Background8586{Context and explanation of concepts. Use **bold** for key terms being defined.}8788</Section>8990<Section type="investigation">9192## Investigation9394### When {Action}9596{Explanation of what this analysis shows}9798<SqlSource source="$source" query="query_name" />99100<LineChart101 data={query_name}102 x="x_column"103 y={["Series 1", "Series 2", "Series 3"]}104 sort=false105 title="Chart Title"106 yFmt="num2"107 chartAreaHeight=400108 yMax=100109 colorPalette={['#2563eb', '#ea580c', '#16a34a']}110 echartsOptions={{111 title: {left: 'center'},112 grid: {bottom: 50, left: 70, top: 60, right: 120},113 xAxis: {type: 'category', name: 'X Axis Label', nameLocation: 'center', nameGap: 35},114 yAxis: {min: 0, max: 100},115 legend: {show: true, right: 10, orient: 'vertical', top: 'center'},116 series: [117 {name: 'Series 1', lineStyle: {width: 3}},118 {name: 'Series 2', lineStyle: {width: 2}},119 {name: 'Series 3', lineStyle: {width: 2}}120 ],121 graphic: [{122 type: 'text',123 left: 15,124 top: 'center',125 rotation: Math.PI / 2,126 style: {127 text: 'Y Axis Label',128 fontSize: 12,129 fill: '#666'130 }131 }]132 }}133/>134135</Section>136137<Section type="takeaways">138139## Takeaways140141- Key finding 1142- Key finding 2143- Key finding 3144145</Section>146```147148## Critical Rules1491501. **SQL queries MUST be at top level** - Not wrapped in HTML elements or Sections. Evidence's preprocessor won't process them otherwise.1511522. **Fixed time range required** - PageMeta MUST have `startTime` and `endTime` props for reproducibility.1531543. **Escape `<` and `>` in prose** - Use inline code backticks: `` `z < 0` `` not `z < 0`.1551564. **Charts require three labels**:157 - `title` prop (centered via `title: {left: 'center'}`)158 - X-axis label via `xAxis: {name: '...', nameLocation: 'center', nameGap: 35}`159 - Y-axis label via `graphic` element (NOT `yAxis.name` which doesn't center properly)1601615. **Action-based section headers** - Use "When Attesting" not "Attester Analysis".1621636. **No "Analysis" suffix in titles** - "Analysis" is implied; use "RPC Snooper Overhead" not "RPC Snooper Overhead Analysis".1641657. **Don't repeat header** - The title from frontmatter is already rendered by the layout.1661678. **Sort time series data ascending** - SQL queries for charts MUST include `ORDER BY date_column ASC` to ensure data is sorted chronologically. Charts will display incorrectly if data is not sorted.1681699. **Use high-contrast colors** - Multi-line charts MUST use `colorPalette` with high-contrast colors. Recommended palette:170 - Red: `#dc2626`171 - Blue: `#2563eb`172 - Purple: `#9333ea`173 - Green: `#16a34a`174 - Orange: `#ea580c`175 Example: `colorPalette={['#2563eb', '#ea580c', '#16a34a']}`17617710. **Line styling for emphasis** - Make the primary metric line thicker (width: 3), use dashed lines for secondary metrics like averages/means:178 ```javascript179 series: [180 {name: 'Primary', lineStyle: {width: 3}},181 {name: 'Secondary', lineStyle: {width: 2, type: 'dashed'}}182 ]183 ```18418511. **Reference lines with markLine** - For horizontal reference lines (e.g., "random chance"), use `markLine` NOT a separate series (which corrupts the x-axis). Position label inside the chart:186 ```javascript187 series: [{188 markLine: {189 silent: true,190 symbol: 'none',191 label: {show: true, position: 'insideEndTop', formatter: 'Label text'},192 lineStyle: {type: 'dashed', color: '#888'},193 data: [{yAxis: 0.56}]194 }195 }]196 ```19719812. **Human-readable SQL column names** - Use column aliases that will appear nicely in chart legends:199 ```sql200 SELECT201 hour,202 round(avg(our_time)) as "Our Node",203 round(avg(median_time)) as "Network Median"204 ```20520613. **Don't describe chart features that don't exist** - Never claim "tight IQR band", "green for negative values", or specific colors in prose unless the chart actually shows them. Verify visually before writing conclusions.20720814. **Per-block comparisons for timing analysis** - When comparing timing between nodes, calculate metrics per-block first, then aggregate. Don't compare raw averages across all data which can be misleading.209210211## SQL Source Files212213For reusable queries, create `sources/xatu_cbt/{query_name}.sql`:214```sql215SELECT216 date_column,217 column1,218 column2219FROM xatu_cbt.table_name220WHERE slot_start_date_time >= '2025-12-21'221 AND slot_start_date_time < '2026-01-21'222ORDER BY date_column ASC223```224225Then reference in the page:226```sql query_name227SELECT * FROM xatu_cbt.{query_name}228```229230## Available Chart Types231232LineChart, BarChart, AreaChart, ScatterPlot, DataTable, BigValue, Value