mirror of
https://github.com/garrytan/gstack.git
synced 2026-05-02 03:35:09 +02:00
76803d789a
Adds comprehensive eval infrastructure: - Tier 1 (free): 13 new static tests — cross-skill path consistency, QA structure validation, greptile format, planted-bug fixture validation - Tier 2 (Agent SDK E2E): /qa quick, /review with pre-built git repo, 3 planted-bug outcome evals (static, SPA, checkout — each with 5 bugs) - Tier 3 (LLM judge): QA workflow quality, health rubric clarity, cross-skill consistency, baseline score pinning New fixtures: 3 HTML pages with 15 total planted bugs, ground truth JSON, review-eval-vuln.rb, eval-baselines.json. Shared llm-judge.ts helper (DRY). Unified EVALS=1 flag replaces SKILL_E2E + ANTHROPIC_API_KEY checks. `bun run test:evals` runs everything that costs money (~$4/run). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
99 lines
3.2 KiB
HTML
99 lines
3.2 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<title>QA Eval — SPA Store</title>
|
|
<style>
|
|
body { font-family: sans-serif; padding: 20px; margin: 0; }
|
|
nav { background: #333; padding: 10px 20px; }
|
|
nav a { color: white; margin-right: 15px; text-decoration: none; cursor: pointer; }
|
|
nav a:hover { text-decoration: underline; }
|
|
#app { padding: 20px; }
|
|
.product { border: 1px solid #ddd; padding: 10px; margin: 10px 0; border-radius: 4px; }
|
|
.product button { padding: 6px 12px; background: #0066cc; color: white; border: none; cursor: pointer; }
|
|
.cart-count { background: #cc0000; color: white; padding: 2px 8px; border-radius: 10px; font-size: 12px; }
|
|
.error { color: red; padding: 10px; }
|
|
.loading { color: #666; padding: 10px; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<nav>
|
|
<a href="#/home">Home</a>
|
|
<a href="#/prodcts">Products</a> <!-- BUG 1: broken route — typo "prodcts" instead of "products" -->
|
|
<a href="#/contact">Contact</a>
|
|
<span class="cart-count" id="cart-count">0</span>
|
|
</nav>
|
|
|
|
<div id="app">
|
|
<p>Welcome to SPA Store. Use the navigation above.</p>
|
|
</div>
|
|
|
|
<script>
|
|
let cartCount = 0;
|
|
|
|
// BUG 2: cart count never resets on route change — stale state
|
|
function addToCart() {
|
|
cartCount++;
|
|
document.getElementById('cart-count').textContent = cartCount;
|
|
}
|
|
|
|
function renderHome() {
|
|
document.getElementById('app').innerHTML = `
|
|
<h1>Welcome to SPA Store</h1>
|
|
<p>Browse our products using the navigation above.</p>
|
|
`;
|
|
}
|
|
|
|
function renderProducts() {
|
|
document.getElementById('app').innerHTML = '<p class="loading">Loading products...</p>';
|
|
|
|
// BUG 3: async race — shows data briefly, then shows error
|
|
setTimeout(() => {
|
|
document.getElementById('app').innerHTML = `
|
|
<h1>Products</h1>
|
|
<div class="product">
|
|
<h3>Widget A</h3>
|
|
<p>$29.99</p>
|
|
<button onclick="addToCart()">Add to Cart</button>
|
|
</div>
|
|
<div class="product">
|
|
<h3>Widget B</h3>
|
|
<p>$49.99</p>
|
|
<button onclick="addToCart()">Add to Cart</button>
|
|
</div>
|
|
`;
|
|
}, 300);
|
|
|
|
setTimeout(() => {
|
|
document.getElementById('app').innerHTML = '<p class="error">Error: Failed to fetch products from API</p>';
|
|
}, 1000);
|
|
}
|
|
|
|
function renderContact() {
|
|
document.getElementById('app').innerHTML = `
|
|
<h1>Contact Us</h1>
|
|
<p>Email: support@spastore.example.com</p>
|
|
`;
|
|
}
|
|
|
|
// BUG 4: nav links have no aria-current attribute on active route
|
|
function router() {
|
|
const hash = window.location.hash || '#/home';
|
|
switch (hash) {
|
|
case '#/home': renderHome(); break;
|
|
case '#/products': renderProducts(); break;
|
|
case '#/contact': renderContact(); break;
|
|
default:
|
|
document.getElementById('app').innerHTML = '<p>Page not found</p>';
|
|
}
|
|
|
|
// BUG 5: console.warn on every route change — simulates listener leak
|
|
console.warn('Possible memory leak detected: 11 event listeners added to window');
|
|
}
|
|
|
|
window.addEventListener('hashchange', router);
|
|
router();
|
|
</script>
|
|
</body>
|
|
</html>
|