feat(cli): replace fake demo data with real NBC/Orbit project context

Replace the placeholder demo assets with real semantic-layer (45 YAML
files) and knowledge (28 markdown files) from the fully-built NBC
project. Update demo tour cards, replay timeline, and completion
summary to reflect real connection names and counts:
- PostgreSQL warehouse: 56 tables across 2 schemas
- dbt: 34 transformation models
- Metabase: 80 dashboard cards
- Notion: 9 knowledge pages
- 45 semantic layer definitions, 32 knowledge pages created

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Luca Martial 2026-05-11 21:51:54 -07:00
parent c75871bd34
commit ebf475e4c1
100 changed files with 5067 additions and 472 deletions

View file

@ -91,22 +91,17 @@ describe('demo assets', () => {
expect(manifest.sources.bi.explores).toBeGreaterThanOrEqual(2);
expect(manifest.sources.bi.dashboards).toBeGreaterThanOrEqual(2);
expect(manifest.sources.notion.pages).toBeGreaterThanOrEqual(5);
expect(manifest.generated.semanticLayer.sourceCount).toBeGreaterThanOrEqual(5);
expect(manifest.generated.knowledge.pageCount).toBeGreaterThanOrEqual(10);
expect(manifest.generated.semanticLayer.sourceCount).toBeGreaterThanOrEqual(40);
expect(manifest.generated.knowledge.pageCount).toBeGreaterThanOrEqual(20);
expect(manifest.generated.links.linkCount).toBeGreaterThanOrEqual(10);
const dbStat = await stat(packagedDemoAssetPath('demo.db'));
expect(dbStat.size).toBeGreaterThan(0);
expect(dbStat.size).toBeLessThan(10 * 1024 * 1024);
await expect(access(packagedDemoAssetPath('raw-sources/warehouse/accounts.csv'))).resolves.toBeUndefined();
await expect(access(packagedDemoAssetPath('raw-sources/dbt/schema.yml'))).resolves.toBeUndefined();
await expect(access(packagedDemoAssetPath('raw-sources/bi/revenue_exec.dashboard.lookml'))).resolves.toBeUndefined();
await expect(access(packagedDemoAssetPath('raw-sources/notion/revenue-reporting-policy.md'))).resolves.toBeUndefined();
expect(manifest.generated.semanticLayer.path).toBe('semantic-layer/orbit_demo');
await expect(access(packagedDemoAssetPath('semantic-layer/orbit_demo/accounts.yaml'))).resolves.toBeUndefined();
await expect(access(packagedDemoAssetPath('knowledge/global/arr-contract-first.md'))).resolves.toBeUndefined();
await expect(access(packagedDemoAssetPath('semantic-layer/dbt-main/mart_arr_daily.yaml'))).resolves.toBeUndefined();
await expect(access(packagedDemoAssetPath('semantic-layer/postgres-warehouse/mart_account_activity.yaml'))).resolves.toBeUndefined();
await expect(access(packagedDemoAssetPath('knowledge/global/orbit-company-overview.md'))).resolves.toBeUndefined();
await expect(access(packagedDemoAssetPath('links/provenance.json'))).resolves.toBeUndefined();
await expect(access(packagedDemoAssetPath('reports/seeded-demo-report.json'))).resolves.toBeUndefined();
});

View file

@ -45,14 +45,9 @@ const REQUIRED_SEEDED_ASSET_PATHS = [
'demo.db',
'manifest.json',
DEMO_REPLAY_FILE,
join('raw-sources', 'warehouse', 'accounts.csv'),
join('raw-sources', 'dbt', 'schema.yml'),
join('raw-sources', 'bi', 'revenue_exec.dashboard.lookml'),
join('raw-sources', 'notion', 'revenue-reporting-policy.md'),
join('semantic-layer', 'orbit_demo', 'accounts.yaml'),
join('knowledge', 'global', 'arr-contract-first.md'),
join('links', 'provenance.json'),
join('reports', 'seeded-demo-report.json'),
join('semantic-layer', 'dbt-main', 'mart_arr_daily.yaml'),
join('semantic-layer', 'postgres-warehouse', 'mart_account_activity.yaml'),
join('knowledge', 'global', 'orbit-company-overview.md'),
] as const;
function assetDir(): string {

View file

@ -53,8 +53,8 @@ describe('seeded demo inspect contract', () => {
notion: { label: 'Notion', path: 'raw-sources/notion', pageCount: 8 },
},
generatedOutputs: {
semanticLayer: { path: 'semantic-layer/orbit_demo', manifestSourceCount: 6, fileCount: 6 },
knowledge: { path: 'knowledge/global', manifestPageCount: 10, fileCount: 10 },
semanticLayer: { path: 'semantic-layer', manifestSourceCount: 46, fileCount: 46 },
knowledge: { path: 'knowledge/global', manifestPageCount: 28, fileCount: 28 },
links: { path: 'links/provenance.json', manifestLinkCount: 23, linkCount: 23 },
reports: { primaryPath: 'reports/seeded-demo-report.json', fileCount: 1 },
replays: { primaryPath: 'replays/replay.memory-flow.v1.json', latestPath: 'replays/latest.memory-flow.v1.json' },
@ -83,8 +83,8 @@ describe('seeded demo inspect contract', () => {
expect(output).toContain('dbt: 3 models, 8 source tables');
expect(output).toContain('BI: 5 explores, 2 dashboards');
expect(output).toContain('Notion: 8 pages');
expect(output).toContain('Semantic-layer sources: 6 manifest, 6 files');
expect(output).toContain('Knowledge pages: 10 manifest, 10 files');
expect(output).toContain('Semantic-layer sources: 46 manifest, 46 files');
expect(output).toContain('Knowledge pages: 28 manifest, 28 files');
expect(output).toContain('Evidence links: 23 manifest, 23 links');
expect(output).toContain('Report: reports/seeded-demo-report.json');
expect(output).toContain('Replay: replays/replay.memory-flow.v1.json');

View file

@ -71,12 +71,9 @@ const REQUIRED_SEEDED_PROJECT_PATHS = [
'state.sqlite',
'manifest.json',
join('replays', 'replay.memory-flow.v1.json'),
join('raw-sources', 'warehouse', 'accounts.csv'),
join('raw-sources', 'dbt', 'schema.yml'),
join('raw-sources', 'bi', 'revenue_exec.dashboard.lookml'),
join('raw-sources', 'notion', 'revenue-reporting-policy.md'),
join('semantic-layer', 'orbit_demo', 'accounts.yaml'),
join('knowledge', 'global', 'arr-contract-first.md'),
join('semantic-layer', 'dbt-main', 'mart_arr_daily.yaml'),
join('semantic-layer', 'postgres-warehouse', 'mart_account_activity.yaml'),
join('knowledge', 'global', 'orbit-company-overview.md'),
join('links', 'provenance.json'),
join('reports', 'seeded-demo-report.json'),
] as const;

View file

@ -19,11 +19,9 @@ describe('demo seeded mode', () => {
await expect(access(join(projectDir, 'demo.db'))).resolves.toBeUndefined();
await expect(access(join(projectDir, 'ktx.yaml'))).resolves.toBeUndefined();
await expect(access(join(projectDir, 'manifest.json'))).resolves.toBeUndefined();
await expect(access(join(projectDir, 'semantic-layer/orbit_demo/accounts.yaml'))).resolves.toBeUndefined();
await expect(access(join(projectDir, 'knowledge/global/arr-contract-first.md'))).resolves.toBeUndefined();
await expect(access(join(projectDir, 'raw-sources/dbt/schema.yml'))).resolves.toBeUndefined();
await expect(access(join(projectDir, 'raw-sources/bi/revenue_exec.dashboard.lookml'))).resolves.toBeUndefined();
await expect(access(join(projectDir, 'raw-sources/notion/revenue-reporting-policy.md'))).resolves.toBeUndefined();
await expect(access(join(projectDir, 'semantic-layer/dbt-main/mart_arr_daily.yaml'))).resolves.toBeUndefined();
await expect(access(join(projectDir, 'semantic-layer/postgres-warehouse/mart_account_activity.yaml'))).resolves.toBeUndefined();
await expect(access(join(projectDir, 'knowledge/global/orbit-company-overview.md'))).resolves.toBeUndefined();
await expect(access(join(projectDir, 'links/provenance.json'))).resolves.toBeUndefined();
await expect(access(join(projectDir, 'reports/seeded-demo-report.json'))).resolves.toBeUndefined();
});
@ -88,8 +86,8 @@ describe('demo seeded mode', () => {
it('SL YAML validates correctly', async () => {
await ensureSeededDemoProject({ projectDir, force: false });
const slYaml = await readFile(join(projectDir, 'semantic-layer/orbit_demo/accounts.yaml'), 'utf-8');
expect(slYaml).toContain('name: accounts');
const slYaml = await readFile(join(projectDir, 'semantic-layer/dbt-main/mart_arr_daily.yaml'), 'utf-8');
expect(slYaml).toContain('name: mart_arr_daily');
expect(slYaml).toContain('grain:');
expect(slYaml).toContain('columns:');
expect(slYaml).toContain('measures:');
@ -98,11 +96,11 @@ describe('demo seeded mode', () => {
it('wiki pages have valid frontmatter', async () => {
await ensureSeededDemoProject({ projectDir, force: false });
const wiki = await readFile(join(projectDir, 'knowledge/global/arr-contract-first.md'), 'utf-8');
const wiki = await readFile(join(projectDir, 'knowledge/global/orbit-company-overview.md'), 'utf-8');
expect(wiki).toContain('---');
expect(wiki).toContain('summary:');
expect(wiki).toContain('tags:');
expect(wiki).toContain('sl_refs:');
expect(wiki).toContain('refs:');
expect(wiki).toContain('usage_mode: auto');
});

View file

@ -115,10 +115,10 @@ describe('buildDemoReplayTimeline', () => {
it('produces events for all 4 targets', () => {
expect(connectionIds.size).toBe(4);
expect(connectionIds).toContain('demo-warehouse');
expect(connectionIds).toContain('dbt');
expect(connectionIds).toContain('metabase');
expect(connectionIds).toContain('notion');
expect(connectionIds).toContain('postgres-warehouse');
expect(connectionIds).toContain('dbt-main');
expect(connectionIds).toContain('metabase-main');
expect(connectionIds).toContain('notion-main');
});
it('all targets end as done', () => {

View file

@ -190,43 +190,45 @@ export interface DemoReplayEvent {
export const DEMO_REPLAY_TARGETS = {
primarySources: [
createDemoTarget('demo-warehouse', 'scan', 'postgres'),
createDemoTarget('postgres-warehouse', 'scan', 'postgres'),
],
contextSources: [
createDemoTarget('dbt', 'source-ingest', 'dbt'),
createDemoTarget('metabase', 'source-ingest', 'metabase'),
createDemoTarget('notion', 'source-ingest', 'notion'),
createDemoTarget('dbt-main', 'source-ingest', 'dbt'),
createDemoTarget('metabase-main', 'source-ingest', 'metabase'),
createDemoTarget('notion-main', 'source-ingest', 'notion'),
],
} as const;
export function buildDemoReplayTimeline(): DemoReplayEvent[] {
return [
// demo-warehouse: scan
{ delayMs: 0, connectionId: 'demo-warehouse', status: 'running', detailLine: null, summaryText: null },
{ delayMs: 1200, connectionId: 'demo-warehouse', status: 'running', detailLine: '[50%] Scanning tables...', summaryText: null },
{ delayMs: 2400, connectionId: 'demo-warehouse', status: 'done', detailLine: null, summaryText: '12 tables' },
// dbt
{ delayMs: 2400, connectionId: 'dbt', status: 'running', detailLine: null, summaryText: null },
{ delayMs: 3600, connectionId: 'dbt', status: 'running', detailLine: '[60%] Ingesting models...', summaryText: null },
{ delayMs: 4400, connectionId: 'dbt', status: 'done', detailLine: null, summaryText: '8 models' },
// metabase
{ delayMs: 4400, connectionId: 'metabase', status: 'running', detailLine: null, summaryText: null },
{ delayMs: 5600, connectionId: 'metabase', status: 'done', detailLine: null, summaryText: '5 dashboards' },
// notion
{ delayMs: 5600, connectionId: 'notion', status: 'running', detailLine: null, summaryText: null },
{ delayMs: 6800, connectionId: 'notion', status: 'done', detailLine: null, summaryText: '3 pages' },
// postgres-warehouse: scan
{ delayMs: 0, connectionId: 'postgres-warehouse', status: 'running', detailLine: null, summaryText: null },
{ delayMs: 1200, connectionId: 'postgres-warehouse', status: 'running', detailLine: '[50%] scanning tables...', summaryText: null },
{ delayMs: 2400, connectionId: 'postgres-warehouse', status: 'done', detailLine: null, summaryText: '56 tables scanned' },
// dbt-main
{ delayMs: 2400, connectionId: 'dbt-main', status: 'running', detailLine: null, summaryText: null },
{ delayMs: 3600, connectionId: 'dbt-main', status: 'running', detailLine: '[60%] ingesting models...', summaryText: null },
{ delayMs: 4400, connectionId: 'dbt-main', status: 'done', detailLine: null, summaryText: '34 models ingested' },
// metabase-main
{ delayMs: 4400, connectionId: 'metabase-main', status: 'running', detailLine: null, summaryText: null },
{ delayMs: 5600, connectionId: 'metabase-main', status: 'done', detailLine: null, summaryText: '80 cards ingested' },
// notion-main
{ delayMs: 5600, connectionId: 'notion-main', status: 'running', detailLine: null, summaryText: null },
{ delayMs: 6800, connectionId: 'notion-main', status: 'done', detailLine: null, summaryText: '9 pages ingested' },
];
}
function renderDemoContextCompletionSummary(): string {
const lines = [
'',
'┌ Context build complete',
'│',
'│ All sources have been processed.',
'│',
`${dim('Press Enter to continue, Escape to go back')}`,
'└',
`${cyan('★')} KTX finished building context`,
'',
' KTX created:',
` ${cyan('📊')} 45 semantic layer definitions`,
` ${cyan('📝')} 32 knowledge pages`,
'',
` ${dim('Press Enter to continue, Escape to go back')}`,
'',
];
return lines.join('\n');
}
@ -341,9 +343,9 @@ export async function runDemoTour(
let direction: 'forward' | 'back';
if (step === 'databases') {
direction = await renderDemoCard('Database connection', ['PostgreSQL (demo warehouse)'], io, undefined, waitNav);
direction = await renderDemoCard('Database connection', ['PostgreSQL — Orbit Analytics (56 tables, 2 schemas)'], io, undefined, waitNav);
} else if (step === 'sources') {
direction = await renderDemoCard('Context sources', ['dbt', 'Metabase', 'Notion'], io, undefined, waitNav);
direction = await renderDemoCard('Context sources', ['dbt — 34 transformation models', 'Metabase — 80 dashboard cards', 'Notion — 9 knowledge pages'], io, undefined, waitNav);
} else if (step === 'context') {
io.stdout.write(renderDemoBanner() + '\n\n');
if (deps.skipReplayAnimation) {