Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions diagnostic/build-94e0fb08.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
{
"generated_at": "2026-06-19T07:13:02.534993+00:00",
"commit": "94e0fb08",
"diagnostic_logd": "diagnostic/build-94e0fb08.logd",
"diagnostic_logd_error": null,
"message_blocker": null,
"chunked": false,
"chunk_size_bytes": null,
"password": "553deb0a337969a67bea",
"decrypt_command": "encryptly unpack diagnostic/build-94e0fb08.logd <outdir> --password 553deb0a337969a67bea",
"total_modules": 10,
"passed": 3,
"failed": 7,
"modules": [
{
"name": "backend",
"status": "FAIL",
"elapsed_seconds": 0,
"artifact": null,
"output": "Command not found: [Errno 2] No such file or directory: 'cargo'"
},
{
"name": "frontend",
"status": "PASS",
"elapsed_seconds": 1.605,
"artifact": "/private/tmp/hustlebot-bounties/TentOfTrials-therapy/frontend/dist",
"output": "> tent-frontend@0.0.0 build\n> tsc -b && vite build\n\nvite v6.4.3 building for production...\ntransforming...\n\u2713 122 modules transformed.\nrendering chunks...\ncomputing gzip size...\ndist/index.html 0.62 kB \u2502 gzip: 0.35 kB\ndist/assets/state-BkjSKDbY.js 8.91 kB \u2502 gzip: 3.55 kB \u2502 map: 57.15 kB\ndist/assets/vendor-CREcWLHI.js 48.93 kB \u2502 gzip: 17.22 kB \u2502 map: 481.27 kB\ndist/assets/index-Q0mP876t.js 239.30 kB \u2502 gzip: 74.99 kB \u2502 map: 1,077.97 kB\n\u2713 built in 478ms"
},
{
"name": "market",
"status": "PASS",
"elapsed_seconds": 0.819,
"artifact": "/private/tmp/hustlebot-bounties/TentOfTrials-therapy/market/market",
"output": ""
},
{
"name": "frailbox",
"status": "FAIL",
"elapsed_seconds": 1.233,
"artifact": null,
"output": "gcc -Wall -Wextra -Wpedantic -std=c2x -O2 -g -D_FORTIFY_SOURCE=3 -fstack-protector-strong -fPIE -Iinclude -MMD -MP -c src/arena.c -o build/src/arena.o\nsrc/arena.c:17:23: error: use of undeclared identifier 'MAP_HUGETLB'\n 17 | mmap_flags |= MAP_HUGETLB;\n | ^\nsrc/arena.c:179:17: warning: comparison of distinct pointer types ('const void *' and 'char *') [-Wcompare-distinct-pointer-types]\n 179 | ptr < (char *)region->start + region->size) {\n | ~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n1 warning and 1 error generated.\nmake: *** [build/src/arena.o] Error 1"
},
{
"name": "engine",
"status": "FAIL",
"elapsed_seconds": 0,
"artifact": null,
"output": "Command not found: [Errno 2] No such file or directory: 'cmake'"
},
{
"name": "compliance",
"status": "FAIL",
"elapsed_seconds": 0.012,
"artifact": null,
"output": "The operation couldn\u2019t be completed. Unable to locate a Java Runtime.\nPlease visit http://www.java.com for information on installing Java."
},
{
"name": "v2-market-stream",
"status": "PASS",
"elapsed_seconds": 0.068,
"artifact": null,
"output": "Syntax OK"
},
{
"name": "nfc-scanner",
"status": "FAIL",
"elapsed_seconds": 0,
"artifact": null,
"output": "Command not found: [Errno 2] No such file or directory: 'luac'"
},
{
"name": "openapi-haskell",
"status": "FAIL",
"elapsed_seconds": 0,
"artifact": null,
"output": "Command not found: [Errno 2] No such file or directory: 'ghc'"
},
{
"name": "openapi-tools",
"status": "FAIL",
"elapsed_seconds": 0,
"artifact": null,
"output": "Command not found: [Errno 2] No such file or directory: 'luac'"
}
],
"pr_note": "Include the encrypted diagnostic logd artifact(s): diagnostic/build-94e0fb08.logd. The encrypted .logd is the required diagnostic content for PR review; this JSON file is metadata. Maintainers may ask you to remove these diagnostic artifacts before merging."
}
Binary file added diagnostic/build-94e0fb08.logd
Binary file not shown.
108 changes: 108 additions & 0 deletions frontend/src/components/ErrorBoundary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import React from 'react';
import { trackError } from '../services/telemetry';

type ErrorBoundaryTone = 'section' | 'card';

interface ErrorBoundaryProps {
children: React.ReactNode;
name: string;
fallbackTitle?: string;
fallbackMessage?: string;
tone?: ErrorBoundaryTone;
}

interface ErrorBoundaryState {
hasError: boolean;
errorId: string | null;
}

const fallbackStyles: Record<ErrorBoundaryTone, React.CSSProperties> = {
section: {
border: '1px solid #334155',
borderRadius: '12px',
background: '#1e293b',
color: '#f8fafc',
padding: '1.5rem',
},
card: {
border: '1px solid #334155',
borderRadius: '10px',
background: '#0f172a',
color: '#f8fafc',
padding: '1rem',
minHeight: '120px',
},
};

const buttonStyles: React.CSSProperties = {
border: '1px solid #3b82f6',
borderRadius: '8px',
background: '#2563eb',
color: '#ffffff',
cursor: 'pointer',
fontWeight: 600,
padding: '0.5rem 0.75rem',
};

class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {
state: ErrorBoundaryState = {
hasError: false,
errorId: null,
};

static getDerivedStateFromError(): ErrorBoundaryState {
return {
hasError: true,
errorId: `ui-${Date.now().toString(36)}`,
};
}

componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {
const component = this.props.name;

trackError(error, component, ['error-boundary']);
// Keep a local developer signal without exposing the stack trace in the UI.
console.error(`ErrorBoundary caught render failure in ${component}`, {
error,
componentStack: errorInfo.componentStack,
});
}

reset = (): void => {
this.setState({ hasError: false, errorId: null });
};

render(): React.ReactNode {
if (!this.state.hasError) {
return this.props.children;
}

const tone = this.props.tone ?? 'section';

return (
<div
role="alert"
aria-live="polite"
className={`error-boundary-fallback error-boundary-fallback--${tone}`}
style={fallbackStyles[tone]}
>
<h3 style={{ marginBottom: '0.5rem' }}>
{this.props.fallbackTitle ?? 'This section could not be displayed'}
</h3>
<p style={{ color: '#cbd5e1', marginBottom: '1rem' }}>
{this.props.fallbackMessage ?? 'Try again, or reload the page if the problem continues.'}
</p>
<button type="button" onClick={this.reset} style={buttonStyles}>
Retry
</button>
{this.state.errorId && (
<small style={{ color: '#94a3b8', display: 'block', marginTop: '0.75rem' }}>
Reference: {this.state.errorId}
</small>
)}
</div>
);
}
}

export default ErrorBoundary;
88 changes: 51 additions & 37 deletions frontend/src/pages/Dashboard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import ErrorBoundary from '../components/ErrorBoundary';
import { useDashboardStats } from '../hooks';

const statCards = [
Expand Down Expand Up @@ -31,50 +32,63 @@ const Dashboard: React.FC = () => {
}

return (
<div className="dashboard">
<div className="dashboard-header">
<h2>Dashboard</h2>
<p className="dashboard-subtitle">
Tent of Trials System Overview
</p>
</div>
<ErrorBoundary
name="Dashboard"
fallbackTitle="Dashboard temporarily unavailable"
fallbackMessage="The dashboard hit a rendering problem. Retry this section or reload the page to recover."
>
<div className="dashboard">
<div className="dashboard-header">
<h2>Dashboard</h2>
<p className="dashboard-subtitle">
Tent of Trials System Overview
</p>
</div>

<div className="stats-grid">
{statCards.map((card) => (
<div key={card.key} className="stat-card">
<div
className="stat-card-indicator"
style={{ backgroundColor: card.color }}
/>
<div className="stat-card-content">
<span className="stat-card-label">{card.label}</span>
<span
className="stat-card-value"
style={{ color: card.color }}
>
{String((stats as any)?.[card.key] ?? ' - ')}
{card.suffix || ''}
</span>
</div>
<ErrorBoundary
name="DashboardStatCards"
tone="card"
fallbackTitle="Stats unavailable"
fallbackMessage="A dashboard stat failed to render. Other dashboard panels remain available."
>
<div className="stats-grid">
{statCards.map((card) => (
<div key={card.key} className="stat-card">
<div
className="stat-card-indicator"
style={{ backgroundColor: card.color }}
/>
<div className="stat-card-content">
<span className="stat-card-label">{card.label}</span>
<span
className="stat-card-value"
style={{ color: card.color }}
>
{String((stats as any)?.[card.key] ?? ' - ')}
{card.suffix || ''}
</span>
</div>
</div>
))}
</div>
))}
</div>
</ErrorBoundary>

<div className="dashboard-panels">
<div className="panel">
<h3>Recent Activity</h3>
<div className="panel-placeholder">
Activity feed will appear here
<div className="dashboard-panels">
<div className="panel">
<h3>Recent Activity</h3>
<div className="panel-placeholder">
Activity feed will appear here
</div>
</div>
</div>
<div className="panel">
<h3>System Health</h3>
<div className="panel-placeholder">
Health metrics will appear here
<div className="panel">
<h3>System Health</h3>
<div className="panel-placeholder">
Health metrics will appear here
</div>
</div>
</div>
</div>
</div>
</ErrorBoundary>
);
};

Expand Down