{"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-bead75b0f9233e05", "name": "No API endpoints detected", "shortDescription": {"text": "No API endpoints detected"}, "fullDescription": {"text": "The scanner did not find FastAPI/Flask/Express/NestJS/GraphQL/gRPC routes. If this repo exposes APIs, the framework may be unsupported."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "info", "confidence": 1.0}}, {"id": "scanner-ecd5f6790c5a8ce8", "name": "Stray `console.log` in TS/JS \u2014 app/api/clients/business-card/upload/route.ts:76", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 app/api/clients/business-card/upload/route.ts:76"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-eec1792961d3a015", "name": "Stray `console.log` in TS/JS \u2014 app/api/samples/upload/route.ts:68", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 app/api/samples/upload/route.ts:68"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-da90a7885bb4c248", "name": "Stray `console.log` in TS/JS \u2014 app/api/documents/upload/route.ts:85", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 app/api/documents/upload/route.ts:85"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-b31403a85559fb5e", "name": "`truncate` class without `title=` for hover reveal \u2014 app/(app)/projects/[id]/page.tsx:72", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 app/(app)/projects/[id]/page.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-b5f768c8336a36ab", "name": "Stray `console.log` in TS/JS \u2014 scripts/inspect-sheets.ts:8", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/inspect-sheets.ts:8"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-6a0c3b3a4a367a59", "name": "Stray `console.log` in TS/JS \u2014 scripts/list-employees.ts:20", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/list-employees.ts:20"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-9481c459e7f12237", "name": "Stray `console.log` in TS/JS \u2014 scripts/verify-env.ts:45", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/verify-env.ts:45"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-23b09f89dd6f114a", "name": "Stray `console.log` in TS/JS \u2014 scripts/wipe-imported.ts:16", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/wipe-imported.ts:16"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-6c269b670cd5ff6a", "name": "Stray `console.log` in TS/JS \u2014 scripts/deactivate-employee.ts:36", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/deactivate-employee.ts:36"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-55e04a97bfaefe96", "name": "Stray `console.log` in TS/JS \u2014 scripts/smoke-test-resend-key.ts:39", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/smoke-test-resend-key.ts:39"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-f7e0236adefa6de0", "name": "Stray `console.log` in TS/JS \u2014 scripts/rename-employee.ts:43", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/rename-employee.ts:43"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-aa18ad5160461211", "name": "Stray `console.log` in TS/JS \u2014 scripts/seed-defaults.ts:53", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/seed-defaults.ts:53"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-7246d2a1658c9bb2", "name": "Stray `console.log` in TS/JS \u2014 scripts/delete-employee.ts:96", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/delete-employee.ts:96"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-1627d8b2a78f9a18", "name": "Stray `console.log` in TS/JS \u2014 scripts/sync-departments.ts:95", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/sync-departments.ts:95"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-ebd1cbd354e06894", "name": "Stray `console.log` in TS/JS \u2014 scripts/seed-demo.ts:4", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/seed-demo.ts:4"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-ea24090e858f373e", "name": "Stray `console.log` in TS/JS \u2014 scripts/seed-reset.ts:4", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/seed-reset.ts:4"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-9c894db93f2df42c", "name": "Stray `console.log` in TS/JS \u2014 scripts/import-legacy.ts:250", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/import-legacy.ts:250"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8a665b537f9887bc", "name": "Stray `console.log` in TS/JS \u2014 scripts/explain-hot-queries.ts:117", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/explain-hot-queries.ts:117"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-94d0248f2d12e1a8", "name": "Stray `console.log` in TS/JS \u2014 scripts/set-status-colors.ts:41", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/set-status-colors.ts:41"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-219b1cf6f5759ef3", "name": "Stray `console.log` in TS/JS \u2014 scripts/apply-migration.ts:15", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/apply-migration.ts:15"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-f2b57af6d2777f21", "name": "Stray `console.log` in TS/JS \u2014 scripts/seed.ts:8", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/seed.ts:8"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-dd1b646ff394f566", "name": "Stray `console.log` in TS/JS \u2014 scripts/demote-admins.ts:30", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/demote-admins.ts:30"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-405c2cfca8d86c7f", "name": "Stray `console.log` in TS/JS \u2014 scripts/apply-all-migrations.ts:117", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/apply-all-migrations.ts:117"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-f3d816e2f07f34ca", "name": "Stray `console.log` in TS/JS \u2014 scripts/bootstrap-admin.ts:61", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/bootstrap-admin.ts:61"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8a3c13ab0f1c950b", "name": "`truncate` class without `title=` for hover reveal \u2014 components/dashboard/status-distribution.tsx:221", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/dashboard/status-distribution.tsx:221"}, "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-b968b60a56a383f7", "name": "`truncate` class without `title=` for hover reveal \u2014 components/dashboard/aging-heatmap.tsx:377", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/dashboard/aging-heatmap.tsx:377"}, "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-3bd04abeb6388d02", "name": "`truncate` class without `title=` for hover reveal \u2014 components/dashboard/kpi-detail-panel.tsx:115", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/dashboard/kpi-detail-panel.tsx:115"}, "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-66cae8aa8926acc6", "name": "`truncate` class without `title=` for hover reveal \u2014 components/dashboard/top-performers.tsx:238", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/dashboard/top-performers.tsx:238"}, "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-c76cf3d6e352f4bf", "name": "`truncate` class without `title=` for hover reveal \u2014 components/inquiries/searchable-select.tsx:155", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/inquiries/searchable-select.tsx:155"}, "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-3207a2009b50699f", "name": "\"active\" state uses light bg in a dark theme \u2014 components/inquiries/form-field.tsx:153", "shortDescription": {"text": "\"active\" state uses light bg in a dark theme \u2014 components/inquiries/form-field.tsx:153"}, "fullDescription": {"text": "A ternary like `active ? 'bg-white' : '...'` (or bg-gray-100/200) on a dark theme produces jarring white pills. Use a dark-emphasized active state instead \u2014 border + ring or slightly brighter dark bg. Example: `active ? 'bg-gray-800 border-gray-500 ring-1 ring-blue-500/30' : '\u2026'`.\n\nWhy: P-E in CHECKLIST.md \u2014 light bg in a dark theme is a class of regression.\nRule id: fq.active-light-bg"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8590ddc13d23606d", "name": "`truncate` class without `title=` for hover reveal \u2014 components/admin/admin-sidebar.tsx:162", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/admin/admin-sidebar.tsx:162"}, "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-06f089bf4f24785e", "name": "`truncate` class without `title=` for hover reveal \u2014 components/admin/department-multi-select.tsx:74", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/admin/department-multi-select.tsx:74"}, "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-d6909469152dc1bf", "name": "`truncate` class without `title=` for hover reveal \u2014 components/admin/recent-dispatch-failures.tsx:102", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/admin/recent-dispatch-failures.tsx:102"}, "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-ca37a71a393e6143", "name": "`truncate` class without `title=` for hover reveal \u2014 components/admin/admin-mobile-bar.tsx:181", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/admin/admin-mobile-bar.tsx:181"}, "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-15ef141599620f07", "name": "`truncate` class without `title=` for hover reveal \u2014 components/admin/recurring-templates-list.tsx:58", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/admin/recurring-templates-list.tsx:58"}, "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-b07f7dd832353b81", "name": "`truncate` class without `title=` for hover reveal \u2014 components/admin/notification-list.tsx:96", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/admin/notification-list.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-8d58f70a0b8795b5", "name": "`truncate` class without `title=` for hover reveal \u2014 components/header/user-menu.tsx:157", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/header/user-menu.tsx:157"}, "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-e3e18e29a3affb2f", "name": "`truncate` class without `title=` for hover reveal \u2014 components/header/global-search.tsx:162", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/header/global-search.tsx:162"}, "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-2db55805043f0f4e", "name": "`truncate` class without `title=` for hover reveal \u2014 components/tasks/client-select.tsx:302", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/tasks/client-select.tsx:302"}, "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-d58b9e751fca1ea1", "name": "`truncate` class without `title=` for hover reveal \u2014 components/tasks/subject-select.tsx:291", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/tasks/subject-select.tsx:291"}, "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-1ba0973eeb4ba8cc", "name": "`truncate` class without `title=` for hover reveal \u2014 components/tasks/task-table.tsx:1304", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/tasks/task-table.tsx:1304"}, "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-508a1f3d3c2e95fc", "name": "`truncate` class without `title=` for hover reveal \u2014 components/tasks/new-task-form.tsx:1136", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/tasks/new-task-form.tsx:1136"}, "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-cbec923e242afa7a", "name": "`truncate` class without `title=` for hover reveal \u2014 components/tasks/task-import.tsx:406", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/tasks/task-import.tsx:406"}, "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-246cfae84d946a88", "name": "`truncate` class without `title=` for hover reveal \u2014 components/tasks/kanban-board.tsx:573", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/tasks/kanban-board.tsx:573"}, "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-dd15f615aa63a0e0", "name": "`truncate` class without `title=` for hover reveal \u2014 components/quotations/quotation-table.tsx:161", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/quotations/quotation-table.tsx:161"}, "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-73bfefcee104c088", "name": "`truncate` class without `title=` for hover reveal \u2014 components/samples/sample-detail.tsx:249", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/samples/sample-detail.tsx:249"}, "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-62da327765f1e2f7", "name": "`truncate` class without `title=` for hover reveal \u2014 components/projects/projects-workspace.tsx:1825", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/projects/projects-workspace.tsx:1825"}, "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-17a03591225e3618", "name": "`truncate` class without `title=` for hover reveal \u2014 components/sales-orders/so-table.tsx:152", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/sales-orders/so-table.tsx:152"}, "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-539c5eaac9293877", "name": "`truncate` class without `title=` for hover reveal \u2014 components/documents/document-library.tsx:221", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/documents/document-library.tsx:221"}, "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-97bbb31b848b2329", "name": "`truncate` class without `title=` for hover reveal \u2014 components/ui/multi-select.tsx:71", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/ui/multi-select.tsx:71"}, "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-869d2342567941c3", "name": "TODO/FIXME marker in shipping code \u2014 lib/achievements/evaluate.ts:135", "shortDescription": {"text": "TODO/FIXME marker in shipping code \u2014 lib/achievements/evaluate.ts:135"}, "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-815b6d8a5d460426", "name": "TODO/FIXME marker in shipping code \u2014 lib/profile/performance.ts:81", "shortDescription": {"text": "TODO/FIXME marker in shipping code \u2014 lib/profile/performance.ts:81"}, "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-c12de2c4dea32153", "name": "Very large file: app/(app)/tasks/actions.ts (1752 lines)", "shortDescription": {"text": "Very large file: app/(app)/tasks/actions.ts (1752 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-94084b90071a4042", "name": "Very large file: components/tasks/task-table.tsx (1372 lines)", "shortDescription": {"text": "Very large file: components/tasks/task-table.tsx (1372 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-86e4e2fa93b51e2c", "name": "Very large file: components/projects/projects-workspace.tsx (2238 lines)", "shortDescription": {"text": "Very large file: components/projects/projects-workspace.tsx (2238 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-ab56c90cc62bb816", "name": "Very large file: db/schema.ts (1312 lines)", "shortDescription": {"text": "Very large file: db/schema.ts (1312 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-ea3b5e389d8c9c0f", "name": "Low test-to-source ratio", "shortDescription": {"text": "Low test-to-source ratio"}, "fullDescription": {"text": "85 tests / 455 src (ratio 0.19)."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-141b30a41e03817b", "name": "No license file detected", "shortDescription": {"text": "No license file detected"}, "fullDescription": {"text": "No LICENSE/COPYING/NOTICE file was found. Generated repositories often omit licensing, which blocks reuse and automated intake."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-3ab5d313dda8e5f9", "name": "Debug logging residue appears in source files", "shortDescription": {"text": "Debug logging residue appears in source files"}, "fullDescription": {"text": "Found 124 console/debugger/print-style debug statements in non-test source. This is a common fast-generation residue before production cleanup."}, "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 192 placeholder/mock markers across 69 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 license. 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-9ad58f2880698b8f", "name": "Commented-code block (5 lines) in app/layout.tsx:33", "shortDescription": {"text": "Commented-code block (5 lines) in app/layout.tsx:33"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-de4943648ae365ef", "name": "Commented-code block (5 lines) in app/(admin)/admin/clients/actions.ts:26", "shortDescription": {"text": "Commented-code block (5 lines) in app/(admin)/admin/clients/actions.ts:26"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-8aa425e59dfb0f68", "name": "Commented-code block (6 lines) in app/(admin)/admin/employees/actions.ts:175", "shortDescription": {"text": "Commented-code block (6 lines) in app/(admin)/admin/employees/actions.ts:175"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-fd11fc20f2dfa8ae", "name": "Commented-code block (5 lines) in app/(app)/tasks/actions.ts:114", "shortDescription": {"text": "Commented-code block (5 lines) in app/(app)/tasks/actions.ts:114"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-59236b6229e411a6", "name": "Commented-code block (5 lines) in tests/unit/masters-actions.test.ts:6", "shortDescription": {"text": "Commented-code block (5 lines) in tests/unit/masters-actions.test.ts:6"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-4ada2affab0f6a94", "name": "Commented-code block (5 lines) in tests/unit/client-kyc-action.test.ts:5", "shortDescription": {"text": "Commented-code block (5 lines) in tests/unit/client-kyc-action.test.ts:5"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-a5b9462f68dddd7b", "name": "Commented-code block (5 lines) in tests/unit/sample-create-action.test.ts:5", "shortDescription": {"text": "Commented-code block (5 lines) in tests/unit/sample-create-action.test.ts:5"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-693cb363a329e959", "name": "Commented-code block (5 lines) in tests/unit/task-actions.test.ts:40", "shortDescription": {"text": "Commented-code block (5 lines) in tests/unit/task-actions.test.ts:40"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-aee622b1e226efd6", "name": "Commented-code block (5 lines) in tests/unit/invite-employee.test.ts:14", "shortDescription": {"text": "Commented-code block (5 lines) in tests/unit/invite-employee.test.ts:14"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-130cec8d60deb1e0", "name": "Commented-code block (12 lines) in scripts/seed-defaults.ts:7", "shortDescription": {"text": "Commented-code block (12 lines) in scripts/seed-defaults.ts:7"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-202f720002e1fdc8", "name": "Commented-code block (6 lines) in scripts/apply-all-migrations.ts:67", "shortDescription": {"text": "Commented-code block (6 lines) in scripts/apply-all-migrations.ts:67"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-b6dfb29eb9b266ac", "name": "Commented-code block (6 lines) in components/layout/filter-bar.tsx:121", "shortDescription": {"text": "Commented-code block (6 lines) in components/layout/filter-bar.tsx:121"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-59ae56ea1f304038", "name": "`fetch()` without try/.catch or AbortSignal \u2014 components/pwa/enable-push-button.tsx:63", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 components/pwa/enable-push-button.tsx:63"}, "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-d14a9e51dbfb9367", "name": "Commented-code block (6 lines) in components/tasks/audit-event.tsx:53", "shortDescription": {"text": "Commented-code block (6 lines) in components/tasks/audit-event.tsx:53"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-c6dc425aed61ceeb", "name": "Commented-code block (5 lines) in components/tasks/task-detail-loader.tsx:70", "shortDescription": {"text": "Commented-code block (5 lines) in components/tasks/task-detail-loader.tsx:70"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-b0cb22748886679c", "name": "Commented-code block (5 lines) in components/tasks/task-table.tsx:410", "shortDescription": {"text": "Commented-code block (5 lines) in components/tasks/task-table.tsx:410"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-f2ef17a6b0fff6c1", "name": "Commented-code block (5 lines) in components/ui/dropdown-menu.tsx:25", "shortDescription": {"text": "Commented-code block (5 lines) in components/ui/dropdown-menu.tsx:25"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-2e900bbbdbf1791b", "name": "Commented-code block (5 lines) in db/schema.ts:64", "shortDescription": {"text": "Commented-code block (5 lines) in db/schema.ts:64"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-4698413ff417d21a", "name": "Commented-code block (6 lines) in db/enums.ts:1", "shortDescription": {"text": "Commented-code block (6 lines) in db/enums.ts:1"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-f48cf0bb5b57ab30", "name": "Commented-code block (6 lines) in lib/task-late.ts:1", "shortDescription": {"text": "Commented-code block (6 lines) in lib/task-late.ts:1"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-3609fb6b2630a1d6", "name": "Commented-code block (5 lines) in lib/recurrence/rrule.ts:192", "shortDescription": {"text": "Commented-code block (5 lines) in lib/recurrence/rrule.ts:192"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-4ec4ce6a8dffd737", "name": "Commented-code block (6 lines) in lib/recurrence/materialize.ts:146", "shortDescription": {"text": "Commented-code block (6 lines) in lib/recurrence/materialize.ts:146"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-1294c3512c4b6b76", "name": "`fetch()` without try/.catch or AbortSignal \u2014 lib/google/calendar.ts:4", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/google/calendar.ts:4"}, "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-23b255d9e63390cd", "name": "Commented-code block (5 lines) in lib/email/resend.ts:27", "shortDescription": {"text": "Commented-code block (5 lines) in lib/email/resend.ts:27"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-8e0685ee0212099b", "name": "Commented-code block (5 lines) in lib/db/index.ts:19", "shortDescription": {"text": "Commented-code block (5 lines) in lib/db/index.ts:19"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-c3cd0f1608433ba2", "name": "Commented-code block (6 lines) in lib/notifications/dispatch.ts:147", "shortDescription": {"text": "Commented-code block (6 lines) in lib/notifications/dispatch.ts:147"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-5f660ddbf45353be", "name": "Commented-code block (5 lines) in lib/queries/notifications.ts:24", "shortDescription": {"text": "Commented-code block (5 lines) in lib/queries/notifications.ts:24"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-7ce9d98ebd2ae926", "name": "Commented-code block (5 lines) in lib/queries/status-display.ts:16", "shortDescription": {"text": "Commented-code block (5 lines) in lib/queries/status-display.ts:16"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-68eb503d73389ca2", "name": "Commented-code block (5 lines) in lib/queries/tasks.ts:13", "shortDescription": {"text": "Commented-code block (5 lines) in lib/queries/tasks.ts:13"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-b0b5e7cb1208a7cd", "name": "13 env vars used in code but missing from .env.example", "shortDescription": {"text": "13 env vars used in code but missing from .env.example"}, "fullDescription": {"text": "Drift between code and config docs. The first few: `CI`, `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET`, `NEXT_PUBLIC_SENTRY_ENABLE_DEV`, `NEXT_PUBLIC_SENTRY_ENABLE_REPLAY`, `NEXT_PUBLIC_SENTRY_TRACES_SAMPLE_RATE`, `NEXT_PUBLIC_VERCEL_ENV`, `NEXT_RUNTIME` + 5 more. Add them (with a placeholder/comment) to .env.example so onboarding doesn't break."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}]}}, "automationDetails": {"id": "repobility/24828"}, "properties": {"repository": "carbide-india/carbideindia", "repoUrl": "https://github.com/carbide-india/carbideindia", "branch": "main"}, "results": [{"ruleId": "scanner-bead75b0f9233e05", "level": "none", "message": {"text": "No API endpoints detected"}, "properties": {"repobilityId": "0f8bb852027c38f8", "scanner": "scanner-primary", "fingerprint": "bead75b0f9233e05", "layer": "api", "severity": "info", "confidence": 1.0, "tags": ["coverage"]}}, {"ruleId": "scanner-ecd5f6790c5a8ce8", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 app/api/clients/business-card/upload/route.ts:76"}, "properties": {"repobilityId": "1a854a9ad714e135", "scanner": "scanner-primary", "fingerprint": "ecd5f6790c5a8ce8", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-eec1792961d3a015", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 app/api/samples/upload/route.ts:68"}, "properties": {"repobilityId": "dfba8556472ef109", "scanner": "scanner-primary", "fingerprint": "eec1792961d3a015", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-da90a7885bb4c248", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 app/api/documents/upload/route.ts:85"}, "properties": {"repobilityId": "0d96fc81712dcd2e", "scanner": "scanner-primary", "fingerprint": "da90a7885bb4c248", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-b31403a85559fb5e", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 app/(app)/projects/[id]/page.tsx:72"}, "properties": {"repobilityId": "126ff163cade3c00", "scanner": "scanner-primary", "fingerprint": "b31403a85559fb5e", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-b5f768c8336a36ab", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/inspect-sheets.ts:8"}, "properties": {"repobilityId": "b90982776fd5e689", "scanner": "scanner-primary", "fingerprint": "b5f768c8336a36ab", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-6a0c3b3a4a367a59", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/list-employees.ts:20"}, "properties": {"repobilityId": "1de3e11b62673061", "scanner": "scanner-primary", "fingerprint": "6a0c3b3a4a367a59", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-9481c459e7f12237", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/verify-env.ts:45"}, "properties": {"repobilityId": "628f1deacc3a2e26", "scanner": "scanner-primary", "fingerprint": "9481c459e7f12237", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-23b09f89dd6f114a", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/wipe-imported.ts:16"}, "properties": {"repobilityId": "d62705f336b9bc09", "scanner": "scanner-primary", "fingerprint": "23b09f89dd6f114a", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-6c269b670cd5ff6a", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/deactivate-employee.ts:36"}, "properties": {"repobilityId": "55c7404a15490c8e", "scanner": "scanner-primary", "fingerprint": "6c269b670cd5ff6a", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-55e04a97bfaefe96", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/smoke-test-resend-key.ts:39"}, "properties": {"repobilityId": "d084fd4a2b250c8f", "scanner": "scanner-primary", "fingerprint": "55e04a97bfaefe96", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-f7e0236adefa6de0", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/rename-employee.ts:43"}, "properties": {"repobilityId": "b90de1501107f275", "scanner": "scanner-primary", "fingerprint": "f7e0236adefa6de0", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-aa18ad5160461211", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/seed-defaults.ts:53"}, "properties": {"repobilityId": "5cfc8afa53f4b0dc", "scanner": "scanner-primary", "fingerprint": "aa18ad5160461211", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-7246d2a1658c9bb2", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/delete-employee.ts:96"}, "properties": {"repobilityId": "4bdeb0083ad51f14", "scanner": "scanner-primary", "fingerprint": "7246d2a1658c9bb2", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-1627d8b2a78f9a18", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/sync-departments.ts:95"}, "properties": {"repobilityId": "d31661aa36234836", "scanner": "scanner-primary", "fingerprint": "1627d8b2a78f9a18", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-ebd1cbd354e06894", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/seed-demo.ts:4"}, "properties": {"repobilityId": "b7f1ec3c1a06f2fb", "scanner": "scanner-primary", "fingerprint": "ebd1cbd354e06894", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-ea24090e858f373e", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/seed-reset.ts:4"}, "properties": {"repobilityId": "798f20cc56889f31", "scanner": "scanner-primary", "fingerprint": "ea24090e858f373e", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-9c894db93f2df42c", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/import-legacy.ts:250"}, "properties": {"repobilityId": "44a51e9cd1d5910e", "scanner": "scanner-primary", "fingerprint": "9c894db93f2df42c", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-8a665b537f9887bc", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/explain-hot-queries.ts:117"}, "properties": {"repobilityId": "18e83ca13d1c342b", "scanner": "scanner-primary", "fingerprint": "8a665b537f9887bc", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-94d0248f2d12e1a8", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/set-status-colors.ts:41"}, "properties": {"repobilityId": "0dcdc165081255e0", "scanner": "scanner-primary", "fingerprint": "94d0248f2d12e1a8", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-219b1cf6f5759ef3", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/apply-migration.ts:15"}, "properties": {"repobilityId": "dbfa6d77b7cd79db", "scanner": "scanner-primary", "fingerprint": "219b1cf6f5759ef3", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-f2b57af6d2777f21", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/seed.ts:8"}, "properties": {"repobilityId": "6b45b8d4fff61a2c", "scanner": "scanner-primary", "fingerprint": "f2b57af6d2777f21", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-dd1b646ff394f566", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/demote-admins.ts:30"}, "properties": {"repobilityId": "cd30f233a0c12f0f", "scanner": "scanner-primary", "fingerprint": "dd1b646ff394f566", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-405c2cfca8d86c7f", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/apply-all-migrations.ts:117"}, "properties": {"repobilityId": "5e73a9872d542556", "scanner": "scanner-primary", "fingerprint": "405c2cfca8d86c7f", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-f3d816e2f07f34ca", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/bootstrap-admin.ts:61"}, "properties": {"repobilityId": "bfdcced7cb923518", "scanner": "scanner-primary", "fingerprint": "f3d816e2f07f34ca", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-8a3c13ab0f1c950b", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/dashboard/status-distribution.tsx:221"}, "properties": {"repobilityId": "8f600420df5ce862", "scanner": "scanner-primary", "fingerprint": "8a3c13ab0f1c950b", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-b968b60a56a383f7", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/dashboard/aging-heatmap.tsx:377"}, "properties": {"repobilityId": "9fa4b4b52b359bf4", "scanner": "scanner-primary", "fingerprint": "b968b60a56a383f7", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-3bd04abeb6388d02", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/dashboard/kpi-detail-panel.tsx:115"}, "properties": {"repobilityId": "b28a39d10b8d5f27", "scanner": "scanner-primary", "fingerprint": "3bd04abeb6388d02", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-66cae8aa8926acc6", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/dashboard/top-performers.tsx:238"}, "properties": {"repobilityId": "1ce4d96bccebeebf", "scanner": "scanner-primary", "fingerprint": "66cae8aa8926acc6", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-c76cf3d6e352f4bf", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/inquiries/searchable-select.tsx:155"}, "properties": {"repobilityId": "98fcc14294cab611", "scanner": "scanner-primary", "fingerprint": "c76cf3d6e352f4bf", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-3207a2009b50699f", "level": "note", "message": {"text": "\"active\" state uses light bg in a dark theme \u2014 components/inquiries/form-field.tsx:153"}, "properties": {"repobilityId": "f48bbd7fe275cd78", "scanner": "scanner-primary", "fingerprint": "3207a2009b50699f", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.active-light-bg"]}}, {"ruleId": "scanner-8590ddc13d23606d", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/admin/admin-sidebar.tsx:162"}, "properties": {"repobilityId": "514b99546930ddb3", "scanner": "scanner-primary", "fingerprint": "8590ddc13d23606d", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-06f089bf4f24785e", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/admin/department-multi-select.tsx:74"}, "properties": {"repobilityId": "d9d16d76f010fcc1", "scanner": "scanner-primary", "fingerprint": "06f089bf4f24785e", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-d6909469152dc1bf", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/admin/recent-dispatch-failures.tsx:102"}, "properties": {"repobilityId": "7c7e4ccf237902ca", "scanner": "scanner-primary", "fingerprint": "d6909469152dc1bf", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-ca37a71a393e6143", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/admin/admin-mobile-bar.tsx:181"}, "properties": {"repobilityId": "707760e40a378a19", "scanner": "scanner-primary", "fingerprint": "ca37a71a393e6143", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-15ef141599620f07", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/admin/recurring-templates-list.tsx:58"}, "properties": {"repobilityId": "afcac80f36bef9df", "scanner": "scanner-primary", "fingerprint": "15ef141599620f07", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-b07f7dd832353b81", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/admin/notification-list.tsx:96"}, "properties": {"repobilityId": "e2a1627f9ab0d021", "scanner": "scanner-primary", "fingerprint": "b07f7dd832353b81", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-8d58f70a0b8795b5", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/header/user-menu.tsx:157"}, "properties": {"repobilityId": "070ab925fe8c66d9", "scanner": "scanner-primary", "fingerprint": "8d58f70a0b8795b5", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-e3e18e29a3affb2f", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/header/global-search.tsx:162"}, "properties": {"repobilityId": "2fedc2e283b8993a", "scanner": "scanner-primary", "fingerprint": "e3e18e29a3affb2f", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-2db55805043f0f4e", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/tasks/client-select.tsx:302"}, "properties": {"repobilityId": "0351d96ebd110855", "scanner": "scanner-primary", "fingerprint": "2db55805043f0f4e", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-d58b9e751fca1ea1", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/tasks/subject-select.tsx:291"}, "properties": {"repobilityId": "e89e48f422564bac", "scanner": "scanner-primary", "fingerprint": "d58b9e751fca1ea1", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-1ba0973eeb4ba8cc", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/tasks/task-table.tsx:1304"}, "properties": {"repobilityId": "316503131083c56d", "scanner": "scanner-primary", "fingerprint": "1ba0973eeb4ba8cc", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-508a1f3d3c2e95fc", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/tasks/new-task-form.tsx:1136"}, "properties": {"repobilityId": "8a0c4b858406fff0", "scanner": "scanner-primary", "fingerprint": "508a1f3d3c2e95fc", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-cbec923e242afa7a", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/tasks/task-import.tsx:406"}, "properties": {"repobilityId": "436e54bedee2699c", "scanner": "scanner-primary", "fingerprint": "cbec923e242afa7a", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-246cfae84d946a88", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/tasks/kanban-board.tsx:573"}, "properties": {"repobilityId": "8cca3294b003ee51", "scanner": "scanner-primary", "fingerprint": "246cfae84d946a88", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-dd15f615aa63a0e0", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/quotations/quotation-table.tsx:161"}, "properties": {"repobilityId": "25ba01494bd42e32", "scanner": "scanner-primary", "fingerprint": "dd15f615aa63a0e0", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-73bfefcee104c088", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/samples/sample-detail.tsx:249"}, "properties": {"repobilityId": "e36ce181aa0785cf", "scanner": "scanner-primary", "fingerprint": "73bfefcee104c088", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-62da327765f1e2f7", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/projects/projects-workspace.tsx:1825"}, "properties": {"repobilityId": "5e78636eb921eabb", "scanner": "scanner-primary", "fingerprint": "62da327765f1e2f7", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-17a03591225e3618", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/sales-orders/so-table.tsx:152"}, "properties": {"repobilityId": "acb9fedd0d073db1", "scanner": "scanner-primary", "fingerprint": "17a03591225e3618", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-539c5eaac9293877", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/documents/document-library.tsx:221"}, "properties": {"repobilityId": "eadc52f7aad45f1f", "scanner": "scanner-primary", "fingerprint": "539c5eaac9293877", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-97bbb31b848b2329", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 components/ui/multi-select.tsx:71"}, "properties": {"repobilityId": "955e8c56146ebb79", "scanner": "scanner-primary", "fingerprint": "97bbb31b848b2329", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-869d2342567941c3", "level": "none", "message": {"text": "TODO/FIXME marker in shipping code \u2014 lib/achievements/evaluate.ts:135"}, "properties": {"repobilityId": "38629c192768571d", "scanner": "scanner-primary", "fingerprint": "869d2342567941c3", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.todo-marker"]}}, {"ruleId": "scanner-815b6d8a5d460426", "level": "none", "message": {"text": "TODO/FIXME marker in shipping code \u2014 lib/profile/performance.ts:81"}, "properties": {"repobilityId": "5a19c8dcadcdf799", "scanner": "scanner-primary", "fingerprint": "815b6d8a5d460426", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.todo-marker"]}}, {"ruleId": "scanner-c12de2c4dea32153", "level": "note", "message": {"text": "Very large file: app/(app)/tasks/actions.ts (1752 lines)"}, "properties": {"repobilityId": "7c8fbf00184921a5", "scanner": "scanner-primary", "fingerprint": "c12de2c4dea32153", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-94084b90071a4042", "level": "note", "message": {"text": "Very large file: components/tasks/task-table.tsx (1372 lines)"}, "properties": {"repobilityId": "4d17745ab2356963", "scanner": "scanner-primary", "fingerprint": "94084b90071a4042", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-86e4e2fa93b51e2c", "level": "note", "message": {"text": "Very large file: components/projects/projects-workspace.tsx (2238 lines)"}, "properties": {"repobilityId": "68b50eb381455eed", "scanner": "scanner-primary", "fingerprint": "86e4e2fa93b51e2c", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-ab56c90cc62bb816", "level": "note", "message": {"text": "Very large file: db/schema.ts (1312 lines)"}, "properties": {"repobilityId": "cf492ebfbadbac76", "scanner": "scanner-primary", "fingerprint": "ab56c90cc62bb816", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-ea3b5e389d8c9c0f", "level": "note", "message": {"text": "Low test-to-source ratio"}, "properties": {"repobilityId": "ef7b2552cc00a375", "scanner": "scanner-primary", "fingerprint": "ea3b5e389d8c9c0f", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["tests"]}}, {"ruleId": "scanner-141b30a41e03817b", "level": "note", "message": {"text": "No license file detected"}, "properties": {"repobilityId": "97c3fb0f5f8fccc6", "scanner": "scanner-primary", "fingerprint": "141b30a41e03817b", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["license", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-3ab5d313dda8e5f9", "level": "note", "message": {"text": "Debug logging residue appears in source files"}, "properties": {"repobilityId": "7b6e8884e463d439", "scanner": "scanner-primary", "fingerprint": "3ab5d313dda8e5f9", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["debug", "cleanup", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-72b2a6250083a784", "level": "warning", "message": {"text": "Placeholder or mock-heavy implementation detected"}, "properties": {"repobilityId": "e47338a2058989cf", "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": "1d15ec3c643008ff", "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": "95c6356d9c0dc09b", "scanner": "scanner-primary", "fingerprint": "749d4bc1bd66df5f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-9ad58f2880698b8f", "level": "none", "message": {"text": "Commented-code block (5 lines) in app/layout.tsx:33"}, "properties": {"repobilityId": "a6f50f2cfebb30d7", "scanner": "scanner-primary", "fingerprint": "9ad58f2880698b8f", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-de4943648ae365ef", "level": "none", "message": {"text": "Commented-code block (5 lines) in app/(admin)/admin/clients/actions.ts:26"}, "properties": {"repobilityId": "5ef047e3c3a246f3", "scanner": "scanner-primary", "fingerprint": "de4943648ae365ef", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-8aa425e59dfb0f68", "level": "none", "message": {"text": "Commented-code block (6 lines) in app/(admin)/admin/employees/actions.ts:175"}, "properties": {"repobilityId": "549be6a83bce2d29", "scanner": "scanner-primary", "fingerprint": "8aa425e59dfb0f68", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-fd11fc20f2dfa8ae", "level": "none", "message": {"text": "Commented-code block (5 lines) in app/(app)/tasks/actions.ts:114"}, "properties": {"repobilityId": "77a183b50bf0c165", "scanner": "scanner-primary", "fingerprint": "fd11fc20f2dfa8ae", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-59236b6229e411a6", "level": "none", "message": {"text": "Commented-code block (5 lines) in tests/unit/masters-actions.test.ts:6"}, "properties": {"repobilityId": "a462ed55455ecf3c", "scanner": "scanner-primary", "fingerprint": "59236b6229e411a6", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-4ada2affab0f6a94", "level": "none", "message": {"text": "Commented-code block (5 lines) in tests/unit/client-kyc-action.test.ts:5"}, "properties": {"repobilityId": "b38f84ad5a4e4c1f", "scanner": "scanner-primary", "fingerprint": "4ada2affab0f6a94", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-a5b9462f68dddd7b", "level": "none", "message": {"text": "Commented-code block (5 lines) in tests/unit/sample-create-action.test.ts:5"}, "properties": {"repobilityId": "38634898d1ff088d", "scanner": "scanner-primary", "fingerprint": "a5b9462f68dddd7b", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-693cb363a329e959", "level": "none", "message": {"text": "Commented-code block (5 lines) in tests/unit/task-actions.test.ts:40"}, "properties": {"repobilityId": "5968e1685f78240b", "scanner": "scanner-primary", "fingerprint": "693cb363a329e959", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-aee622b1e226efd6", "level": "none", "message": {"text": "Commented-code block (5 lines) in tests/unit/invite-employee.test.ts:14"}, "properties": {"repobilityId": "d0e899c19e472eae", "scanner": "scanner-primary", "fingerprint": "aee622b1e226efd6", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-130cec8d60deb1e0", "level": "none", "message": {"text": "Commented-code block (12 lines) in scripts/seed-defaults.ts:7"}, "properties": {"repobilityId": "5bafa345a109c246", "scanner": "scanner-primary", "fingerprint": "130cec8d60deb1e0", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-202f720002e1fdc8", "level": "none", "message": {"text": "Commented-code block (6 lines) in scripts/apply-all-migrations.ts:67"}, "properties": {"repobilityId": "6a968ad6d97a7147", "scanner": "scanner-primary", "fingerprint": "202f720002e1fdc8", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-b6dfb29eb9b266ac", "level": "none", "message": {"text": "Commented-code block (6 lines) in components/layout/filter-bar.tsx:121"}, "properties": {"repobilityId": "0d707c829b24438a", "scanner": "scanner-primary", "fingerprint": "b6dfb29eb9b266ac", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-59ae56ea1f304038", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 components/pwa/enable-push-button.tsx:63"}, "properties": {"repobilityId": "3bd4c0036bb29f57", "scanner": "scanner-primary", "fingerprint": "59ae56ea1f304038", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-d14a9e51dbfb9367", "level": "none", "message": {"text": "Commented-code block (6 lines) in components/tasks/audit-event.tsx:53"}, "properties": {"repobilityId": "509b545399a839ac", "scanner": "scanner-primary", "fingerprint": "d14a9e51dbfb9367", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-c6dc425aed61ceeb", "level": "none", "message": {"text": "Commented-code block (5 lines) in components/tasks/task-detail-loader.tsx:70"}, "properties": {"repobilityId": "c1453484defe21ae", "scanner": "scanner-primary", "fingerprint": "c6dc425aed61ceeb", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-b0cb22748886679c", "level": "none", "message": {"text": "Commented-code block (5 lines) in components/tasks/task-table.tsx:410"}, "properties": {"repobilityId": "bfb7b386f225a03f", "scanner": "scanner-primary", "fingerprint": "b0cb22748886679c", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-f2ef17a6b0fff6c1", "level": "none", "message": {"text": "Commented-code block (5 lines) in components/ui/dropdown-menu.tsx:25"}, "properties": {"repobilityId": "168d83b835ef1c49", "scanner": "scanner-primary", "fingerprint": "f2ef17a6b0fff6c1", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-2e900bbbdbf1791b", "level": "none", "message": {"text": "Commented-code block (5 lines) in db/schema.ts:64"}, "properties": {"repobilityId": "10aa4e1441a67fb2", "scanner": "scanner-primary", "fingerprint": "2e900bbbdbf1791b", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-4698413ff417d21a", "level": "none", "message": {"text": "Commented-code block (6 lines) in db/enums.ts:1"}, "properties": {"repobilityId": "97928dcaa00031ff", "scanner": "scanner-primary", "fingerprint": "4698413ff417d21a", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-f48cf0bb5b57ab30", "level": "none", "message": {"text": "Commented-code block (6 lines) in lib/task-late.ts:1"}, "properties": {"repobilityId": "d30e8edd917094ca", "scanner": "scanner-primary", "fingerprint": "f48cf0bb5b57ab30", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-3609fb6b2630a1d6", "level": "none", "message": {"text": "Commented-code block (5 lines) in lib/recurrence/rrule.ts:192"}, "properties": {"repobilityId": "ed4c68ed5c418fa5", "scanner": "scanner-primary", "fingerprint": "3609fb6b2630a1d6", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-4ec4ce6a8dffd737", "level": "none", "message": {"text": "Commented-code block (6 lines) in lib/recurrence/materialize.ts:146"}, "properties": {"repobilityId": "90685a6e4b2d67d8", "scanner": "scanner-primary", "fingerprint": "4ec4ce6a8dffd737", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-1294c3512c4b6b76", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/google/calendar.ts:4"}, "properties": {"repobilityId": "6a5e46980e023bd6", "scanner": "scanner-primary", "fingerprint": "1294c3512c4b6b76", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-23b255d9e63390cd", "level": "none", "message": {"text": "Commented-code block (5 lines) in lib/email/resend.ts:27"}, "properties": {"repobilityId": "930a327bd835e404", "scanner": "scanner-primary", "fingerprint": "23b255d9e63390cd", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-8e0685ee0212099b", "level": "none", "message": {"text": "Commented-code block (5 lines) in lib/db/index.ts:19"}, "properties": {"repobilityId": "028e9ef95a88e502", "scanner": "scanner-primary", "fingerprint": "8e0685ee0212099b", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-c3cd0f1608433ba2", "level": "none", "message": {"text": "Commented-code block (6 lines) in lib/notifications/dispatch.ts:147"}, "properties": {"repobilityId": "49fd940336d256b3", "scanner": "scanner-primary", "fingerprint": "c3cd0f1608433ba2", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-5f660ddbf45353be", "level": "none", "message": {"text": "Commented-code block (5 lines) in lib/queries/notifications.ts:24"}, "properties": {"repobilityId": "429a6c8512e9b166", "scanner": "scanner-primary", "fingerprint": "5f660ddbf45353be", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-7ce9d98ebd2ae926", "level": "none", "message": {"text": "Commented-code block (5 lines) in lib/queries/status-display.ts:16"}, "properties": {"repobilityId": "19218723cacba9e8", "scanner": "scanner-primary", "fingerprint": "7ce9d98ebd2ae926", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-68eb503d73389ca2", "level": "none", "message": {"text": "Commented-code block (5 lines) in lib/queries/tasks.ts:13"}, "properties": {"repobilityId": "e65b30a624bad4d1", "scanner": "scanner-primary", "fingerprint": "68eb503d73389ca2", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-b0b5e7cb1208a7cd", "level": "note", "message": {"text": "13 env vars used in code but missing from .env.example"}, "properties": {"repobilityId": "2737b8666c1f7eeb", "scanner": "scanner-primary", "fingerprint": "b0b5e7cb1208a7cd", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "config-drift"]}}]}]}