diff --git a/diagnostic/build-94e0fb08.json b/diagnostic/build-94e0fb08.json new file mode 100644 index 00000000..7b349ca5 --- /dev/null +++ b/diagnostic/build-94e0fb08.json @@ -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 --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." +} diff --git a/diagnostic/build-94e0fb08.logd b/diagnostic/build-94e0fb08.logd new file mode 100644 index 00000000..8cae9cc4 Binary files /dev/null and b/diagnostic/build-94e0fb08.logd differ diff --git a/frontend/src/components/ErrorBoundary.tsx b/frontend/src/components/ErrorBoundary.tsx new file mode 100644 index 00000000..0376e7a9 --- /dev/null +++ b/frontend/src/components/ErrorBoundary.tsx @@ -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 = { + 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 { + 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 ( +
+

+ {this.props.fallbackTitle ?? 'This section could not be displayed'} +

+

+ {this.props.fallbackMessage ?? 'Try again, or reload the page if the problem continues.'} +

+ + {this.state.errorId && ( + + Reference: {this.state.errorId} + + )} +
+ ); + } +} + +export default ErrorBoundary; diff --git a/frontend/src/pages/Dashboard.tsx b/frontend/src/pages/Dashboard.tsx index 447dcfa3..2c3aacb7 100644 --- a/frontend/src/pages/Dashboard.tsx +++ b/frontend/src/pages/Dashboard.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import ErrorBoundary from '../components/ErrorBoundary'; import { useDashboardStats } from '../hooks'; const statCards = [ @@ -31,50 +32,63 @@ const Dashboard: React.FC = () => { } return ( -
-
-

Dashboard

-

- Tent of Trials System Overview -

-
+ +
+
+

Dashboard

+

+ Tent of Trials System Overview +

+
-
- {statCards.map((card) => ( -
-
-
- {card.label} - - {String((stats as any)?.[card.key] ?? ' - ')} - {card.suffix || ''} - -
+ +
+ {statCards.map((card) => ( +
+
+
+ {card.label} + + {String((stats as any)?.[card.key] ?? ' - ')} + {card.suffix || ''} + +
+
+ ))}
- ))} -
+
-
-
-

Recent Activity

-
- Activity feed will appear here +
+
+

Recent Activity

+
+ Activity feed will appear here +
-
-
-

System Health

-
- Health metrics will appear here +
+

System Health

+
+ Health metrics will appear here +
-
+ ); };