{"version": "2.1.0", "$schema": "https://json.schemastore.org/sarif-2.1.0.json", "runs": [{"tool": {"driver": {"name": "Repobility", "informationUri": "https://repobility.com", "rules": [{"id": "scanner-d498e0aa37252b95", "name": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/FolderAssign.tsx:48", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/FolderAssign.tsx:48"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-b2f2b182ef182234", "name": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/BottomNav.tsx:87", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/BottomNav.tsx:87"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-dc7f61e3d202338c", "name": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/BrowserViewer.tsx:84", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/BrowserViewer.tsx:84"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-56034b79261a347d", "name": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/Modal.tsx:83", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/Modal.tsx:83"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-d9a9883f84212f0d", "name": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/DashboardGrid.tsx:97", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/DashboardGrid.tsx:97"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-e6deb8d03b41f060", "name": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/widgets/AudioPlayerWidget.tsx:100", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/widgets/AudioPlayerWidget.tsx:100"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-bb4d18df1a9a112b", "name": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/widgets/FilePreviewWidget.tsx:86", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/widgets/FilePreviewWidget.tsx:86"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-dd7d9bc9a7d28733", "name": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/widgets/WidgetRenderer.tsx:124", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/widgets/WidgetRenderer.tsx:124"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-1834b93c34b652f4", "name": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/widgets/VideoPlayerWidget.tsx:25", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/widgets/VideoPlayerWidget.tsx:25"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-f2a10423aab4e1c1", "name": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/chat/CollapsibleCode.tsx:72", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/chat/CollapsibleCode.tsx:72"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-cd7dc69bf4ff2432", "name": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/chat/ThreadMembersPanel.tsx:35", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/chat/ThreadMembersPanel.tsx:35"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-532e2a763b9ea2f5", "name": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/chat/SubAgentPanel.tsx:68", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/chat/SubAgentPanel.tsx:68"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-bd79fb908dcfe2bb", "name": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/chat/ToolPanels.tsx:73", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/chat/ToolPanels.tsx:73"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-e92366888fcd17b9", "name": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/workbench/ProjectsPanel.tsx:175", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/workbench/ProjectsPanel.tsx:175"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-dc7d79cccc4f6aef", "name": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/workbench/TabBar.tsx:54", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/workbench/TabBar.tsx:54"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-e94e491da18ea09e", "name": "TODO/FIXME marker in shipping code \u2014 web/frontend/src/lib/api-helpers.ts:369", "shortDescription": {"text": "TODO/FIXME marker in shipping code \u2014 web/frontend/src/lib/api-helpers.ts:369"}, "fullDescription": {"text": "Track in /reviews or /issues, not as a code comment that rots.\n\nWhy: Drift control \u2014 shouldn't be the same as Quality TODO scanner.\nRule id: fq.todo-marker"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-6745f743c34e0f7c", "name": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Agents.tsx:308", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Agents.tsx:308"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-6987ac51321e2935", "name": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Chat.tsx:1102", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Chat.tsx:1102"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-f97cbc44a7050952", "name": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/AgentEdit.tsx:575", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/AgentEdit.tsx:575"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-04d537ba2c25d561", "name": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Skills.tsx:171", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Skills.tsx:171"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-9990cd02e4a2891b", "name": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Dashboards.tsx:294", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Dashboards.tsx:294"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-5eaf4c752b7d65f5", "name": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/MediaLibrary.tsx:259", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/MediaLibrary.tsx:259"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-b1de5198f36568a4", "name": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Library.tsx:499", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Library.tsx:499"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-eb3261642ad9001e", "name": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Settings.tsx:1048", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Settings.tsx:1048"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-50e71d9bb13c9339", "name": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Secrets.tsx:127", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Secrets.tsx:127"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-13ccb990cc3b0e4b", "name": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Scheduler.tsx:222", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Scheduler.tsx:222"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-088283ac94b4889a", "name": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Logs.tsx:286", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Logs.tsx:286"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-d74e8f9d47069319", "name": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/HeartbeatMonitor.tsx:427", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/HeartbeatMonitor.tsx:427"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-04fe533b41bcc484", "name": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/TodoLists.tsx:471", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/TodoLists.tsx:471"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-c26d996720a130af", "name": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/GatewayEdit.tsx:231", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/GatewayEdit.tsx:231"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-680c753cb9371418", "name": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Browser.tsx:96", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Browser.tsx:96"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-73ff390935a333a9", "name": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Tools.tsx:104", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Tools.tsx:104"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-748be4264341e52f", "name": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Context.tsx:185", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Context.tsx:185"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-1f3d6bc22a841ab2", "name": "Insecure pattern 'cors_wildcard' in internal/handlers/dashboards.go:307", "shortDescription": {"text": "Insecure pattern 'cors_wildcard' in internal/handlers/dashboards.go:307"}, "fullDescription": {"text": "Found a known-risky pattern (cors_wildcard). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-159b648792b774f3", "name": "Possible secret in web/frontend/src/pages/Setup.tsx", "shortDescription": {"text": "Possible secret in web/frontend/src/pages/Setup.tsx"}, "fullDescription": {"text": "Detected pattern matching password_literal. Rotate the credential and move to a secret manager."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "critical", "confidence": 1.0}}, {"id": "scanner-46c644c6227e4d4a", "name": "GitHub Action is tag-pinned rather than SHA-pinned", "shortDescription": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "fullDescription": {"text": "softprops/action-gh-release@v2 can move without a code change in this repo. Pin third-party actions to a reviewed 40-character commit SHA."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-1838a141491ce38c", "name": "GitHub Actions workflow grants broad write permissions", "shortDescription": {"text": "GitHub Actions workflow grants broad write permissions"}, "fullDescription": {"text": "CI tokens with write permissions increase blast radius when an action, dependency, or PR workflow is compromised. Prefer job-level least-privilege permissions."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-0a5ab549038c1cc1", "name": "GitHub Action is tag-pinned rather than SHA-pinned", "shortDescription": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "fullDescription": {"text": "dtolnay/rust-toolchain@stable can move without a code change in this repo. Pin third-party actions to a reviewed 40-character commit SHA."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-4da77c8b475b9ec3", "name": "GitHub Actions workflow grants broad write permissions", "shortDescription": {"text": "GitHub Actions workflow grants broad write permissions"}, "fullDescription": {"text": "CI tokens with write permissions increase blast radius when an action, dependency, or PR workflow is compromised. Prefer job-level least-privilege permissions."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-54373a6da3812e8a", "name": "Very large file: web/frontend/src/pages/Chat.tsx (1790 lines)", "shortDescription": {"text": "Very large file: web/frontend/src/pages/Chat.tsx (1790 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-07a39d12525e6506", "name": "Very large file: web/frontend/src/pages/AgentEdit.tsx (1329 lines)", "shortDescription": {"text": "Very large file: web/frontend/src/pages/AgentEdit.tsx (1329 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-c618da6ed39acb9c", "name": "Very large file: web/frontend/src/pages/Settings.tsx (3527 lines)", "shortDescription": {"text": "Very large file: web/frontend/src/pages/Settings.tsx (3527 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-6893a6c8b0861585", "name": "Very low test-to-source ratio", "shortDescription": {"text": "Very low test-to-source ratio"}, "fullDescription": {"text": "30 test file(s) for 456 source file(s) (ratio 0.07). Consider adding integration or unit tests for critical paths."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-2dfb3f7231371024", "name": "84 TODO/FIXME markers", "shortDescription": {"text": "84 TODO/FIXME markers"}, "fullDescription": {"text": "High count of TODO/FIXME/HACK markers \u2014 track them as issues so they're not forgotten."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-56f37d731d380a8b", "name": "Node manifest has dependencies but no lockfile: npm/openpaw/package.json", "shortDescription": {"text": "Node manifest has dependencies but no lockfile: npm/openpaw/package.json"}, "fullDescription": {"text": "`package.json` declares dependencies, but no same-directory npm/pnpm/yarn/bun lockfile was found. Generated projects without lockfiles are less reproducible and harder to secure-scan precisely."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-72b2a6250083a784", "name": "Placeholder or mock-heavy implementation detected", "shortDescription": {"text": "Placeholder or mock-heavy implementation detected"}, "fullDescription": {"text": "Found 151 placeholder/mock markers across 38 source files. This often means the repo looks complete while core flows still use generated scaffolding or fake data."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-2d0c7b7ab8f8aacf", "name": "Critical user flow still appears backed by mock or placeholder data", "shortDescription": {"text": "Critical user flow still appears backed by mock or placeholder data"}, "fullDescription": {"text": "A payment/auth/admin/order/billing-style flow contains mock, fake, TODO, dummy, or placeholder markers in runtime source. In the Fable corpus this is a high-leverage completeness smell: the app can look finished while the money, identity, or tenant flow is still scaffolded."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-749d4bc1bd66df5f", "name": "Agent instructions exist but release-hardening basics are missing", "shortDescription": {"text": "Agent instructions exist but release-hardening basics are missing"}, "fullDescription": {"text": "AI-coder instruction files were found, but the repo is missing lockfile. Treat this as a contract gap: the agent is guided, but the generated output is not yet guarded by the controls that make it repeatable."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-ea8f3013f588db25", "name": "Shallow git history limits provenance confidence", "shortDescription": {"text": "Shallow git history limits provenance confidence"}, "fullDescription": {"text": "The repository is a shallow clone. Origin/evolution analysis cannot distinguish fresh generation, imported legacy code, or long-lived human code with high confidence."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8424db9c75e04ba4", "name": "Very short observed git history", "shortDescription": {"text": "Very short observed git history"}, "fullDescription": {"text": "The repo has multiple source files but two or fewer visible commits. This is not a failure by itself, but it lowers confidence in evolution-based diagnosis."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-6ec48a23edfe179f", "name": "Agent authority lacks a verifier contract: .claude/agents/idea-gardener.md", "shortDescription": {"text": "Agent authority lacks a verifier contract: .claude/agents/idea-gardener.md"}, "fullDescription": {"text": "This agent instruction grants code or shell authority but does not state the verification gate that decides promotion. The recurring safe pattern is: LLM proposes; deterministic tests/build/security checks verify; only verified code promotes."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-d7c623a176e6bf84", "name": "Agent authority lacks a verifier contract: .claude/agents/the-farmer.md", "shortDescription": {"text": "Agent authority lacks a verifier contract: .claude/agents/the-farmer.md"}, "fullDescription": {"text": "This agent instruction grants code or shell authority but does not state the verification gate that decides promotion. The recurring safe pattern is: LLM proposes; deterministic tests/build/security checks verify; only verified code promotes."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-0e4ce5df93fbd46d", "name": "Agent authority lacks a verifier contract: .claude/agents/i18n-locale-translator.md", "shortDescription": {"text": "Agent authority lacks a verifier contract: .claude/agents/i18n-locale-translator.md"}, "fullDescription": {"text": "This agent instruction grants code or shell authority but does not state the verification gate that decides promotion. The recurring safe pattern is: LLM proposes; deterministic tests/build/security checks verify; only verified code promotes."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-358bc9330c880691", "name": "Agent authority lacks a verifier contract: .claude/agents/researcher.md", "shortDescription": {"text": "Agent authority lacks a verifier contract: .claude/agents/researcher.md"}, "fullDescription": {"text": "This agent instruction grants code or shell authority but does not state the verification gate that decides promotion. The recurring safe pattern is: LLM proposes; deterministic tests/build/security checks verify; only verified code promotes."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-ba8cf7601b43207f", "name": "Agent authority lacks a verifier contract: .claude/agents/go-handler-agent.md", "shortDescription": {"text": "Agent authority lacks a verifier contract: .claude/agents/go-handler-agent.md"}, "fullDescription": {"text": "This agent instruction grants code or shell authority but does not state the verification gate that decides promotion. The recurring safe pattern is: LLM proposes; deterministic tests/build/security checks verify; only verified code promotes."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-ed12b72b00b2d599", "name": "Agent authority lacks a verifier contract: .claude/agents/code-cleaner.md", "shortDescription": {"text": "Agent authority lacks a verifier contract: .claude/agents/code-cleaner.md"}, "fullDescription": {"text": "This agent instruction grants code or shell authority but does not state the verification gate that decides promotion. The recurring safe pattern is: LLM proposes; deterministic tests/build/security checks verify; only verified code promotes."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-dd2c5c4f88c937d4", "name": "Agent authority lacks a verifier contract: .claude/agents/code-quality.md", "shortDescription": {"text": "Agent authority lacks a verifier contract: .claude/agents/code-quality.md"}, "fullDescription": {"text": "This agent instruction grants code or shell authority but does not state the verification gate that decides promotion. The recurring safe pattern is: LLM proposes; deterministic tests/build/security checks verify; only verified code promotes."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-85a855f6ff1b4130", "name": "Agent authority lacks a verifier contract: .claude/skills/research/SKILL.md", "shortDescription": {"text": "Agent authority lacks a verifier contract: .claude/skills/research/SKILL.md"}, "fullDescription": {"text": "This agent instruction grants code or shell authority but does not state the verification gate that decides promotion. The recurring safe pattern is: LLM proposes; deterministic tests/build/security checks verify; only verified code promotes."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-4e36f4af2f6aefe1", "name": "Agent authority lacks a verifier contract: .claude/skills/farm-audit/SKILL.md", "shortDescription": {"text": "Agent authority lacks a verifier contract: .claude/skills/farm-audit/SKILL.md"}, "fullDescription": {"text": "This agent instruction grants code or shell authority but does not state the verification gate that decides promotion. The recurring safe pattern is: LLM proposes; deterministic tests/build/security checks verify; only verified code promotes."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-d8793b360d8e0482", "name": "`fetch()` without try/.catch or AbortSignal \u2014 web/frontend/src/components/Header.tsx:196", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/frontend/src/components/Header.tsx:196"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-29c5dacea7b019bf", "name": "`fetch()` without try/.catch or AbortSignal \u2014 web/frontend/src/lib/api.ts:32", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/frontend/src/lib/api.ts:32"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-dc6d2e46501b9fc7", "name": "`fetch()` without try/.catch or AbortSignal \u2014 web/frontend/src/pages/Agents.tsx:82", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/frontend/src/pages/Agents.tsx:82"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-01e6d1ced35d5348", "name": "`fetch()` without try/.catch or AbortSignal \u2014 web/frontend/src/pages/AgentEdit.tsx:221", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/frontend/src/pages/AgentEdit.tsx:221"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-c93239013fabbfea", "name": "`fetch()` without try/.catch or AbortSignal \u2014 web/frontend/src/pages/Dashboards.tsx:86", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/frontend/src/pages/Dashboards.tsx:86"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-affd3cf019f68e04", "name": "`fetch()` without try/.catch or AbortSignal \u2014 web/frontend/src/pages/Settings.tsx:170", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/frontend/src/pages/Settings.tsx:170"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-5e5647812e0cc7c9", "name": "`fetch()` without try/.catch or AbortSignal \u2014 web/frontend/src/pages/GatewayEdit.tsx:104", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/frontend/src/pages/GatewayEdit.tsx:104"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-0bf89447027690f8", "name": "Frontend route `get-started` has no Link/navigate to it \u2014 web/frontend/src/App.tsx", "shortDescription": {"text": "Frontend route `get-started` has no Link/navigate to it \u2014 web/frontend/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-c19e4b1752903380", "name": "Frontend route `how-it-works` has no Link/navigate to it \u2014 web/frontend/src/App.tsx", "shortDescription": {"text": "Frontend route `how-it-works` has no Link/navigate to it \u2014 web/frontend/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-a82689dbe247a325", "name": "Frontend route `features` has no Link/navigate to it \u2014 web/frontend/src/App.tsx", "shortDescription": {"text": "Frontend route `features` has no Link/navigate to it \u2014 web/frontend/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-487a9b6e205d4724", "name": "Frontend route `desktop` has no Link/navigate to it \u2014 web/frontend/src/App.tsx", "shortDescription": {"text": "Frontend route `desktop` has no Link/navigate to it \u2014 web/frontend/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-ff220bcdfe1c2d56", "name": "Frontend route `use-cases` has no Link/navigate to it \u2014 web/frontend/src/App.tsx", "shortDescription": {"text": "Frontend route `use-cases` has no Link/navigate to it \u2014 web/frontend/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-7b9852f68aa3ac0c", "name": "Frontend route `architecture` has no Link/navigate to it \u2014 web/frontend/src/App.tsx", "shortDescription": {"text": "Frontend route `architecture` has no Link/navigate to it \u2014 web/frontend/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-3ff517a713b1f9dd", "name": "Frontend route `/chat/:threadId` has no Link/navigate to it \u2014 web/frontend/src/App.tsx", "shortDescription": {"text": "Frontend route `/chat/:threadId` has no Link/navigate to it \u2014 web/frontend/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-84b865cede6e499d", "name": "Frontend route `/agents/:slug` has no Link/navigate to it \u2014 web/frontend/src/App.tsx", "shortDescription": {"text": "Frontend route `/agents/:slug` has no Link/navigate to it \u2014 web/frontend/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-fff39d3b4e2d6eab", "name": "Dangling fetch: POST /api/v1/auth/avatar (web/frontend/src/components/Header.tsx:196)", "shortDescription": {"text": "Dangling fetch: POST /api/v1/auth/avatar (web/frontend/src/components/Header.tsx:196)"}, "fullDescription": {"text": "`web/frontend/src/components/Header.tsx:196` calls `POST /api/v1/auth/avatar` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/v1/auth/avatar`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-3398b8a1ca780b91", "name": "Dangling fetch: POST /api/v1/agent-roles/upload-avatar (web/frontend/src/pages/Agents.tsx:82)", "shortDescription": {"text": "Dangling fetch: POST /api/v1/agent-roles/upload-avatar (web/frontend/src/pages/Agents.tsx:82)"}, "fullDescription": {"text": "`web/frontend/src/pages/Agents.tsx:82` calls `POST /api/v1/agent-roles/upload-avatar` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/v1/agent-roles/upload-avatar`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-f8c73b07b7a12aad", "name": "Dangling fetch: POST /api/v1/agent-roles/upload-avatar (web/frontend/src/pages/AgentEdit.tsx:221)", "shortDescription": {"text": "Dangling fetch: POST /api/v1/agent-roles/upload-avatar (web/frontend/src/pages/AgentEdit.tsx:221)"}, "fullDescription": {"text": "`web/frontend/src/pages/AgentEdit.tsx:221` calls `POST /api/v1/agent-roles/upload-avatar` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/v1/agent-roles/upload-avatar`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-605a4d5c7db5ceaa", "name": "Dangling fetch: POST /api/v1/tools/${toolId}/call (web/frontend/src/pages/Dashboards.tsx:86)", "shortDescription": {"text": "Dangling fetch: POST /api/v1/tools/${toolId}/call (web/frontend/src/pages/Dashboards.tsx:86)"}, "fullDescription": {"text": "`web/frontend/src/pages/Dashboards.tsx:86` calls `POST /api/v1/tools/${toolId}/call` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/v1/tools/<p>/call`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-9d148832ddf690d6", "name": "Dangling fetch: GET /api/v1/tools (web/frontend/src/pages/Dashboards.tsx:94)", "shortDescription": {"text": "Dangling fetch: GET /api/v1/tools (web/frontend/src/pages/Dashboards.tsx:94)"}, "fullDescription": {"text": "`web/frontend/src/pages/Dashboards.tsx:94` calls `GET /api/v1/tools` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/v1/tools`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-11458138685e5ebb", "name": "Dangling fetch: POST /api/v1/settings/design/background (web/frontend/src/pages/Dashboards.tsx:237)", "shortDescription": {"text": "Dangling fetch: POST /api/v1/settings/design/background (web/frontend/src/pages/Dashboards.tsx:237)"}, "fullDescription": {"text": "`web/frontend/src/pages/Dashboards.tsx:237` calls `POST /api/v1/settings/design/background` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/v1/settings/design/background`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-383ff7e4e37a30f7", "name": "Dangling fetch: POST /api/v1/auth/avatar (web/frontend/src/pages/Settings.tsx:170)", "shortDescription": {"text": "Dangling fetch: POST /api/v1/auth/avatar (web/frontend/src/pages/Settings.tsx:170)"}, "fullDescription": {"text": "`web/frontend/src/pages/Settings.tsx:170` calls `POST /api/v1/auth/avatar` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/v1/auth/avatar`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-a8f5501ddbc2f5dc", "name": "Dangling fetch: POST /api/v1/settings/design/background (web/frontend/src/pages/Settings.tsx:1892)", "shortDescription": {"text": "Dangling fetch: POST /api/v1/settings/design/background (web/frontend/src/pages/Settings.tsx:1892)"}, "fullDescription": {"text": "`web/frontend/src/pages/Settings.tsx:1892` calls `POST /api/v1/settings/design/background` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/v1/settings/design/background`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-cbbd7b24ca83164a", "name": "Dangling fetch: GET /api/v1/system/health (web/frontend/src/pages/Settings.tsx:2391)", "shortDescription": {"text": "Dangling fetch: GET /api/v1/system/health (web/frontend/src/pages/Settings.tsx:2391)"}, "fullDescription": {"text": "`web/frontend/src/pages/Settings.tsx:2391` calls `GET /api/v1/system/health` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/v1/system/health`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-349fbcde401f47b0", "name": "Dangling fetch: GET /api/v1/system/export (web/frontend/src/pages/Settings.tsx:2907)", "shortDescription": {"text": "Dangling fetch: GET /api/v1/system/export (web/frontend/src/pages/Settings.tsx:2907)"}, "fullDescription": {"text": "`web/frontend/src/pages/Settings.tsx:2907` calls `GET /api/v1/system/export` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/v1/system/export`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-f38a49d6fcdfa931", "name": "Dangling fetch: POST /api/v1/agent-roles/upload-avatar (web/frontend/src/pages/GatewayEdit.tsx:104)", "shortDescription": {"text": "Dangling fetch: POST /api/v1/agent-roles/upload-avatar (web/frontend/src/pages/GatewayEdit.tsx:104)"}, "fullDescription": {"text": "`web/frontend/src/pages/GatewayEdit.tsx:104` calls `POST /api/v1/agent-roles/upload-avatar` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: fetch\nNormalized path used for matching: `/v1/agent-roles/upload-avatar`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-f9510b91177d65de", "name": "Unused endpoint: PUT /settings/pixellab-api-key", "shortDescription": {"text": "Unused endpoint: PUT /settings/pixellab-api-key"}, "fullDescription": {"text": "`web/frontend/src/components/companion/CompanionWizard.tsx` declares `PUT /settings/pixellab-api-key` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-c059f57186114027", "name": "Unused endpoint: POST /auth/logout", "shortDescription": {"text": "Unused endpoint: POST /auth/logout"}, "fullDescription": {"text": "`web/frontend/src/contexts/AuthContext.tsx` declares `POST /auth/logout` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-247fd8314d5d575f", "name": "Unused endpoint: PUT /settings/design", "shortDescription": {"text": "Unused endpoint: PUT /settings/design"}, "fullDescription": {"text": "`web/frontend/src/contexts/DesignContext.tsx` declares `PUT /settings/design` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-6a23aeabb1f0c4d3", "name": "Unused endpoint: PUT /notifications/read-all", "shortDescription": {"text": "Unused endpoint: PUT /notifications/read-all"}, "fullDescription": {"text": "`web/frontend/src/lib/api-helpers.ts` declares `PUT /notifications/read-all` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-d153c42975584121", "name": "Unused endpoint: DELETE /notifications", "shortDescription": {"text": "Unused endpoint: DELETE /notifications"}, "fullDescription": {"text": "`web/frontend/src/lib/api-helpers.ts` declares `DELETE /notifications` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-684f0e83ba7e1558", "name": "Unused endpoint: GET ", "shortDescription": {"text": "Unused endpoint: GET "}, "fullDescription": {"text": "`web/frontend/src/pages/Agents.tsx` declares `GET ` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-193f390c75901c60", "name": "Unused endpoint: POST /setup/personalize", "shortDescription": {"text": "Unused endpoint: POST /setup/personalize"}, "fullDescription": {"text": "`web/frontend/src/pages/Setup.tsx` declares `POST /setup/personalize` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-9143464946a01de5", "name": "Unused endpoint: PUT /auth/profile", "shortDescription": {"text": "Unused endpoint: PUT /auth/profile"}, "fullDescription": {"text": "`web/frontend/src/pages/Settings.tsx` declares `PUT /auth/profile` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-4585c350da9e880d", "name": "Unused endpoint: POST /auth/change-password", "shortDescription": {"text": "Unused endpoint: POST /auth/change-password"}, "fullDescription": {"text": "`web/frontend/src/pages/Settings.tsx` declares `POST /auth/change-password` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-ababc57d7228b4f3", "name": "Unused endpoint: PUT /settings/general", "shortDescription": {"text": "Unused endpoint: PUT /settings/general"}, "fullDescription": {"text": "`web/frontend/src/pages/Settings.tsx` declares `PUT /settings/general` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-1cf2ed60cbbf2375", "name": "Unused endpoint: PUT /settings", "shortDescription": {"text": "Unused endpoint: PUT /settings"}, "fullDescription": {"text": "`web/frontend/src/pages/Settings.tsx` declares `PUT /settings` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-35064f229286d579", "name": "Unused endpoint: PUT /settings/models", "shortDescription": {"text": "Unused endpoint: PUT /settings/models"}, "fullDescription": {"text": "`web/frontend/src/pages/Settings.tsx` declares `PUT /settings/models` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-391fb7eb180ea08f", "name": "Unused endpoint: PUT /settings/api-key", "shortDescription": {"text": "Unused endpoint: PUT /settings/api-key"}, "fullDescription": {"text": "`web/frontend/src/pages/Settings.tsx` declares `PUT /settings/api-key` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-34ba520914d95542", "name": "Unused endpoint: PUT /settings/security", "shortDescription": {"text": "Unused endpoint: PUT /settings/security"}, "fullDescription": {"text": "`web/frontend/src/pages/Settings.tsx` declares `PUT /settings/security` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-f7e43671782ea387", "name": "Unused endpoint: POST /system/update/apply", "shortDescription": {"text": "Unused endpoint: POST /system/update/apply"}, "fullDescription": {"text": "`web/frontend/src/pages/Settings.tsx` declares `POST /system/update/apply` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-a21c666784531829", "name": "Unused endpoint: POST /settings/backup/run", "shortDescription": {"text": "Unused endpoint: POST /settings/backup/run"}, "fullDescription": {"text": "`web/frontend/src/pages/Settings.tsx` declares `POST /settings/backup/run` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-2f825e4e1d86d83c", "name": "Unused endpoint: DELETE /system/data", "shortDescription": {"text": "Unused endpoint: DELETE /system/data"}, "fullDescription": {"text": "`web/frontend/src/pages/Settings.tsx` declares `DELETE /system/data` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-2346b4b4a8d305f0", "name": "Unused endpoint: DELETE /auth/account", "shortDescription": {"text": "Unused endpoint: DELETE /auth/account"}, "fullDescription": {"text": "`web/frontend/src/pages/Settings.tsx` declares `DELETE /auth/account` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-1684892a9c1b4be5", "name": "Unused endpoint: POST /secrets", "shortDescription": {"text": "Unused endpoint: POST /secrets"}, "fullDescription": {"text": "`web/frontend/src/pages/Secrets.tsx` declares `POST /secrets` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-bb4497b3cab9fef5", "name": "Unused endpoint: POST /schedules", "shortDescription": {"text": "Unused endpoint: POST /schedules"}, "fullDescription": {"text": "`web/frontend/src/pages/Scheduler.tsx` declares `POST /schedules` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}]}}, "automationDetails": {"id": "repobility/22923"}, "properties": {"repository": "WynterJones/OpenPaw", "repoUrl": "https://github.com/WynterJones/OpenPaw", "branch": "main"}, "results": [{"ruleId": "scanner-d498e0aa37252b95", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/FolderAssign.tsx:48"}, "properties": {"repobilityId": "99483c4c3c0d599a", "scanner": "scanner-primary", "fingerprint": "d498e0aa37252b95", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-b2f2b182ef182234", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/BottomNav.tsx:87"}, "properties": {"repobilityId": "8cf0e9e2609ccc50", "scanner": "scanner-primary", "fingerprint": "b2f2b182ef182234", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-dc7f61e3d202338c", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/BrowserViewer.tsx:84"}, "properties": {"repobilityId": "1943e0444b6a1051", "scanner": "scanner-primary", "fingerprint": "dc7f61e3d202338c", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-56034b79261a347d", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/Modal.tsx:83"}, "properties": {"repobilityId": "4210602286cb93bd", "scanner": "scanner-primary", "fingerprint": "56034b79261a347d", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-d9a9883f84212f0d", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/DashboardGrid.tsx:97"}, "properties": {"repobilityId": "6be0bde0ea94f0a5", "scanner": "scanner-primary", "fingerprint": "d9a9883f84212f0d", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-e6deb8d03b41f060", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/widgets/AudioPlayerWidget.tsx:100"}, "properties": {"repobilityId": "8bd5c2d121768574", "scanner": "scanner-primary", "fingerprint": "e6deb8d03b41f060", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-bb4d18df1a9a112b", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/widgets/FilePreviewWidget.tsx:86"}, "properties": {"repobilityId": "4e20c460664873ef", "scanner": "scanner-primary", "fingerprint": "bb4d18df1a9a112b", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-dd7d9bc9a7d28733", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/widgets/WidgetRenderer.tsx:124"}, "properties": {"repobilityId": "12893e6206f3818b", "scanner": "scanner-primary", "fingerprint": "dd7d9bc9a7d28733", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-1834b93c34b652f4", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/widgets/VideoPlayerWidget.tsx:25"}, "properties": {"repobilityId": "31e76cd0a8b84cef", "scanner": "scanner-primary", "fingerprint": "1834b93c34b652f4", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-f2a10423aab4e1c1", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/chat/CollapsibleCode.tsx:72"}, "properties": {"repobilityId": "7d7e62157e89ac3a", "scanner": "scanner-primary", "fingerprint": "f2a10423aab4e1c1", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-cd7dc69bf4ff2432", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/chat/ThreadMembersPanel.tsx:35"}, "properties": {"repobilityId": "9e3b0ea141940f85", "scanner": "scanner-primary", "fingerprint": "cd7dc69bf4ff2432", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-532e2a763b9ea2f5", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/chat/SubAgentPanel.tsx:68"}, "properties": {"repobilityId": "20c2b687afefc20d", "scanner": "scanner-primary", "fingerprint": "532e2a763b9ea2f5", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-bd79fb908dcfe2bb", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/chat/ToolPanels.tsx:73"}, "properties": {"repobilityId": "dd9d0a29f4d2ac6c", "scanner": "scanner-primary", "fingerprint": "bd79fb908dcfe2bb", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-e92366888fcd17b9", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/workbench/ProjectsPanel.tsx:175"}, "properties": {"repobilityId": "376b50854fae9bea", "scanner": "scanner-primary", "fingerprint": "e92366888fcd17b9", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-dc7d79cccc4f6aef", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/components/workbench/TabBar.tsx:54"}, "properties": {"repobilityId": "2837b070acf667c3", "scanner": "scanner-primary", "fingerprint": "dc7d79cccc4f6aef", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-e94e491da18ea09e", "level": "none", "message": {"text": "TODO/FIXME marker in shipping code \u2014 web/frontend/src/lib/api-helpers.ts:369"}, "properties": {"repobilityId": "e63692b0504b7b21", "scanner": "scanner-primary", "fingerprint": "e94e491da18ea09e", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.todo-marker"]}}, {"ruleId": "scanner-6745f743c34e0f7c", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Agents.tsx:308"}, "properties": {"repobilityId": "50af9173ebca34b8", "scanner": "scanner-primary", "fingerprint": "6745f743c34e0f7c", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-6987ac51321e2935", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Chat.tsx:1102"}, "properties": {"repobilityId": "b0ba6248310015ec", "scanner": "scanner-primary", "fingerprint": "6987ac51321e2935", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-f97cbc44a7050952", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/AgentEdit.tsx:575"}, "properties": {"repobilityId": "4e840baf2a3c6c54", "scanner": "scanner-primary", "fingerprint": "f97cbc44a7050952", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-04d537ba2c25d561", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Skills.tsx:171"}, "properties": {"repobilityId": "1bb02fa960754d98", "scanner": "scanner-primary", "fingerprint": "04d537ba2c25d561", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-9990cd02e4a2891b", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Dashboards.tsx:294"}, "properties": {"repobilityId": "0594cdf459fa4789", "scanner": "scanner-primary", "fingerprint": "9990cd02e4a2891b", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-5eaf4c752b7d65f5", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/MediaLibrary.tsx:259"}, "properties": {"repobilityId": "35fb1c594ff4c88e", "scanner": "scanner-primary", "fingerprint": "5eaf4c752b7d65f5", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-b1de5198f36568a4", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Library.tsx:499"}, "properties": {"repobilityId": "978eede8350c24ce", "scanner": "scanner-primary", "fingerprint": "b1de5198f36568a4", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-eb3261642ad9001e", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Settings.tsx:1048"}, "properties": {"repobilityId": "179e60075ae0a9ba", "scanner": "scanner-primary", "fingerprint": "eb3261642ad9001e", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-50e71d9bb13c9339", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Secrets.tsx:127"}, "properties": {"repobilityId": "1b0c583f0edb2e40", "scanner": "scanner-primary", "fingerprint": "50e71d9bb13c9339", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-13ccb990cc3b0e4b", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Scheduler.tsx:222"}, "properties": {"repobilityId": "cb40b04372de1683", "scanner": "scanner-primary", "fingerprint": "13ccb990cc3b0e4b", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-088283ac94b4889a", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Logs.tsx:286"}, "properties": {"repobilityId": "bf8a2ebfe94c480d", "scanner": "scanner-primary", "fingerprint": "088283ac94b4889a", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-d74e8f9d47069319", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/HeartbeatMonitor.tsx:427"}, "properties": {"repobilityId": "a3f1848d50dc7996", "scanner": "scanner-primary", "fingerprint": "d74e8f9d47069319", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-04fe533b41bcc484", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/TodoLists.tsx:471"}, "properties": {"repobilityId": "f6c847e8ab0fe637", "scanner": "scanner-primary", "fingerprint": "04fe533b41bcc484", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-c26d996720a130af", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/GatewayEdit.tsx:231"}, "properties": {"repobilityId": "625d5c023480f288", "scanner": "scanner-primary", "fingerprint": "c26d996720a130af", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-680c753cb9371418", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Browser.tsx:96"}, "properties": {"repobilityId": "97e04d3fcc31cb1d", "scanner": "scanner-primary", "fingerprint": "680c753cb9371418", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-73ff390935a333a9", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Tools.tsx:104"}, "properties": {"repobilityId": "161784442cd78e43", "scanner": "scanner-primary", "fingerprint": "73ff390935a333a9", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-748be4264341e52f", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/frontend/src/pages/Context.tsx:185"}, "properties": {"repobilityId": "569de9e6fdc6bfd3", "scanner": "scanner-primary", "fingerprint": "748be4264341e52f", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-1f3d6bc22a841ab2", "level": "warning", "message": {"text": "Insecure pattern 'cors_wildcard' in internal/handlers/dashboards.go:307"}, "properties": {"repobilityId": "a906e6da70291aa1", "scanner": "scanner-primary", "fingerprint": "1f3d6bc22a841ab2", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "cors_wildcard"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "internal/handlers/dashboards.go"}, "region": {"startLine": 307}}}]}, {"ruleId": "scanner-159b648792b774f3", "level": "error", "message": {"text": "Possible secret in web/frontend/src/pages/Setup.tsx"}, "properties": {"repobilityId": "9be06cb545ca5189", "scanner": "scanner-primary", "fingerprint": "159b648792b774f3", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "web/frontend/src/pages/Setup.tsx"}, "region": {"startLine": 58}}}]}, {"ruleId": "scanner-159b648792b774f3", "level": "error", "message": {"text": "Possible secret in web/frontend/src/pages/Setup.tsx"}, "properties": {"repobilityId": "9be06cb545ca5189", "scanner": "scanner-primary", "fingerprint": "159b648792b774f3", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "web/frontend/src/pages/Setup.tsx"}, "region": {"startLine": 59}}}]}, {"ruleId": "scanner-159b648792b774f3", "level": "error", "message": {"text": "Possible secret in web/frontend/src/pages/Setup.tsx"}, "properties": {"repobilityId": "9be06cb545ca5189", "scanner": "scanner-primary", "fingerprint": "159b648792b774f3", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "web/frontend/src/pages/Setup.tsx"}, "region": {"startLine": 60}}}]}, {"ruleId": "scanner-46c644c6227e4d4a", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "f0dc584a111ffc00", "scanner": "scanner-primary", "fingerprint": "46c644c6227e4d4a", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/release.yml"}, "region": {"startLine": 93}}}]}, {"ruleId": "scanner-1838a141491ce38c", "level": "warning", "message": {"text": "GitHub Actions workflow grants broad write permissions"}, "properties": {"repobilityId": "b8fd4f5048f96576", "scanner": "scanner-primary", "fingerprint": "1838a141491ce38c", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "least-privilege"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/release.yml"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-0a5ab549038c1cc1", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "5edd46b2559194b1", "scanner": "scanner-primary", "fingerprint": "0a5ab549038c1cc1", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/desktop.yml"}, "region": {"startLine": 44}}}]}, {"ruleId": "scanner-0a5ab549038c1cc1", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "21d72c513ba52208", "scanner": "scanner-primary", "fingerprint": "0a5ab549038c1cc1", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/desktop.yml"}, "region": {"startLine": 77}}}]}, {"ruleId": "scanner-4da77c8b475b9ec3", "level": "warning", "message": {"text": "GitHub Actions workflow grants broad write permissions"}, "properties": {"repobilityId": "e1da11cf4c7b100d", "scanner": "scanner-primary", "fingerprint": "4da77c8b475b9ec3", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "least-privilege"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/desktop.yml"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-54373a6da3812e8a", "level": "note", "message": {"text": "Very large file: web/frontend/src/pages/Chat.tsx (1790 lines)"}, "properties": {"repobilityId": "fb8f5bc1991db9d3", "scanner": "scanner-primary", "fingerprint": "54373a6da3812e8a", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-07a39d12525e6506", "level": "note", "message": {"text": "Very large file: web/frontend/src/pages/AgentEdit.tsx (1329 lines)"}, "properties": {"repobilityId": "76beedf571f8eae0", "scanner": "scanner-primary", "fingerprint": "07a39d12525e6506", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-c618da6ed39acb9c", "level": "note", "message": {"text": "Very large file: web/frontend/src/pages/Settings.tsx (3527 lines)"}, "properties": {"repobilityId": "da461d587ac6e092", "scanner": "scanner-primary", "fingerprint": "c618da6ed39acb9c", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-6893a6c8b0861585", "level": "warning", "message": {"text": "Very low test-to-source ratio"}, "properties": {"repobilityId": "54a7de3f06314bf0", "scanner": "scanner-primary", "fingerprint": "6893a6c8b0861585", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["tests", "coverage"]}}, {"ruleId": "scanner-2dfb3f7231371024", "level": "note", "message": {"text": "84 TODO/FIXME markers"}, "properties": {"repobilityId": "4b38c118003e07d2", "scanner": "scanner-primary", "fingerprint": "2dfb3f7231371024", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["maintenance"]}}, {"ruleId": "scanner-56f37d731d380a8b", "level": "note", "message": {"text": "Node manifest has dependencies but no lockfile: npm/openpaw/package.json"}, "properties": {"repobilityId": "155511fc6d70bdd5", "scanner": "scanner-primary", "fingerprint": "56f37d731d380a8b", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["dependency", "lockfile", "reproducibility", "generated-repo-pattern"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "npm/openpaw/package.json"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-72b2a6250083a784", "level": "warning", "message": {"text": "Placeholder or mock-heavy implementation detected"}, "properties": {"repobilityId": "3059369650ee444b", "scanner": "scanner-primary", "fingerprint": "72b2a6250083a784", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "mock-data", "incomplete", "generated-repo-pattern"]}}, {"ruleId": "scanner-2d0c7b7ab8f8aacf", "level": "warning", "message": {"text": "Critical user flow still appears backed by mock or placeholder data"}, "properties": {"repobilityId": "bdb0f0de53a7f9f8", "scanner": "scanner-primary", "fingerprint": "2d0c7b7ab8f8aacf", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "mock-data", "critical-flow", "generated-repo-pattern"]}}, {"ruleId": "scanner-749d4bc1bd66df5f", "level": "warning", "message": {"text": "Agent instructions exist but release-hardening basics are missing"}, "properties": {"repobilityId": "b9f3c2b799524c02", "scanner": "scanner-primary", "fingerprint": "749d4bc1bd66df5f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-ea8f3013f588db25", "level": "note", "message": {"text": "Shallow git history limits provenance confidence"}, "properties": {"repobilityId": "d70206432b7592cc", "scanner": "scanner-primary", "fingerprint": "ea8f3013f588db25", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["provenance", "git-history", "generated-repo-pattern"]}}, {"ruleId": "scanner-8424db9c75e04ba4", "level": "none", "message": {"text": "Very short observed git history"}, "properties": {"repobilityId": "997ade40ba1f05e6", "scanner": "scanner-primary", "fingerprint": "8424db9c75e04ba4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["provenance", "git-history", "generated-repo-pattern"]}}, {"ruleId": "scanner-6ec48a23edfe179f", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: .claude/agents/idea-gardener.md"}, "properties": {"repobilityId": "5c70b2d371fa8054", "scanner": "scanner-primary", "fingerprint": "6ec48a23edfe179f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "claude_instruction"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".claude/agents/idea-gardener.md"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-d7c623a176e6bf84", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: .claude/agents/the-farmer.md"}, "properties": {"repobilityId": "7ba3ea3c5fe4dc94", "scanner": "scanner-primary", "fingerprint": "d7c623a176e6bf84", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "claude_instruction"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".claude/agents/the-farmer.md"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-0e4ce5df93fbd46d", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: .claude/agents/i18n-locale-translator.md"}, "properties": {"repobilityId": "d4c96a64a105360a", "scanner": "scanner-primary", "fingerprint": "0e4ce5df93fbd46d", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "claude_instruction"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".claude/agents/i18n-locale-translator.md"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-358bc9330c880691", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: .claude/agents/researcher.md"}, "properties": {"repobilityId": "a67bbfb84c43b677", "scanner": "scanner-primary", "fingerprint": "358bc9330c880691", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "claude_instruction"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".claude/agents/researcher.md"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-ba8cf7601b43207f", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: .claude/agents/go-handler-agent.md"}, "properties": {"repobilityId": "ea75e5fca025b73d", "scanner": "scanner-primary", "fingerprint": "ba8cf7601b43207f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "claude_instruction"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".claude/agents/go-handler-agent.md"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-ed12b72b00b2d599", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: .claude/agents/code-cleaner.md"}, "properties": {"repobilityId": "baf7dd16e20e48e8", "scanner": "scanner-primary", "fingerprint": "ed12b72b00b2d599", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "claude_instruction"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".claude/agents/code-cleaner.md"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-dd2c5c4f88c937d4", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: .claude/agents/code-quality.md"}, "properties": {"repobilityId": "f97f5eda65a29a57", "scanner": "scanner-primary", "fingerprint": "dd2c5c4f88c937d4", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "claude_instruction"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".claude/agents/code-quality.md"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-85a855f6ff1b4130", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: .claude/skills/research/SKILL.md"}, "properties": {"repobilityId": "aa6ea638adfda0ed", "scanner": "scanner-primary", "fingerprint": "85a855f6ff1b4130", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "claude_instruction"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".claude/skills/research/SKILL.md"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-4e36f4af2f6aefe1", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: .claude/skills/farm-audit/SKILL.md"}, "properties": {"repobilityId": "ae45ba2f3a3e1eb0", "scanner": "scanner-primary", "fingerprint": "4e36f4af2f6aefe1", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "claude_instruction"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".claude/skills/farm-audit/SKILL.md"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-d8793b360d8e0482", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/frontend/src/components/Header.tsx:196"}, "properties": {"repobilityId": "16bcc61722556ad2", "scanner": "scanner-primary", "fingerprint": "d8793b360d8e0482", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-29c5dacea7b019bf", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/frontend/src/lib/api.ts:32"}, "properties": {"repobilityId": "a0988e925c5ddb10", "scanner": "scanner-primary", "fingerprint": "29c5dacea7b019bf", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-dc6d2e46501b9fc7", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/frontend/src/pages/Agents.tsx:82"}, "properties": {"repobilityId": "32fa5625b5398db9", "scanner": "scanner-primary", "fingerprint": "dc6d2e46501b9fc7", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-01e6d1ced35d5348", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/frontend/src/pages/AgentEdit.tsx:221"}, "properties": {"repobilityId": "124c1f81938f796f", "scanner": "scanner-primary", "fingerprint": "01e6d1ced35d5348", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-c93239013fabbfea", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/frontend/src/pages/Dashboards.tsx:86"}, "properties": {"repobilityId": "13471732be3abae5", "scanner": "scanner-primary", "fingerprint": "c93239013fabbfea", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-affd3cf019f68e04", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/frontend/src/pages/Settings.tsx:170"}, "properties": {"repobilityId": "cf1fb7155c7e30eb", "scanner": "scanner-primary", "fingerprint": "affd3cf019f68e04", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-5e5647812e0cc7c9", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/frontend/src/pages/GatewayEdit.tsx:104"}, "properties": {"repobilityId": "f890dbcae274951c", "scanner": "scanner-primary", "fingerprint": "5e5647812e0cc7c9", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-0bf89447027690f8", "level": "warning", "message": {"text": "Frontend route `get-started` has no Link/navigate to it \u2014 web/frontend/src/App.tsx"}, "properties": {"repobilityId": "c590ae0c73901a4d", "scanner": "scanner-primary", "fingerprint": "0bf89447027690f8", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-c19e4b1752903380", "level": "warning", "message": {"text": "Frontend route `how-it-works` has no Link/navigate to it \u2014 web/frontend/src/App.tsx"}, "properties": {"repobilityId": "62eec055e4e42cea", "scanner": "scanner-primary", "fingerprint": "c19e4b1752903380", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-a82689dbe247a325", "level": "warning", "message": {"text": "Frontend route `features` has no Link/navigate to it \u2014 web/frontend/src/App.tsx"}, "properties": {"repobilityId": "ad86dc8e8fb2f360", "scanner": "scanner-primary", "fingerprint": "a82689dbe247a325", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-487a9b6e205d4724", "level": "warning", "message": {"text": "Frontend route `desktop` has no Link/navigate to it \u2014 web/frontend/src/App.tsx"}, "properties": {"repobilityId": "e0245602f7ff1348", "scanner": "scanner-primary", "fingerprint": "487a9b6e205d4724", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-ff220bcdfe1c2d56", "level": "warning", "message": {"text": "Frontend route `use-cases` has no Link/navigate to it \u2014 web/frontend/src/App.tsx"}, "properties": {"repobilityId": "326f386bcd26db87", "scanner": "scanner-primary", "fingerprint": "ff220bcdfe1c2d56", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-7b9852f68aa3ac0c", "level": "warning", "message": {"text": "Frontend route `architecture` has no Link/navigate to it \u2014 web/frontend/src/App.tsx"}, "properties": {"repobilityId": "80720c129b2c8a88", "scanner": "scanner-primary", "fingerprint": "7b9852f68aa3ac0c", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-3ff517a713b1f9dd", "level": "warning", "message": {"text": "Frontend route `/chat/:threadId` has no Link/navigate to it \u2014 web/frontend/src/App.tsx"}, "properties": {"repobilityId": "820da90773acefd0", "scanner": "scanner-primary", "fingerprint": "3ff517a713b1f9dd", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-84b865cede6e499d", "level": "warning", "message": {"text": "Frontend route `/agents/:slug` has no Link/navigate to it \u2014 web/frontend/src/App.tsx"}, "properties": {"repobilityId": "dddaa73946ca7c71", "scanner": "scanner-primary", "fingerprint": "84b865cede6e499d", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-fff39d3b4e2d6eab", "level": "error", "message": {"text": "Dangling fetch: POST /api/v1/auth/avatar (web/frontend/src/components/Header.tsx:196)"}, "properties": {"repobilityId": "61045109c68c6f6b", "scanner": "scanner-primary", "fingerprint": "fff39d3b4e2d6eab", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-3398b8a1ca780b91", "level": "error", "message": {"text": "Dangling fetch: POST /api/v1/agent-roles/upload-avatar (web/frontend/src/pages/Agents.tsx:82)"}, "properties": {"repobilityId": "5bbbe4b393973117", "scanner": "scanner-primary", "fingerprint": "3398b8a1ca780b91", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-f8c73b07b7a12aad", "level": "error", "message": {"text": "Dangling fetch: POST /api/v1/agent-roles/upload-avatar (web/frontend/src/pages/AgentEdit.tsx:221)"}, "properties": {"repobilityId": "5e0eaf7384b2b101", "scanner": "scanner-primary", "fingerprint": "f8c73b07b7a12aad", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-605a4d5c7db5ceaa", "level": "error", "message": {"text": "Dangling fetch: POST /api/v1/tools/${toolId}/call (web/frontend/src/pages/Dashboards.tsx:86)"}, "properties": {"repobilityId": "c9628d87de4adf8b", "scanner": "scanner-primary", "fingerprint": "605a4d5c7db5ceaa", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-9d148832ddf690d6", "level": "error", "message": {"text": "Dangling fetch: GET /api/v1/tools (web/frontend/src/pages/Dashboards.tsx:94)"}, "properties": {"repobilityId": "a49efbc6c8304fee", "scanner": "scanner-primary", "fingerprint": "9d148832ddf690d6", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-11458138685e5ebb", "level": "error", "message": {"text": "Dangling fetch: POST /api/v1/settings/design/background (web/frontend/src/pages/Dashboards.tsx:237)"}, "properties": {"repobilityId": "b69432f48fd154d3", "scanner": "scanner-primary", "fingerprint": "11458138685e5ebb", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-383ff7e4e37a30f7", "level": "error", "message": {"text": "Dangling fetch: POST /api/v1/auth/avatar (web/frontend/src/pages/Settings.tsx:170)"}, "properties": {"repobilityId": "8eeddd5c699c6eb4", "scanner": "scanner-primary", "fingerprint": "383ff7e4e37a30f7", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-a8f5501ddbc2f5dc", "level": "error", "message": {"text": "Dangling fetch: POST /api/v1/settings/design/background (web/frontend/src/pages/Settings.tsx:1892)"}, "properties": {"repobilityId": "4197660cd331d49f", "scanner": "scanner-primary", "fingerprint": "a8f5501ddbc2f5dc", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-cbbd7b24ca83164a", "level": "error", "message": {"text": "Dangling fetch: GET /api/v1/system/health (web/frontend/src/pages/Settings.tsx:2391)"}, "properties": {"repobilityId": "78c0b90510f92531", "scanner": "scanner-primary", "fingerprint": "cbbd7b24ca83164a", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-349fbcde401f47b0", "level": "error", "message": {"text": "Dangling fetch: GET /api/v1/system/export (web/frontend/src/pages/Settings.tsx:2907)"}, "properties": {"repobilityId": "41340623e94bc2c5", "scanner": "scanner-primary", "fingerprint": "349fbcde401f47b0", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-f38a49d6fcdfa931", "level": "error", "message": {"text": "Dangling fetch: POST /api/v1/agent-roles/upload-avatar (web/frontend/src/pages/GatewayEdit.tsx:104)"}, "properties": {"repobilityId": "01ae3adedf1f1cd5", "scanner": "scanner-primary", "fingerprint": "f38a49d6fcdfa931", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "fetch"]}}, {"ruleId": "scanner-f9510b91177d65de", "level": "note", "message": {"text": "Unused endpoint: PUT /settings/pixellab-api-key"}, "properties": {"repobilityId": "e78475a837672b2a", "scanner": "scanner-primary", "fingerprint": "f9510b91177d65de", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-c059f57186114027", "level": "note", "message": {"text": "Unused endpoint: POST /auth/logout"}, "properties": {"repobilityId": "3bc624261db2ed4a", "scanner": "scanner-primary", "fingerprint": "c059f57186114027", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-247fd8314d5d575f", "level": "note", "message": {"text": "Unused endpoint: PUT /settings/design"}, "properties": {"repobilityId": "a2406a8fe9b743f6", "scanner": "scanner-primary", "fingerprint": "247fd8314d5d575f", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-6a23aeabb1f0c4d3", "level": "note", "message": {"text": "Unused endpoint: PUT /notifications/read-all"}, "properties": {"repobilityId": "f1027041cf2c46c1", "scanner": "scanner-primary", "fingerprint": "6a23aeabb1f0c4d3", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-d153c42975584121", "level": "note", "message": {"text": "Unused endpoint: DELETE /notifications"}, "properties": {"repobilityId": "ab2891bb5f0e2a09", "scanner": "scanner-primary", "fingerprint": "d153c42975584121", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-684f0e83ba7e1558", "level": "note", "message": {"text": "Unused endpoint: GET "}, "properties": {"repobilityId": "0ee63926ebdf65dc", "scanner": "scanner-primary", "fingerprint": "684f0e83ba7e1558", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-193f390c75901c60", "level": "note", "message": {"text": "Unused endpoint: POST /setup/personalize"}, "properties": {"repobilityId": "5c1378f1ae1aeb89", "scanner": "scanner-primary", "fingerprint": "193f390c75901c60", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-9143464946a01de5", "level": "note", "message": {"text": "Unused endpoint: PUT /auth/profile"}, "properties": {"repobilityId": "2f49e93eef9c1cc9", "scanner": "scanner-primary", "fingerprint": "9143464946a01de5", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-4585c350da9e880d", "level": "note", "message": {"text": "Unused endpoint: POST /auth/change-password"}, "properties": {"repobilityId": "db20a9b3544e759d", "scanner": "scanner-primary", "fingerprint": "4585c350da9e880d", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-ababc57d7228b4f3", "level": "note", "message": {"text": "Unused endpoint: PUT /settings/general"}, "properties": {"repobilityId": "da5648e919019a95", "scanner": "scanner-primary", "fingerprint": "ababc57d7228b4f3", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-1cf2ed60cbbf2375", "level": "note", "message": {"text": "Unused endpoint: PUT /settings"}, "properties": {"repobilityId": "9167ecfe3ce876c7", "scanner": "scanner-primary", "fingerprint": "1cf2ed60cbbf2375", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-35064f229286d579", "level": "note", "message": {"text": "Unused endpoint: PUT /settings/models"}, "properties": {"repobilityId": "3d923a46995eddc0", "scanner": "scanner-primary", "fingerprint": "35064f229286d579", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-391fb7eb180ea08f", "level": "note", "message": {"text": "Unused endpoint: PUT /settings/api-key"}, "properties": {"repobilityId": "e144ecfda4ddb178", "scanner": "scanner-primary", "fingerprint": "391fb7eb180ea08f", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-34ba520914d95542", "level": "note", "message": {"text": "Unused endpoint: PUT /settings/security"}, "properties": {"repobilityId": "242a18e85ce51c2f", "scanner": "scanner-primary", "fingerprint": "34ba520914d95542", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-f7e43671782ea387", "level": "note", "message": {"text": "Unused endpoint: POST /system/update/apply"}, "properties": {"repobilityId": "b46326b789b39328", "scanner": "scanner-primary", "fingerprint": "f7e43671782ea387", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-a21c666784531829", "level": "note", "message": {"text": "Unused endpoint: POST /settings/backup/run"}, "properties": {"repobilityId": "91cf7d6e7d73af9d", "scanner": "scanner-primary", "fingerprint": "a21c666784531829", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-2f825e4e1d86d83c", "level": "note", "message": {"text": "Unused endpoint: DELETE /system/data"}, "properties": {"repobilityId": "20e78b732c25ce5c", "scanner": "scanner-primary", "fingerprint": "2f825e4e1d86d83c", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-2346b4b4a8d305f0", "level": "note", "message": {"text": "Unused endpoint: DELETE /auth/account"}, "properties": {"repobilityId": "33098f7708c511b9", "scanner": "scanner-primary", "fingerprint": "2346b4b4a8d305f0", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-1684892a9c1b4be5", "level": "note", "message": {"text": "Unused endpoint: POST /secrets"}, "properties": {"repobilityId": "69788437a36d26cb", "scanner": "scanner-primary", "fingerprint": "1684892a9c1b4be5", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-bb4497b3cab9fef5", "level": "note", "message": {"text": "Unused endpoint: POST /schedules"}, "properties": {"repobilityId": "5d896a0253598f6b", "scanner": "scanner-primary", "fingerprint": "bb4497b3cab9fef5", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}]}]}