{"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-87654f1be0fd14f8", "name": "Stray `console.log` in TS/JS \u2014 apps/web/scripts/generate-font-sprites.ts:64", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 apps/web/scripts/generate-font-sprites.ts:64"}, "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-9248ec3d39f12272", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/dub/components/dub-view.tsx:438", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/dub/components/dub-view.tsx:438"}, "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-4db58155a49ccc2a", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/dub/components/voice-picker.tsx:138", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/dub/components/voice-picker.tsx:138"}, "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-c3b44d41557d3a1b", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/dub/course/components/import-course.tsx:228", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/dub/course/components/import-course.tsx:228"}, "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-bc3a7b007827422b", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/dub/course/components/export-button.tsx:142", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/dub/course/components/export-button.tsx:142"}, "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-9a7c9a50e07787f2", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/dub/course/components/batch-center.tsx:125", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/dub/course/components/batch-center.tsx:125"}, "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-24c788882c85c226", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/timeline/components/timeline-element.tsx:911", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/timeline/components/timeline-element.tsx:911"}, "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-3f3ad634be070b82", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/timeline/components/index.tsx:946", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/timeline/components/index.tsx:946"}, "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-27e27e2888b4e9d8", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/components/ui/font-picker.tsx:100", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/components/ui/font-picker.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-e24faea712a0b8bd", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/components/landing/hero.tsx:407", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/components/landing/hero.tsx:407"}, "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-5e6d9149966e17b4", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/components/editor/panels/assets/draggable-item.tsx:161", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/components/editor/panels/assets/draggable-item.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-39961ced6b46071b", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/components/editor/panels/assets/views/settings/index.t", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/components/editor/panels/assets/views/settings/index.tsx:236"}, "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-886bb86d72b0becd", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 apps/web/src/app/page.tsx:85", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 apps/web/src/app/page.tsx:85"}, "fullDescription": {"text": "Open XSS surface unless the input is provably trusted. Replace with explicit JSX or sanitize via a vetted library.\n\nWhy: OWASP basics. Already partially flagged by the security analyzer.\nRule id: fq.dangerous-html"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-8b3d8d736a229e9d", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/app/projects/page.tsx:747", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/app/projects/page.tsx:747"}, "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-37099448a718b809", "name": "Stray `console.log` in TS/JS \u2014 apps/web/src/lib/analytics.ts:39", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 apps/web/src/lib/analytics.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-8b91d965f2bbd1b0", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/sounds/components/assets-view.tsx:527", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/sounds/components/assets-view.tsx:527"}, "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-f36282140a074635", "name": "Stray `console.log` in TS/JS \u2014 apps/web/src/services/transcription/worker.ts:120", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 apps/web/src/services/transcription/worker.ts:120"}, "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-3ec5b19ea2a521be", "name": "TODO/FIXME marker in shipping code \u2014 apps/web/src/actions/use-editor-actions.ts:496", "shortDescription": {"text": "TODO/FIXME marker in shipping code \u2014 apps/web/src/actions/use-editor-actions.ts:496"}, "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-8469e41a801a6954", "name": "TODO/FIXME marker in shipping code \u2014 apps/web/src/guides/registry.tsx:20", "shortDescription": {"text": "TODO/FIXME marker in shipping code \u2014 apps/web/src/guides/registry.tsx:20"}, "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-3942e3b6ee1d7164", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/project/components/project-info-dialog.tsx:48", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/project/components/project-info-dialog.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-16571cd32c60e2d5", "name": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/project/components/delete-project-dialog.tsx:42", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/project/components/delete-project-dialog.tsx:42"}, "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-0ed57e814e5be16d", "name": "Docker base image is tag-pinned but not digest-pinned: oven/bun:alpine", "shortDescription": {"text": "Docker base image is tag-pinned but not digest-pinned: oven/bun:alpine"}, "fullDescription": {"text": "Container tags can be retagged upstream. Pin production base images to a reviewed digest (`image@sha256:...`) when reproducibility and supply-chain integrity matter."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "low", "confidence": 1.0}}, {"id": "scanner-aa5acaa49eb8315b", "name": "Containers defined but no K8s/orchestration manifest found", "shortDescription": {"text": "Containers defined but no K8s/orchestration manifest found"}, "fullDescription": {"text": "Repo has Dockerfiles/compose but no Kubernetes/Nomad manifests. If the target deployment is K8s, the manifests may live in a separate ops repo."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "low", "confidence": 1.0}}, {"id": "scanner-30a2a5fcbd5e8957", "name": "Insecure pattern 'node_child_process' in apps/web/src/dub/course/link/server/bin.ts:5", "shortDescription": {"text": "Insecure pattern 'node_child_process' in apps/web/src/dub/course/link/server/bin.ts:5"}, "fullDescription": {"text": "Found a known-risky pattern (node_child_process). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-07b2b7847cb7cab3", "name": "Insecure pattern 'eval_used' in apps/web/src/utils/__tests__/math.test.ts:108", "shortDescription": {"text": "Insecure pattern 'eval_used' in apps/web/src/utils/__tests__/math.test.ts:108"}, "fullDescription": {"text": "Found a known-risky pattern (eval_used). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-e076ab009c3dec9f", "name": "Insecure pattern 'dangerous_innerhtml' in apps/web/src/app/page.tsx:85", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in apps/web/src/app/page.tsx:85"}, "fullDescription": {"text": "Found a known-risky pattern (dangerous_innerhtml). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-27924aa79fa4a517", "name": "GitHub Action is tag-pinned rather than SHA-pinned", "shortDescription": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "fullDescription": {"text": "actions/cache@v4 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": "low", "confidence": 1.0}}, {"id": "scanner-6893a6c8b0861585", "name": "Very low test-to-source ratio", "shortDescription": {"text": "Very low test-to-source ratio"}, "fullDescription": {"text": "52 test file(s) for 711 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-4a9eb7dc7c6e3880", "name": "Node manifest has dependencies but no lockfile: apps/web/package.json", "shortDescription": {"text": "Node manifest has dependencies but no lockfile: apps/web/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-3ab5d313dda8e5f9", "name": "Debug logging residue appears in source files", "shortDescription": {"text": "Debug logging residue appears in source files"}, "fullDescription": {"text": "Found 15 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 31 placeholder/mock markers across 23 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-49c68efa71eff82a", "name": "Commented-code block (5 lines) in eslint.config.mjs:87", "shortDescription": {"text": "Commented-code block (5 lines) in eslint.config.mjs:87"}, "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-eca967f972b34146", "name": "Commented-code block (6 lines) in eslint/rules/prefer-object-params.mjs:31", "shortDescription": {"text": "Commented-code block (6 lines) in eslint/rules/prefer-object-params.mjs:31"}, "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-01c8178581858854", "name": "Commented-code block (6 lines) in eslint/rules/__tests__/prefer-object-params.test.mjs:96", "shortDescription": {"text": "Commented-code block (6 lines) in eslint/rules/__tests__/prefer-object-params.test.mjs:96"}, "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-bce0539aa0515bcc", "name": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/scripts/generate-font-sprites.ts:65", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/scripts/generate-font-sprites.ts:65"}, "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-0f21ccbb036b2b66", "name": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/src/media/audio.ts:235", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/src/media/audio.ts:235"}, "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-e9b08afec2cdeb35", "name": "Commented-code block (5 lines) in apps/web/src/commands/timeline/element/split-elements.ts:94", "shortDescription": {"text": "Commented-code block (5 lines) in apps/web/src/commands/timeline/element/split-elements.ts:94"}, "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-e19febe470b5ed59", "name": "Commented-code block (5 lines) in apps/web/src/dub/original-audio.ts:1", "shortDescription": {"text": "Commented-code block (5 lines) in apps/web/src/dub/original-audio.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-bb6e81e01c59f9ff", "name": "Commented-code block (7 lines) in apps/web/src/dub/units.ts:1", "shortDescription": {"text": "Commented-code block (7 lines) in apps/web/src/dub/units.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-1aa66b7a33b7dabe", "name": "Commented-code block (6 lines) in apps/web/src/dub/custom-voices.ts:6", "shortDescription": {"text": "Commented-code block (6 lines) in apps/web/src/dub/custom-voices.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-7140fadaef960330", "name": "Commented-code block (5 lines) in apps/web/src/dub/adapter.ts:159", "shortDescription": {"text": "Commented-code block (5 lines) in apps/web/src/dub/adapter.ts:159"}, "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-5e26294357adb003", "name": "Commented-code block (5 lines) in apps/web/src/dub/voice-lang-check.ts:5", "shortDescription": {"text": "Commented-code block (5 lines) in apps/web/src/dub/voice-lang-check.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-b378f2d29eb3640f", "name": "Commented-code block (5 lines) in apps/web/src/dub/sanitize.ts:1", "shortDescription": {"text": "Commented-code block (5 lines) in apps/web/src/dub/sanitize.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-1811ec8e419d8088", "name": "Commented-code block (5 lines) in apps/web/src/dub/subtitle-split.ts:1", "shortDescription": {"text": "Commented-code block (5 lines) in apps/web/src/dub/subtitle-split.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-ab7e2cceab6b6a6e", "name": "Commented-code block (5 lines) in apps/web/src/dub/components/dub-view.tsx:813", "shortDescription": {"text": "Commented-code block (5 lines) in apps/web/src/dub/components/dub-view.tsx:813"}, "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-c40b3f8c95dfcc67", "name": "Commented-code block (5 lines) in apps/web/src/dub/course/export-batch.ts:1", "shortDescription": {"text": "Commented-code block (5 lines) in apps/web/src/dub/course/export-batch.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-c7eb05cb62a53217", "name": "Commented-code block (5 lines) in apps/web/src/dub/course/idb.ts:1", "shortDescription": {"text": "Commented-code block (5 lines) in apps/web/src/dub/course/idb.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-93c8678d93a8f4b2", "name": "Commented-code block (5 lines) in apps/web/src/dub/course/zip.ts:1", "shortDescription": {"text": "Commented-code block (5 lines) in apps/web/src/dub/course/zip.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-3e76b58bc716fe9b", "name": "Commented-code block (7 lines) in apps/web/src/dub/course/components/course-overlay.tsx:3", "shortDescription": {"text": "Commented-code block (7 lines) in apps/web/src/dub/course/components/course-overlay.tsx:3"}, "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-37370f35d817392a", "name": "Commented-code block (5 lines) in apps/web/src/dub/course/link/client.ts:1", "shortDescription": {"text": "Commented-code block (5 lines) in apps/web/src/dub/course/link/client.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-2d071da0727a5c90", "name": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/src/dub/course/link/client.ts:144", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/src/dub/course/link/client.ts:144"}, "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-1d85be764037e7d0", "name": "Commented-code block (5 lines) in apps/web/src/dub/course/link/server/jobs.ts:1", "shortDescription": {"text": "Commented-code block (5 lines) in apps/web/src/dub/course/link/server/jobs.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-b0f1d6869e52cfb9", "name": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/src/dub/course/link/server/jobs.ts:182", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/src/dub/course/link/server/jobs.ts:182"}, "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-41ba50aa19bc8fea", "name": "Commented-code block (5 lines) in apps/web/src/dub/course/engine/stages/assemble.ts:1", "shortDescription": {"text": "Commented-code block (5 lines) in apps/web/src/dub/course/engine/stages/assemble.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-4c65652847f2fd53", "name": "Commented-code block (5 lines) in apps/web/src/dub/course/engine/stages/export.ts:1", "shortDescription": {"text": "Commented-code block (5 lines) in apps/web/src/dub/course/engine/stages/export.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-4496f6450c2ffd5d", "name": "Commented-code block (5 lines) in apps/web/src/dub/course/engine/stages/synthesize.ts:1", "shortDescription": {"text": "Commented-code block (5 lines) in apps/web/src/dub/course/engine/stages/synthesize.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-2d525f6f7801a150", "name": "Commented-code block (6 lines) in apps/web/src/timeline/controllers/element-interaction-controller.ts:104", "shortDescription": {"text": "Commented-code block (6 lines) in apps/web/src/timeline/controllers/element-interaction-controller.ts:104"}, "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-90c11a7f3e8db7a4", "name": "Commented-code block (7 lines) in apps/web/src/timeline/group-resize/compute-resize.ts:81", "shortDescription": {"text": "Commented-code block (7 lines) in apps/web/src/timeline/group-resize/compute-resize.ts:81"}, "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-6e7b531f3a3c876c", "name": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/src/components/header.tsx:58", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/src/components/header.tsx:58"}, "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-016db92cbd03d4c9", "name": "Commented-code block (5 lines) in apps/web/src/components/landing/hero.tsx:13", "shortDescription": {"text": "Commented-code block (5 lines) in apps/web/src/components/landing/hero.tsx: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-576f911832f6475c", "name": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/src/app/api/sounds/search/route.ts:235", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/src/app/api/sounds/search/route.ts:235"}, "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-6f45e00a18d4ae92", "name": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/src/sounds/use-sound-search.ts:50", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/src/sounds/use-sound-search.ts:50"}, "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-13701f4d967593e0", "name": "Commented-code block (5 lines) in apps/web/src/services/transcription/worker.ts:104", "shortDescription": {"text": "Commented-code block (5 lines) in apps/web/src/services/transcription/worker.ts:104"}, "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-1e6b4bc92ac30c9c", "name": "Commented-code block (5 lines) in apps/web/src/core/managers/commands.ts:56", "shortDescription": {"text": "Commented-code block (5 lines) in apps/web/src/core/managers/commands.ts:56"}, "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-2eafc3188c36bb02", "name": "3 env vars used in code but missing from .env.example", "shortDescription": {"text": "3 env vars used in code but missing from .env.example"}, "fullDescription": {"text": "Drift between code and config docs. The first few: `ALL_PROXY`, `HTTPS_PROXY`, `HTTP_PROXY`. Add them (with a placeholder/comment) to .env.example so onboarding doesn't break."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}]}}, "automationDetails": {"id": "repobility/23576"}, "properties": {"repository": "zebo101/dubcopilot", "repoUrl": "https://github.com/zebo101/dubcopilot", "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-87654f1be0fd14f8", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 apps/web/scripts/generate-font-sprites.ts:64"}, "properties": {"repobilityId": "ca40fee6cd7bb369", "scanner": "scanner-primary", "fingerprint": "87654f1be0fd14f8", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-9248ec3d39f12272", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/dub/components/dub-view.tsx:438"}, "properties": {"repobilityId": "2897e3b8866978a3", "scanner": "scanner-primary", "fingerprint": "9248ec3d39f12272", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-4db58155a49ccc2a", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/dub/components/voice-picker.tsx:138"}, "properties": {"repobilityId": "af0710bbb3249759", "scanner": "scanner-primary", "fingerprint": "4db58155a49ccc2a", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-c3b44d41557d3a1b", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/dub/course/components/import-course.tsx:228"}, "properties": {"repobilityId": "a0b3ae53eb298ace", "scanner": "scanner-primary", "fingerprint": "c3b44d41557d3a1b", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-bc3a7b007827422b", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/dub/course/components/export-button.tsx:142"}, "properties": {"repobilityId": "f5c5e032b224891f", "scanner": "scanner-primary", "fingerprint": "bc3a7b007827422b", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-9a7c9a50e07787f2", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/dub/course/components/batch-center.tsx:125"}, "properties": {"repobilityId": "c7e4715d15ad016b", "scanner": "scanner-primary", "fingerprint": "9a7c9a50e07787f2", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-24c788882c85c226", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/timeline/components/timeline-element.tsx:911"}, "properties": {"repobilityId": "d5e1ab12541b5e2d", "scanner": "scanner-primary", "fingerprint": "24c788882c85c226", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-3f3ad634be070b82", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/timeline/components/index.tsx:946"}, "properties": {"repobilityId": "172eaffb6f87d852", "scanner": "scanner-primary", "fingerprint": "3f3ad634be070b82", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-27e27e2888b4e9d8", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/components/ui/font-picker.tsx:100"}, "properties": {"repobilityId": "3aefa767303b55c5", "scanner": "scanner-primary", "fingerprint": "27e27e2888b4e9d8", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-e24faea712a0b8bd", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/components/landing/hero.tsx:407"}, "properties": {"repobilityId": "7752800b89adf70f", "scanner": "scanner-primary", "fingerprint": "e24faea712a0b8bd", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-5e6d9149966e17b4", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/components/editor/panels/assets/draggable-item.tsx:161"}, "properties": {"repobilityId": "0e926af4bed9f4f6", "scanner": "scanner-primary", "fingerprint": "5e6d9149966e17b4", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-39961ced6b46071b", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/components/editor/panels/assets/views/settings/index.tsx:236"}, "properties": {"repobilityId": "bb88ef577d544cce", "scanner": "scanner-primary", "fingerprint": "39961ced6b46071b", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-886bb86d72b0becd", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 apps/web/src/app/page.tsx:85"}, "properties": {"repobilityId": "4256fb41200a9cfe", "scanner": "scanner-primary", "fingerprint": "886bb86d72b0becd", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-8b3d8d736a229e9d", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/app/projects/page.tsx:747"}, "properties": {"repobilityId": "fde402cd1fa5357a", "scanner": "scanner-primary", "fingerprint": "8b3d8d736a229e9d", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-37099448a718b809", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 apps/web/src/lib/analytics.ts:39"}, "properties": {"repobilityId": "7769c5efe78bc3e3", "scanner": "scanner-primary", "fingerprint": "37099448a718b809", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-8b91d965f2bbd1b0", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/sounds/components/assets-view.tsx:527"}, "properties": {"repobilityId": "af44ffd8c74adf9f", "scanner": "scanner-primary", "fingerprint": "8b91d965f2bbd1b0", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-f36282140a074635", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 apps/web/src/services/transcription/worker.ts:120"}, "properties": {"repobilityId": "fea3d4eba052e599", "scanner": "scanner-primary", "fingerprint": "f36282140a074635", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-3ec5b19ea2a521be", "level": "none", "message": {"text": "TODO/FIXME marker in shipping code \u2014 apps/web/src/actions/use-editor-actions.ts:496"}, "properties": {"repobilityId": "bbc97ba3253741cf", "scanner": "scanner-primary", "fingerprint": "3ec5b19ea2a521be", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.todo-marker"]}}, {"ruleId": "scanner-8469e41a801a6954", "level": "none", "message": {"text": "TODO/FIXME marker in shipping code \u2014 apps/web/src/guides/registry.tsx:20"}, "properties": {"repobilityId": "69921fa6a6bcaa0c", "scanner": "scanner-primary", "fingerprint": "8469e41a801a6954", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.todo-marker"]}}, {"ruleId": "scanner-3942e3b6ee1d7164", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/project/components/project-info-dialog.tsx:48"}, "properties": {"repobilityId": "d18b89e046bb12d8", "scanner": "scanner-primary", "fingerprint": "3942e3b6ee1d7164", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-16571cd32c60e2d5", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 apps/web/src/project/components/delete-project-dialog.tsx:42"}, "properties": {"repobilityId": "5ebfbc15d6fd00a6", "scanner": "scanner-primary", "fingerprint": "16571cd32c60e2d5", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-0ed57e814e5be16d", "level": "note", "message": {"text": "Docker base image is tag-pinned but not digest-pinned: oven/bun:alpine"}, "properties": {"repobilityId": "a80ac7064b305df0", "scanner": "scanner-primary", "fingerprint": "0ed57e814e5be16d", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "docker", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/web/Dockerfile"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-aa5acaa49eb8315b", "level": "note", "message": {"text": "Containers defined but no K8s/orchestration manifest found"}, "properties": {"repobilityId": "b230ea9b68736081", "scanner": "scanner-primary", "fingerprint": "aa5acaa49eb8315b", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["coverage", "deployment"]}}, {"ruleId": "scanner-30a2a5fcbd5e8957", "level": "warning", "message": {"text": "Insecure pattern 'node_child_process' in apps/web/src/dub/course/link/server/bin.ts:5"}, "properties": {"repobilityId": "9b3dcdc782a7f8b0", "scanner": "scanner-primary", "fingerprint": "30a2a5fcbd5e8957", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "node_child_process"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/web/src/dub/course/link/server/bin.ts"}, "region": {"startLine": 5}}}]}, {"ruleId": "scanner-07b2b7847cb7cab3", "level": "error", "message": {"text": "Insecure pattern 'eval_used' in apps/web/src/utils/__tests__/math.test.ts:108"}, "properties": {"repobilityId": "936f8da5ef3d00e4", "scanner": "scanner-primary", "fingerprint": "07b2b7847cb7cab3", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["owasp", "eval_used"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/web/src/utils/__tests__/math.test.ts"}, "region": {"startLine": 108}}}]}, {"ruleId": "scanner-e076ab009c3dec9f", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in apps/web/src/app/page.tsx:85"}, "properties": {"repobilityId": "d54215008ef9de96", "scanner": "scanner-primary", "fingerprint": "e076ab009c3dec9f", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/web/src/app/page.tsx"}, "region": {"startLine": 85}}}]}, {"ruleId": "scanner-27924aa79fa4a517", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "54c8f1b47dd62535", "scanner": "scanner-primary", "fingerprint": "27924aa79fa4a517", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/ci.yml"}, "region": {"startLine": 29}}}]}, {"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-4a9eb7dc7c6e3880", "level": "note", "message": {"text": "Node manifest has dependencies but no lockfile: apps/web/package.json"}, "properties": {"repobilityId": "6c1704bf24cf19ac", "scanner": "scanner-primary", "fingerprint": "4a9eb7dc7c6e3880", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["dependency", "lockfile", "reproducibility", "generated-repo-pattern"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "apps/web/package.json"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-3ab5d313dda8e5f9", "level": "note", "message": {"text": "Debug logging residue appears in source files"}, "properties": {"repobilityId": "2953a6ffa2263ec2", "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": "91a7de0a0784a67e", "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": "f2eb7dabbc3c2045", "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": "4501e3982bf3e001", "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": "d3f2957e50683f13", "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": "ddb8ec2d1b7f55af", "scanner": "scanner-primary", "fingerprint": "8424db9c75e04ba4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["provenance", "git-history", "generated-repo-pattern"]}}, {"ruleId": "scanner-49c68efa71eff82a", "level": "none", "message": {"text": "Commented-code block (5 lines) in eslint.config.mjs:87"}, "properties": {"repobilityId": "318305a8bcd5e122", "scanner": "scanner-primary", "fingerprint": "49c68efa71eff82a", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-eca967f972b34146", "level": "none", "message": {"text": "Commented-code block (6 lines) in eslint/rules/prefer-object-params.mjs:31"}, "properties": {"repobilityId": "8e4a63f54da65f2e", "scanner": "scanner-primary", "fingerprint": "eca967f972b34146", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-01c8178581858854", "level": "none", "message": {"text": "Commented-code block (6 lines) in eslint/rules/__tests__/prefer-object-params.test.mjs:96"}, "properties": {"repobilityId": "49158a5d06ad435d", "scanner": "scanner-primary", "fingerprint": "01c8178581858854", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-bce0539aa0515bcc", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/scripts/generate-font-sprites.ts:65"}, "properties": {"repobilityId": "94492ef780494254", "scanner": "scanner-primary", "fingerprint": "bce0539aa0515bcc", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-0f21ccbb036b2b66", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/src/media/audio.ts:235"}, "properties": {"repobilityId": "a9672d4ba2916150", "scanner": "scanner-primary", "fingerprint": "0f21ccbb036b2b66", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-e9b08afec2cdeb35", "level": "none", "message": {"text": "Commented-code block (5 lines) in apps/web/src/commands/timeline/element/split-elements.ts:94"}, "properties": {"repobilityId": "220da5212b83a6bc", "scanner": "scanner-primary", "fingerprint": "e9b08afec2cdeb35", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-e19febe470b5ed59", "level": "none", "message": {"text": "Commented-code block (5 lines) in apps/web/src/dub/original-audio.ts:1"}, "properties": {"repobilityId": "1535d6b6a98046f0", "scanner": "scanner-primary", "fingerprint": "e19febe470b5ed59", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-bb6e81e01c59f9ff", "level": "none", "message": {"text": "Commented-code block (7 lines) in apps/web/src/dub/units.ts:1"}, "properties": {"repobilityId": "a1942e2f83f2835c", "scanner": "scanner-primary", "fingerprint": "bb6e81e01c59f9ff", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-1aa66b7a33b7dabe", "level": "none", "message": {"text": "Commented-code block (6 lines) in apps/web/src/dub/custom-voices.ts:6"}, "properties": {"repobilityId": "7f1ad286cfe7bca3", "scanner": "scanner-primary", "fingerprint": "1aa66b7a33b7dabe", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-7140fadaef960330", "level": "none", "message": {"text": "Commented-code block (5 lines) in apps/web/src/dub/adapter.ts:159"}, "properties": {"repobilityId": "c4cf649deb17b6f7", "scanner": "scanner-primary", "fingerprint": "7140fadaef960330", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-5e26294357adb003", "level": "none", "message": {"text": "Commented-code block (5 lines) in apps/web/src/dub/voice-lang-check.ts:5"}, "properties": {"repobilityId": "3c63ceecadcd0bad", "scanner": "scanner-primary", "fingerprint": "5e26294357adb003", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-b378f2d29eb3640f", "level": "none", "message": {"text": "Commented-code block (5 lines) in apps/web/src/dub/sanitize.ts:1"}, "properties": {"repobilityId": "680502420970013c", "scanner": "scanner-primary", "fingerprint": "b378f2d29eb3640f", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-1811ec8e419d8088", "level": "none", "message": {"text": "Commented-code block (5 lines) in apps/web/src/dub/subtitle-split.ts:1"}, "properties": {"repobilityId": "c6f6177eb58af9b5", "scanner": "scanner-primary", "fingerprint": "1811ec8e419d8088", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-ab7e2cceab6b6a6e", "level": "none", "message": {"text": "Commented-code block (5 lines) in apps/web/src/dub/components/dub-view.tsx:813"}, "properties": {"repobilityId": "6caae639c6fd41c1", "scanner": "scanner-primary", "fingerprint": "ab7e2cceab6b6a6e", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-c40b3f8c95dfcc67", "level": "none", "message": {"text": "Commented-code block (5 lines) in apps/web/src/dub/course/export-batch.ts:1"}, "properties": {"repobilityId": "934285df50937703", "scanner": "scanner-primary", "fingerprint": "c40b3f8c95dfcc67", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-c7eb05cb62a53217", "level": "none", "message": {"text": "Commented-code block (5 lines) in apps/web/src/dub/course/idb.ts:1"}, "properties": {"repobilityId": "990a9c5e93f2a6da", "scanner": "scanner-primary", "fingerprint": "c7eb05cb62a53217", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-93c8678d93a8f4b2", "level": "none", "message": {"text": "Commented-code block (5 lines) in apps/web/src/dub/course/zip.ts:1"}, "properties": {"repobilityId": "fe0852a763a21116", "scanner": "scanner-primary", "fingerprint": "93c8678d93a8f4b2", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-3e76b58bc716fe9b", "level": "none", "message": {"text": "Commented-code block (7 lines) in apps/web/src/dub/course/components/course-overlay.tsx:3"}, "properties": {"repobilityId": "d0a84a139bb76b01", "scanner": "scanner-primary", "fingerprint": "3e76b58bc716fe9b", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-37370f35d817392a", "level": "none", "message": {"text": "Commented-code block (5 lines) in apps/web/src/dub/course/link/client.ts:1"}, "properties": {"repobilityId": "507d4471a91454d4", "scanner": "scanner-primary", "fingerprint": "37370f35d817392a", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-2d071da0727a5c90", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/src/dub/course/link/client.ts:144"}, "properties": {"repobilityId": "5bb3d1c2e9ee870a", "scanner": "scanner-primary", "fingerprint": "2d071da0727a5c90", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-1d85be764037e7d0", "level": "none", "message": {"text": "Commented-code block (5 lines) in apps/web/src/dub/course/link/server/jobs.ts:1"}, "properties": {"repobilityId": "c648f9c37e40f583", "scanner": "scanner-primary", "fingerprint": "1d85be764037e7d0", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-b0f1d6869e52cfb9", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/src/dub/course/link/server/jobs.ts:182"}, "properties": {"repobilityId": "241fabad4b026853", "scanner": "scanner-primary", "fingerprint": "b0f1d6869e52cfb9", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-41ba50aa19bc8fea", "level": "none", "message": {"text": "Commented-code block (5 lines) in apps/web/src/dub/course/engine/stages/assemble.ts:1"}, "properties": {"repobilityId": "285ff939a19c6850", "scanner": "scanner-primary", "fingerprint": "41ba50aa19bc8fea", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-4c65652847f2fd53", "level": "none", "message": {"text": "Commented-code block (5 lines) in apps/web/src/dub/course/engine/stages/export.ts:1"}, "properties": {"repobilityId": "b513c1ce02e1ee89", "scanner": "scanner-primary", "fingerprint": "4c65652847f2fd53", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-4496f6450c2ffd5d", "level": "none", "message": {"text": "Commented-code block (5 lines) in apps/web/src/dub/course/engine/stages/synthesize.ts:1"}, "properties": {"repobilityId": "d4286b093ee46640", "scanner": "scanner-primary", "fingerprint": "4496f6450c2ffd5d", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-2d525f6f7801a150", "level": "none", "message": {"text": "Commented-code block (6 lines) in apps/web/src/timeline/controllers/element-interaction-controller.ts:104"}, "properties": {"repobilityId": "9869906fba08d8a8", "scanner": "scanner-primary", "fingerprint": "2d525f6f7801a150", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-90c11a7f3e8db7a4", "level": "none", "message": {"text": "Commented-code block (7 lines) in apps/web/src/timeline/group-resize/compute-resize.ts:81"}, "properties": {"repobilityId": "80d9cdf796173d89", "scanner": "scanner-primary", "fingerprint": "90c11a7f3e8db7a4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-6e7b531f3a3c876c", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/src/components/header.tsx:58"}, "properties": {"repobilityId": "41cbbee0f558139a", "scanner": "scanner-primary", "fingerprint": "6e7b531f3a3c876c", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-016db92cbd03d4c9", "level": "none", "message": {"text": "Commented-code block (5 lines) in apps/web/src/components/landing/hero.tsx:13"}, "properties": {"repobilityId": "88ca9b7e7e8c4006", "scanner": "scanner-primary", "fingerprint": "016db92cbd03d4c9", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-576f911832f6475c", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/src/app/api/sounds/search/route.ts:235"}, "properties": {"repobilityId": "65c9635ad3124d3f", "scanner": "scanner-primary", "fingerprint": "576f911832f6475c", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-6f45e00a18d4ae92", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 apps/web/src/sounds/use-sound-search.ts:50"}, "properties": {"repobilityId": "bf121434771327dc", "scanner": "scanner-primary", "fingerprint": "6f45e00a18d4ae92", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-13701f4d967593e0", "level": "none", "message": {"text": "Commented-code block (5 lines) in apps/web/src/services/transcription/worker.ts:104"}, "properties": {"repobilityId": "8bf06a7c09bab043", "scanner": "scanner-primary", "fingerprint": "13701f4d967593e0", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-1e6b4bc92ac30c9c", "level": "none", "message": {"text": "Commented-code block (5 lines) in apps/web/src/core/managers/commands.ts:56"}, "properties": {"repobilityId": "bf6b2875eaab45db", "scanner": "scanner-primary", "fingerprint": "1e6b4bc92ac30c9c", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-2eafc3188c36bb02", "level": "none", "message": {"text": "3 env vars used in code but missing from .env.example"}, "properties": {"repobilityId": "bd934ba112b02ffa", "scanner": "scanner-primary", "fingerprint": "2eafc3188c36bb02", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "config-drift"]}}]}]}