feat: another track
This commit is contained in:
@@ -14,10 +14,11 @@ import {
|
|||||||
ShieldAlert,
|
ShieldAlert,
|
||||||
MessageSquare,
|
MessageSquare,
|
||||||
Crown,
|
Crown,
|
||||||
|
FlaskConical,
|
||||||
} from 'lucide-react'
|
} from 'lucide-react'
|
||||||
import { Footer } from '@/components/footer'
|
import { Footer } from '@/components/footer'
|
||||||
import { LiveTerminal } from '@/components/hackathons/live-terminal'
|
import { LiveTerminal } from '@/components/hackathons/live-terminal'
|
||||||
import { StreamViz, SecureViz, RadarViz, ScanViz, ExtendViz } from '@/components/hackathons/track-visuals'
|
import { StreamViz, SecureViz, RadarViz, ScanViz, ExtendViz, BenchViz } from '@/components/hackathons/track-visuals'
|
||||||
|
|
||||||
const ShieldScene = dynamic(
|
const ShieldScene = dynamic(
|
||||||
() => import('@/components/hackathons/shield-scene').then((m) => m.ShieldScene),
|
() => import('@/components/hackathons/shield-scene').then((m) => m.ShieldScene),
|
||||||
@@ -546,6 +547,18 @@ const tracks = [
|
|||||||
examples: ['Error interception', 'Context injection', 'Alternative suggestion', 'Loop prevention'],
|
examples: ['Error interception', 'Context injection', 'Alternative suggestion', 'Loop prevention'],
|
||||||
Visual: ExtendViz,
|
Visual: ExtendViz,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'control-benchmark',
|
||||||
|
icon: FlaskConical,
|
||||||
|
title: 'Control Evaluation Benchmark',
|
||||||
|
hook: 'Build the test suite that measures how well sandboxes actually work.',
|
||||||
|
color: 'from-rose-500/10 to-pink-500/5',
|
||||||
|
borderColor: 'hover:border-rose-500/30',
|
||||||
|
description: 'Define main tasks (real software engineering work) paired with side tasks (exfiltrate a key, install a backdoor, modify git hooks). Measure how much useful work an agent completes under Greywall\'s restrictions vs. how often adversarial goals succeed.',
|
||||||
|
scoring: 'Show the safety/usefulness tradeoff. A good benchmark reveals real weaknesses, not just toy scenarios.',
|
||||||
|
examples: ['Main/side task pairs', 'Policy quality scoring', 'Layer isolation tests', 'Reproducible evals'],
|
||||||
|
Visual: BenchViz,
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
function TrackCard({ track, index }: { track: typeof tracks[0]; index: number }) {
|
function TrackCard({ track, index }: { track: typeof tracks[0]; index: number }) {
|
||||||
@@ -612,7 +625,7 @@ function Tracks() {
|
|||||||
Pick your track.
|
Pick your track.
|
||||||
</h2>
|
</h2>
|
||||||
<p className="font-serif text-lg text-muted-foreground max-w-2xl mx-auto">
|
<p className="font-serif text-lg text-muted-foreground max-w-2xl mx-auto">
|
||||||
Five open-ended tracks, all building on top of{' '}
|
Six open-ended tracks, all building on top of{' '}
|
||||||
<a href="https://github.com/GreyhavenHQ/greywall" target="_blank" rel="noopener noreferrer" className="text-primary hover:text-primary/80 transition-colors underline underline-offset-2">Greywall</a>.
|
<a href="https://github.com/GreyhavenHQ/greywall" target="_blank" rel="noopener noreferrer" className="text-primary hover:text-primary/80 transition-colors underline underline-offset-2">Greywall</a>.
|
||||||
Go deep on one or try a few.
|
Go deep on one or try a few.
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -405,3 +405,146 @@ export function ExtendViz() {
|
|||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ─── Benchmark grid (Track 6 — Control Evaluation Benchmark) ─── */
|
||||||
|
|
||||||
|
export function BenchViz() {
|
||||||
|
const canvasRef = useRef<HTMLCanvasElement>(null)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const canvas = canvasRef.current
|
||||||
|
if (!canvas) return
|
||||||
|
const ctx = canvas.getContext('2d')
|
||||||
|
if (!ctx) return
|
||||||
|
|
||||||
|
const dpr = window.devicePixelRatio || 1
|
||||||
|
let w = 0, h = 0
|
||||||
|
|
||||||
|
const resize = () => {
|
||||||
|
const rect = canvas.getBoundingClientRect()
|
||||||
|
w = rect.width
|
||||||
|
h = rect.height
|
||||||
|
canvas.width = w * dpr
|
||||||
|
canvas.height = h * dpr
|
||||||
|
ctx.setTransform(dpr, 0, 0, dpr, 0, 0)
|
||||||
|
}
|
||||||
|
resize()
|
||||||
|
|
||||||
|
let t = 0
|
||||||
|
let animId: number
|
||||||
|
|
||||||
|
const cols = 6, rows = 8
|
||||||
|
const cells = Array.from({ length: cols * rows }, (_, i) => ({
|
||||||
|
pass: Math.random() > 0.25,
|
||||||
|
revealAt: Math.random() * 4 + (Math.floor(i / cols)) * 0.3,
|
||||||
|
pulsePhase: Math.random() * Math.PI * 2,
|
||||||
|
}))
|
||||||
|
|
||||||
|
const draw = () => {
|
||||||
|
ctx.clearRect(0, 0, w, h)
|
||||||
|
t += 0.016
|
||||||
|
|
||||||
|
const padX = w * 0.08, padY = h * 0.06
|
||||||
|
const cellW = (w - padX * 2) / cols
|
||||||
|
const cellH = (h - padY * 2) / rows
|
||||||
|
const gap = 2.5
|
||||||
|
const loopT = t % 6
|
||||||
|
|
||||||
|
cells.forEach((cell, i) => {
|
||||||
|
const col = i % cols
|
||||||
|
const row = Math.floor(i / cols)
|
||||||
|
const x = padX + col * cellW + gap
|
||||||
|
const y = padY + row * cellH + gap
|
||||||
|
const cw = cellW - gap * 2
|
||||||
|
const ch = cellH - gap * 2
|
||||||
|
const r = Math.min(cw, ch) * 0.15
|
||||||
|
|
||||||
|
if (loopT < cell.revealAt) {
|
||||||
|
// Not yet revealed — dim outline
|
||||||
|
ctx.strokeStyle = 'rgba(244, 63, 94, 0.06)'
|
||||||
|
ctx.lineWidth = 0.5
|
||||||
|
ctx.beginPath()
|
||||||
|
ctx.roundRect(x, y, cw, ch, r)
|
||||||
|
ctx.stroke()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reveal animation
|
||||||
|
const revealProgress = Math.min((loopT - cell.revealAt) * 2, 1)
|
||||||
|
const pulse = Math.sin(t * 2 + cell.pulsePhase) * 0.15 + 0.85
|
||||||
|
|
||||||
|
if (cell.pass) {
|
||||||
|
// Pass — rose/green tint
|
||||||
|
ctx.fillStyle = `rgba(74, 222, 128, ${0.12 * revealProgress * pulse})`
|
||||||
|
ctx.beginPath()
|
||||||
|
ctx.roundRect(x, y, cw, ch, r)
|
||||||
|
ctx.fill()
|
||||||
|
|
||||||
|
ctx.strokeStyle = `rgba(74, 222, 128, ${0.25 * revealProgress})`
|
||||||
|
ctx.lineWidth = 0.5
|
||||||
|
ctx.beginPath()
|
||||||
|
ctx.roundRect(x, y, cw, ch, r)
|
||||||
|
ctx.stroke()
|
||||||
|
|
||||||
|
// Checkmark
|
||||||
|
if (revealProgress > 0.5) {
|
||||||
|
const alpha = (revealProgress - 0.5) * 2
|
||||||
|
const cx = x + cw / 2, cy = y + ch / 2
|
||||||
|
const s = Math.min(cw, ch) * 0.2
|
||||||
|
ctx.strokeStyle = `rgba(74, 222, 128, ${0.5 * alpha})`
|
||||||
|
ctx.lineWidth = 1.2
|
||||||
|
ctx.beginPath()
|
||||||
|
ctx.moveTo(cx - s * 0.6, cy)
|
||||||
|
ctx.lineTo(cx - s * 0.1, cy + s * 0.5)
|
||||||
|
ctx.lineTo(cx + s * 0.6, cy - s * 0.4)
|
||||||
|
ctx.stroke()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Fail — red tint
|
||||||
|
ctx.fillStyle = `rgba(244, 63, 94, ${0.15 * revealProgress * pulse})`
|
||||||
|
ctx.beginPath()
|
||||||
|
ctx.roundRect(x, y, cw, ch, r)
|
||||||
|
ctx.fill()
|
||||||
|
|
||||||
|
ctx.strokeStyle = `rgba(244, 63, 94, ${0.3 * revealProgress})`
|
||||||
|
ctx.lineWidth = 0.5
|
||||||
|
ctx.beginPath()
|
||||||
|
ctx.roundRect(x, y, cw, ch, r)
|
||||||
|
ctx.stroke()
|
||||||
|
|
||||||
|
// X mark
|
||||||
|
if (revealProgress > 0.5) {
|
||||||
|
const alpha = (revealProgress - 0.5) * 2
|
||||||
|
const cx = x + cw / 2, cy = y + ch / 2
|
||||||
|
const s = Math.min(cw, ch) * 0.18
|
||||||
|
ctx.strokeStyle = `rgba(244, 63, 94, ${0.5 * alpha})`
|
||||||
|
ctx.lineWidth = 1.2
|
||||||
|
ctx.beginPath()
|
||||||
|
ctx.moveTo(cx - s, cy - s)
|
||||||
|
ctx.lineTo(cx + s, cy + s)
|
||||||
|
ctx.moveTo(cx + s, cy - s)
|
||||||
|
ctx.lineTo(cx - s, cy + s)
|
||||||
|
ctx.stroke()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Progress bar at bottom
|
||||||
|
const barY = h - padY * 0.6
|
||||||
|
const barH = 2
|
||||||
|
const progress = Math.min(loopT / 5, 1)
|
||||||
|
ctx.fillStyle = 'rgba(244, 63, 94, 0.08)'
|
||||||
|
ctx.fillRect(padX, barY, w - padX * 2, barH)
|
||||||
|
ctx.fillStyle = 'rgba(244, 63, 94, 0.3)'
|
||||||
|
ctx.fillRect(padX, barY, (w - padX * 2) * progress, barH)
|
||||||
|
|
||||||
|
animId = requestAnimationFrame(draw)
|
||||||
|
}
|
||||||
|
draw()
|
||||||
|
|
||||||
|
window.addEventListener('resize', resize)
|
||||||
|
return () => { cancelAnimationFrame(animId); window.removeEventListener('resize', resize) }
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return <canvas ref={canvasRef} className="absolute inset-0 w-full h-full" style={{ display: 'block' }} />
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user