From c022e47c3d9fb1c4078fad860faa006857dd6057 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 16 Jul 2026 03:06:49 +0000 Subject: [PATCH 01/10] fix(experiments): correct 404 detail links on redlines and ndeltas index pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The index pages linked to top-level /redlines/{configId} and /ndeltas/{modelId}, which don't exist — the detail routes live under /experiments/. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_017bEpzahprA9rLt1wxxTKgy --- src/app/experiments/ndeltas/page.tsx | 2 +- src/app/experiments/redlines/page.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/experiments/ndeltas/page.tsx b/src/app/experiments/ndeltas/page.tsx index d9e509f2..edfa7292 100644 --- a/src/app/experiments/ndeltas/page.tsx +++ b/src/app/experiments/ndeltas/page.tsx @@ -49,7 +49,7 @@ export default async function NDeltasIndexPage() { {m.medianDelta !== null && m.medianDelta !== undefined ? m.medianDelta.toFixed(3) : '—'} {m.totalEntries} {new Date(m.generatedAt).toLocaleString()} - View details + View details ))} diff --git a/src/app/experiments/redlines/page.tsx b/src/app/experiments/redlines/page.tsx index cae9f854..254f21e8 100644 --- a/src/app/experiments/redlines/page.tsx +++ b/src/app/experiments/redlines/page.tsx @@ -85,7 +85,7 @@ export default async function RedlinesIndexPage() {
{it.configId} From 7ab7fbe5ded5988ef99dc3c9f72c48ca7f80946b Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 16 Jul 2026 03:07:56 +0000 Subject: [PATCH 02/10] =?UTF-8?q?chore:=20remove=20dead=20code=20=E2=80=94?= =?UTF-8?q?=20/v2=20prototype,=20orphaned=20components,=20archived=20pilot?= =?UTF-8?q?=20v1,=20dangling=20scripts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - src/app/v2: duplicate homepage prototype, no inbound links anywhere - NavBarV2: imported only by the deleted v2 layout - SearchAutocomplete: zero importers - pilot/india-multilingual/_archive_v1: explicitly archived, unreferenced - package.json scripts test:personality / compare:personality / test:preference / test:self-preference pointed at CLI files that no longer exist Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_017bEpzahprA9rLt1wxxTKgy --- package.json | 4 - src/app/components/NavBarV2.tsx | 488 ---------------- src/app/components/SearchAutocomplete.tsx | 351 ------------ src/app/pilot/india-multilingual/README.md | 1 - .../india-multilingual/_archive_v1/PLAN.md | 502 ----------------- .../_archive_v1/PilotClient.tsx | 197 ------- .../_archive_v1/components/BreakdownTable.tsx | 133 ----- .../components/DataQualitySection.tsx | 184 ------ .../components/DisagreementExplorer.tsx | 224 -------- .../components/ExemplarWorkers.tsx | 227 -------- .../_archive_v1/components/FeaturedCases.tsx | 531 ------------------ .../_archive_v1/components/FilterBar.tsx | 116 ---- .../components/FindingsSection.tsx | 126 ----- .../components/HeadToHeadResults.tsx | 180 ------ .../_archive_v1/components/HeroSection.tsx | 62 -- .../components/HumanLLMComparison.tsx | 127 ----- .../components/ImplicationsSection.tsx | 112 ---- .../components/MethodologySection.tsx | 125 ----- .../components/ModelPerformanceSection.tsx | 240 -------- .../_archive_v1/components/PilotFooter.tsx | 48 -- .../_archive_v1/components/PromptDetails.tsx | 171 ------ .../_archive_v1/components/PromptExplorer.tsx | 213 ------- .../_archive_v1/components/PromptRow.tsx | 135 ----- .../india-multilingual/_archive_v1/page.tsx | 63 --- src/app/v2/layout.tsx | 25 - src/app/v2/page.tsx | 208 ------- 26 files changed, 4793 deletions(-) delete mode 100644 src/app/components/NavBarV2.tsx delete mode 100644 src/app/components/SearchAutocomplete.tsx delete mode 100644 src/app/pilot/india-multilingual/_archive_v1/PLAN.md delete mode 100644 src/app/pilot/india-multilingual/_archive_v1/PilotClient.tsx delete mode 100644 src/app/pilot/india-multilingual/_archive_v1/components/BreakdownTable.tsx delete mode 100644 src/app/pilot/india-multilingual/_archive_v1/components/DataQualitySection.tsx delete mode 100644 src/app/pilot/india-multilingual/_archive_v1/components/DisagreementExplorer.tsx delete mode 100644 src/app/pilot/india-multilingual/_archive_v1/components/ExemplarWorkers.tsx delete mode 100644 src/app/pilot/india-multilingual/_archive_v1/components/FeaturedCases.tsx delete mode 100644 src/app/pilot/india-multilingual/_archive_v1/components/FilterBar.tsx delete mode 100644 src/app/pilot/india-multilingual/_archive_v1/components/FindingsSection.tsx delete mode 100644 src/app/pilot/india-multilingual/_archive_v1/components/HeadToHeadResults.tsx delete mode 100644 src/app/pilot/india-multilingual/_archive_v1/components/HeroSection.tsx delete mode 100644 src/app/pilot/india-multilingual/_archive_v1/components/HumanLLMComparison.tsx delete mode 100644 src/app/pilot/india-multilingual/_archive_v1/components/ImplicationsSection.tsx delete mode 100644 src/app/pilot/india-multilingual/_archive_v1/components/MethodologySection.tsx delete mode 100644 src/app/pilot/india-multilingual/_archive_v1/components/ModelPerformanceSection.tsx delete mode 100644 src/app/pilot/india-multilingual/_archive_v1/components/PilotFooter.tsx delete mode 100644 src/app/pilot/india-multilingual/_archive_v1/components/PromptDetails.tsx delete mode 100644 src/app/pilot/india-multilingual/_archive_v1/components/PromptExplorer.tsx delete mode 100644 src/app/pilot/india-multilingual/_archive_v1/components/PromptRow.tsx delete mode 100644 src/app/pilot/india-multilingual/_archive_v1/page.tsx delete mode 100644 src/app/v2/layout.tsx delete mode 100644 src/app/v2/page.tsx diff --git a/package.json b/package.json index e8553287..6eaead1a 100644 --- a/package.json +++ b/package.json @@ -25,10 +25,6 @@ "test:e2e:ui": "playwright test --ui", "test:e2e:report": "playwright show-report", "pr:screenshots": "node scripts/pr-screenshots.mjs", - "test:personality": "tsx src/cli/personality-test.ts", - "compare:personality": "tsx src/cli/compare-personality.ts", - "test:preference": "tsx src/cli/preference-test.ts", - "test:self-preference": "tsx src/cli/self-preference-test.ts", "cli": "tsx --no-cache -r ./src/cli/env-loader.js src/cli/index.ts", "cli:generate-pain-points": "pnpm cli generate-pain-points", "cli:annotate-pain-points": "pnpm cli annotate-pain-points", diff --git a/src/app/components/NavBarV2.tsx b/src/app/components/NavBarV2.tsx deleted file mode 100644 index a0e48e1d..00000000 --- a/src/app/components/NavBarV2.tsx +++ /dev/null @@ -1,488 +0,0 @@ -'use client'; - -import React, { useState, useEffect, useRef, useCallback } from 'react'; -import Link from 'next/link'; -import { useRouter } from 'next/navigation'; -import CIPLogo from '@/components/icons/CIPLogo'; -import Icon from '@/components/ui/icon'; -import { Input } from '@/components/ui/input'; -import { Button } from '@/components/ui/button'; -import Fuse from 'fuse.js'; -import { AutocompleteEntry } from '@/cli/types/cli_types'; -import { cn } from '@/lib/utils'; - -const NAV_LINKS = [ - { href: '/', label: 'Home' }, - { href: '#', label: 'Our Methodology', disabled: true }, - { href: '#', label: 'About Weval', disabled: true }, -]; - -const ACTION_LINKS = [ - { href: '#', label: 'Suggest Eval', disabled: true }, - { href: '/sandbox', label: 'Create Eval', disabled: false, primary: true }, -]; - -export function NavBarV2() { - const router = useRouter(); - const [mobileMenuOpen, setMobileMenuOpen] = useState(false); - const [searchFocused, setSearchFocused] = useState(false); - const [query, setQuery] = useState(''); - const [suggestions, setSuggestions] = useState([]); - const [selectedIndex, setSelectedIndex] = useState(-1); - const [fuse, setFuse] = useState | null>(null); - const [isLoading, setIsLoading] = useState(true); - const inputRef = useRef(null); - const containerRef = useRef(null); - const listRef = useRef(null); - - // Load autocomplete index - useEffect(() => { - async function loadIndex() { - try { - const response = await fetch('/api/autocomplete'); - if (response.ok) { - const data = await response.json(); - setFuse(new Fuse(data, { - keys: [ - { name: 'title', weight: 2 }, - { name: 'keywords', weight: 1.5 }, - { name: 'tags', weight: 1.2 }, - { name: 'snippet', weight: 0.8 }, - { name: 'domain', weight: 1 }, - ], - threshold: 0.4, - includeScore: true, - minMatchCharLength: 2, - ignoreLocation: true, - })); - } - } catch (error) { - console.error('Failed to load autocomplete index:', error); - } finally { - setIsLoading(false); - } - } - loadIndex(); - }, []); - - // Update suggestions - useEffect(() => { - if (!fuse || query.length < 2) { - setSuggestions([]); - return; - } - const results = fuse.search(query); - setSuggestions(results.slice(0, 5).map(r => r.item)); - setSelectedIndex(-1); - }, [query, fuse]); - - // Close on click outside - useEffect(() => { - function handleClickOutside(event: MouseEvent) { - if (containerRef.current && !containerRef.current.contains(event.target as Node)) { - setSearchFocused(false); - } - } - document.addEventListener('mousedown', handleClickOutside); - return () => document.removeEventListener('mousedown', handleClickOutside); - }, []); - - // Escape key handling - useEffect(() => { - function handleEscape(event: KeyboardEvent) { - if (event.key === 'Escape') { - setSearchFocused(false); - setMobileMenuOpen(false); - inputRef.current?.blur(); - } - } - document.addEventListener('keydown', handleEscape); - return () => document.removeEventListener('keydown', handleEscape); - }, []); - - // Scroll selected into view - useEffect(() => { - if (selectedIndex >= 0 && listRef.current) { - const el = listRef.current.children[selectedIndex] as HTMLElement; - el?.scrollIntoView({ block: 'nearest' }); - } - }, [selectedIndex]); - - const handleSelect = useCallback((entry: AutocompleteEntry) => { - setQuery(''); - setSearchFocused(false); - router.push(`/analysis/${entry.configId}`); - }, [router]); - - const handleKeyDown = (e: React.KeyboardEvent) => { - const showDropdown = searchFocused && (suggestions.length > 0 || query.length > 2); - - if (!showDropdown) { - if (e.key === 'Enter' && query.length > 2) { - router.push(`/all?q=${encodeURIComponent(query)}`); - setSearchFocused(false); - } - return; - } - - const totalOptions = suggestions.length + (query.length > 2 ? 1 : 0); - - switch (e.key) { - case 'ArrowDown': - e.preventDefault(); - setSelectedIndex(prev => prev < totalOptions - 1 ? prev + 1 : prev); - break; - case 'ArrowUp': - e.preventDefault(); - setSelectedIndex(prev => prev > 0 ? prev - 1 : -1); - break; - case 'Enter': - e.preventDefault(); - if (selectedIndex >= 0 && selectedIndex < suggestions.length) { - handleSelect(suggestions[selectedIndex]); - } else if (query.length > 2) { - router.push(`/all?q=${encodeURIComponent(query)}`); - setSearchFocused(false); - } - break; - } - }; - - const showDropdown = searchFocused && (suggestions.length > 0 || (query.length > 2 && !isLoading)); - const listboxId = 'navbar-search-listbox'; - const getOptionId = (idx: number) => `navbar-search-option-${idx}`; - - return ( - <> - {/* Mobile search overlay */} - {searchFocused && ( -
-
-
- - Search evaluations -
-
-
- -
- = 0 ? getOptionId(selectedIndex) : undefined} - placeholder="Search..." - value={query} - onChange={(e) => setQuery(e.target.value)} - onKeyDown={handleKeyDown} - className="w-full pl-11 pr-4 py-3 text-base rounded-lg bg-white dark:bg-card" - autoFocus - autoComplete="off" - /> - {showDropdown && ( -
-
    - {suggestions.map((entry, idx) => ( -
  • - -
  • - ))} - {query.length > 2 && ( -
  • - -
  • - )} -
-
- )} -
-
-
- )} - - {/* Mobile menu overlay */} - {mobileMenuOpen && ( -
-
-
- setMobileMenuOpen(false)}> - - - w - eval - - - -
- -
-
- {ACTION_LINKS.map(link => ( - !link.disabled && setMobileMenuOpen(false)} - className={cn( - "block px-4 py-3 rounded-lg text-center", - link.disabled - ? "text-muted-foreground bg-muted/50 cursor-not-allowed" - : link.primary - ? "bg-primary text-primary-foreground hover:bg-primary/90" - : "bg-muted hover:bg-muted/80" - )} - aria-disabled={link.disabled} - > - {link.label} - - ))} -
-
-
- )} - - {/* Main navbar */} -
-
-
- {/* Left: Logo + Nav Links */} -
- - - - w - eval - - - -
- - {/* Center: Search (desktop) */} -
-
-
- {isLoading ? ( - - ) : ( - - )} -
- = 0 ? getOptionId(selectedIndex) : undefined} - placeholder="Search evaluations..." - value={query} - onChange={(e) => { - setQuery(e.target.value); - setSearchFocused(true); - }} - onFocus={() => setSearchFocused(true)} - onKeyDown={handleKeyDown} - className="w-full pl-9 pr-4 py-2 text-sm rounded-lg bg-muted/50 border-transparent focus:bg-white dark:focus:bg-card focus:border-border" - disabled={isLoading} - autoComplete="off" - /> -
- {showDropdown && ( -
-
    - {suggestions.length > 0 ? ( - suggestions.map((entry, idx) => ( -
  • - -
  • - )) - ) : query.length > 2 ? ( -
  • - No matching evaluations -
  • - ) : null} - {query.length > 2 && ( -
  • - -
  • - )} -
-
- )} -
- - {/* Right: Action buttons (desktop) + Mobile controls */} -
- {/* Mobile search button */} - - - {/* Desktop action buttons */} -
- {ACTION_LINKS.map(link => ( - link.disabled ? ( - - ) : ( - - ) - ))} -
- - {/* Mobile menu button */} - -
-
-
-
- - ); -} diff --git a/src/app/components/SearchAutocomplete.tsx b/src/app/components/SearchAutocomplete.tsx deleted file mode 100644 index 7ee0542c..00000000 --- a/src/app/components/SearchAutocomplete.tsx +++ /dev/null @@ -1,351 +0,0 @@ -'use client'; - -import React, { useState, useEffect, useRef, useCallback } from 'react'; -import { useRouter } from 'next/navigation'; -import { Input } from '@/components/ui/input'; -import Icon from '@/components/ui/icon'; -import Fuse from 'fuse.js'; -import { AutocompleteEntry } from '@/cli/types/cli_types'; - -interface SearchAutocompleteProps { - placeholder?: string; - className?: string; -} - -export function SearchAutocomplete({ - placeholder = 'Search evaluations...', - className = '', -}: SearchAutocompleteProps) { - const router = useRouter(); - const [query, setQuery] = useState(''); - const [isOpen, setIsOpen] = useState(false); - const [isFocused, setIsFocused] = useState(false); - const [suggestions, setSuggestions] = useState([]); - const [selectedIndex, setSelectedIndex] = useState(-1); - const [fuse, setFuse] = useState | null>(null); - const [isLoading, setIsLoading] = useState(true); - const inputRef = useRef(null); - const containerRef = useRef(null); - const listRef = useRef(null); - - // Load the autocomplete index on mount - useEffect(() => { - async function loadIndex() { - try { - const response = await fetch('/api/autocomplete'); - if (response.ok) { - const data = await response.json(); - setFuse(new Fuse(data, { - keys: [ - { name: 'title', weight: 2 }, - { name: 'keywords', weight: 1.5 }, - { name: 'tags', weight: 1.2 }, - { name: 'snippet', weight: 0.8 }, - { name: 'domain', weight: 1 }, - { name: 'topModel', weight: 0.5 }, - ], - threshold: 0.4, - includeScore: true, - minMatchCharLength: 2, - ignoreLocation: true, - })); - } - } catch (error) { - console.error('Failed to load autocomplete index:', error); - } finally { - setIsLoading(false); - } - } - loadIndex(); - }, []); - - // Update suggestions when query changes - useEffect(() => { - if (!fuse || query.length < 2) { - setSuggestions([]); - return; - } - - const results = fuse.search(query); - setSuggestions(results.slice(0, 6).map(r => r.item)); - setSelectedIndex(-1); - }, [query, fuse]); - - // Close dropdown when clicking outside - useEffect(() => { - function handleClickOutside(event: MouseEvent) { - if (containerRef.current && !containerRef.current.contains(event.target as Node)) { - setIsOpen(false); - setIsFocused(false); - } - } - document.addEventListener('mousedown', handleClickOutside); - return () => document.removeEventListener('mousedown', handleClickOutside); - }, []); - - // Handle escape key to close mobile fullscreen - useEffect(() => { - function handleEscape(event: KeyboardEvent) { - if (event.key === 'Escape' && isFocused) { - setIsOpen(false); - setIsFocused(false); - inputRef.current?.blur(); - } - } - document.addEventListener('keydown', handleEscape); - return () => document.removeEventListener('keydown', handleEscape); - }, [isFocused]); - - // Scroll selected item into view - useEffect(() => { - if (selectedIndex >= 0 && listRef.current) { - const selectedElement = listRef.current.children[selectedIndex] as HTMLElement; - selectedElement?.scrollIntoView({ block: 'nearest' }); - } - }, [selectedIndex]); - - const handleSelect = useCallback((entry: AutocompleteEntry) => { - setQuery(''); - setIsOpen(false); - setIsFocused(false); - router.push(`/analysis/${entry.configId}`); - }, [router]); - - const handleKeyDown = (e: React.KeyboardEvent) => { - if (!isOpen || suggestions.length === 0) { - if (e.key === 'Enter' && query.length > 2) { - router.push(`/all?q=${encodeURIComponent(query)}`); - setIsOpen(false); - setIsFocused(false); - } - return; - } - - switch (e.key) { - case 'ArrowDown': - e.preventDefault(); - setSelectedIndex(prev => - prev < suggestions.length ? prev + 1 : prev - ); - break; - case 'ArrowUp': - e.preventDefault(); - setSelectedIndex(prev => prev > 0 ? prev - 1 : -1); - break; - case 'Enter': - e.preventDefault(); - if (selectedIndex >= 0 && selectedIndex < suggestions.length) { - handleSelect(suggestions[selectedIndex]); - } else if (selectedIndex === suggestions.length && query.length > 2) { - // "Search all" option selected - router.push(`/all?q=${encodeURIComponent(query)}`); - setIsOpen(false); - setIsFocused(false); - } else if (query.length > 2) { - router.push(`/all?q=${encodeURIComponent(query)}`); - setIsOpen(false); - setIsFocused(false); - } - break; - case 'Escape': - e.preventDefault(); - setIsOpen(false); - setIsFocused(false); - inputRef.current?.blur(); - break; - } - }; - - const handleFocus = () => { - setIsOpen(true); - setIsFocused(true); - }; - - const handleClose = () => { - setIsOpen(false); - setIsFocused(false); - setQuery(''); - inputRef.current?.blur(); - }; - - const showDropdown = isOpen && (suggestions.length > 0 || (query.length > 2 && !isLoading)); - - // Generate unique IDs for accessibility - const listboxId = 'search-autocomplete-listbox'; - const getOptionId = (index: number) => `search-option-${index}`; - - return ( - <> - {/* Mobile fullscreen overlay */} - {isFocused && ( -