{"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-0619f4446b87e8d7", "name": "Stray `console.log` in TS/JS \u2014 scripts/test-degree-risk-majors.ts:67", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/test-degree-risk-majors.ts:67"}, "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-efe7ba5667f8de6c", "name": "Stray `console.log` in TS/JS \u2014 scripts/sync-cities-ca.ts:43", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/sync-cities-ca.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-096709de577b4b0a", "name": "Stray `console.log` in TS/JS \u2014 scripts/sync-colleges-au.ts:155", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/sync-colleges-au.ts:155"}, "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-4469f0f6bda19130", "name": "Stray `console.log` in TS/JS \u2014 scripts/sync-programs.ts:111", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/sync-programs.ts:111"}, "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-577ec09acdcb7354", "name": "Stray `console.log` in TS/JS \u2014 scripts/sync-colleges-ca.ts:240", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/sync-colleges-ca.ts:240"}, "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-90f2d0ec9f391284", "name": "Stray `console.log` in TS/JS \u2014 scripts/sync-colleges-ie.ts:126", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/sync-colleges-ie.ts:126"}, "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-1eaf3a31bb837d2c", "name": "Stray `console.log` in TS/JS \u2014 scripts/sync-cities-au.ts:43", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/sync-cities-au.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-640a63585d384c50", "name": "Stray `console.log` in TS/JS \u2014 scripts/sync-cities.ts:145", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/sync-cities.ts:145"}, "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-cbf0901a86a75641", "name": "Stray `console.log` in TS/JS \u2014 scripts/sync-cities-ie.ts:43", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/sync-cities-ie.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-836711e637ffb6d1", "name": "Stray `console.log` in TS/JS \u2014 scripts/sync-colleges.ts:103", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/sync-colleges.ts:103"}, "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-5b72e27a2ff90942", "name": "Stray `console.log` in TS/JS \u2014 scripts/sync-colleges-uk.ts:217", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/sync-colleges-uk.ts:217"}, "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-c017ad5541fc399f", "name": "Stray `console.log` in TS/JS \u2014 scripts/sync-cities-uk.ts:43", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/sync-cities-uk.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-0ba208b1b21b9fce", "name": "Stray `console.log` in TS/JS \u2014 scripts/calc-roi.ts:109", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/calc-roi.ts:109"}, "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-c8aeede95ed16d81", "name": "Stray `console.log` in TS/JS \u2014 scripts/upsert-courses-ie.ts:136", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/upsert-courses-ie.ts:136"}, "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-c46f9c1b70268b7f", "name": "Stray `console.log` in TS/JS \u2014 scripts/scrape-tuition-au.ts:121", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/scrape-tuition-au.ts:121"}, "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-b0383f06e2149a2f", "name": "TODO/FIXME marker in shipping code \u2014 src/app/layout.tsx:28", "shortDescription": {"text": "TODO/FIXME marker in shipping code \u2014 src/app/layout.tsx:28"}, "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-6eb58754264defca", "name": "`truncate` class without `title=` for hover reveal \u2014 src/app/page.tsx:102", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/page.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-83c748b19330603b", "name": "`truncate` class without `title=` for hover reveal \u2014 src/app/dashboard/page.tsx:319", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/dashboard/page.tsx:319"}, "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-ca1e3814e9e30cdd", "name": "`truncate` class without `title=` for hover reveal \u2014 src/app/checklist/page.tsx:364", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/checklist/page.tsx:364"}, "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-f9a24fa379d3a742", "name": "TODO/FIXME marker in shipping code \u2014 src/app/checklist/page.tsx:26", "shortDescription": {"text": "TODO/FIXME marker in shipping code \u2014 src/app/checklist/page.tsx:26"}, "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-1b31f2782c651057", "name": "`truncate` class without `title=` for hover reveal \u2014 src/app/timeline/page.tsx:723", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/timeline/page.tsx:723"}, "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-8e08918a964bbe3f", "name": "`truncate` class without `title=` for hover reveal \u2014 src/app/compare/page.tsx:382", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/compare/page.tsx:382"}, "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-1e00ea7702f90a39", "name": "`truncate` class without `title=` for hover reveal \u2014 src/app/onboarding/page.tsx:266", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/onboarding/page.tsx:266"}, "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-24f9eb9a125a08e7", "name": "`truncate` class without `title=` for hover reveal \u2014 src/app/career-path/page.tsx:453", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/career-path/page.tsx:453"}, "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-ae4abf217272f16a", "name": "`truncate` class without `title=` for hover reveal \u2014 src/app/degree-risk/result/where-to-study.tsx:83", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/degree-risk/result/where-to-study.tsx:83"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-1a7782159ec1c5b2", "name": "`truncate` class without `title=` for hover reveal \u2014 src/app/documents/page.tsx:301", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/documents/page.tsx:301"}, "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-79e8b5491f9b50b7", "name": "`truncate` class without `title=` for hover reveal \u2014 src/app/roi-explorer/RoiExplorerClient.tsx:824", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/roi-explorer/RoiExplorerClient.tsx:824"}, "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-8b021181497ce6b1", "name": "TODO/FIXME marker in shipping code \u2014 src/app/roi-explorer/RoiExplorerClient.tsx:654", "shortDescription": {"text": "TODO/FIXME marker in shipping code \u2014 src/app/roi-explorer/RoiExplorerClient.tsx:654"}, "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-4473ba3f1e519e68", "name": "TODO/FIXME marker in shipping code \u2014 src/app/roi-explorer/[country]/[college_id]/CollegeDetailClient.tsx:149", "shortDescription": {"text": "TODO/FIXME marker in shipping code \u2014 src/app/roi-explorer/[country]/[college_id]/CollegeDetailClient.tsx:149"}, "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-33b37d001e5e2134", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 src/components/seo/json-ld.tsx:8", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 src/components/seo/json-ld.tsx:8"}, "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-dee46b36753ca619", "name": "Insecure pattern 'dangerous_innerhtml' in src/components/seo/json-ld.tsx:8", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in src/components/seo/json-ld.tsx:8"}, "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-cb68c177fc467829", "name": "Insecure pattern 'direct_innerhtml_assignment' in public/games/vacant-dublin.html:964", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/games/vacant-dublin.html:964"}, "fullDescription": {"text": "Found a known-risky pattern (direct_innerhtml_assignment). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-6893a6c8b0861585", "name": "Very low test-to-source ratio", "shortDescription": {"text": "Very low test-to-source ratio"}, "fullDescription": {"text": "1 test file(s) for 118 source file(s) (ratio 0.01). Consider adding integration or unit tests for critical paths."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "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 203 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 34 placeholder/mock markers across 11 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-9d79c4077342a7d0", "name": "Runtime service client appears to use placeholder configuration", "shortDescription": {"text": "Runtime service client appears to use placeholder configuration"}, "fullDescription": {"text": "A runtime source file appears to wire Supabase/Firebase/AI/payment-style clients to placeholder URLs, keys, or fallback values. In the Fable corpus this often means the UI/API shape is present while the backend service is not actually configured."}, "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-b9088664ace7f748", "name": "Composite production-readiness gap", "shortDescription": {"text": "Composite production-readiness gap"}, "fullDescription": {"text": "Multiple low-cost hardening controls are missing together: ci, tests. Opus verification showed these co-occurring gaps are a better readiness signal than reading each flag in isolation."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "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 ci, tests. 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-2c5f98b152cddb6d", "name": "Agent authority lacks a verifier contract: .claude/launch.json", "shortDescription": {"text": "Agent authority lacks a verifier contract: .claude/launch.json"}, "fullDescription": {"text": "This agent instruction grants code or shell authority but does not state the verification gate that decides promotion. The recurring safe pattern is: LLM proposes; deterministic tests/build/security checks verify; only verified code promotes."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-7d8321e747e4762d", "name": "Commented-code block (7 lines) in scripts/sync-colleges-au.ts:186", "shortDescription": {"text": "Commented-code block (7 lines) in scripts/sync-colleges-au.ts:186"}, "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-6336d9a793d8b1bf", "name": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/sync-colleges-au.ts:231", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/sync-colleges-au.ts:231"}, "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-da71bb62bafa6d67", "name": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/sync-programs.ts:72", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/sync-programs.ts:72"}, "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-57cf9af4894d880c", "name": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/sync-colleges-ca.ts:383", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/sync-colleges-ca.ts:383"}, "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-0e6854cafdc60c5f", "name": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/sync-colleges-ie.ts:237", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/sync-colleges-ie.ts:237"}, "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-ae4bccb517494205", "name": "Commented-code block (7 lines) in scripts/merge_to_supabase.py:3", "shortDescription": {"text": "Commented-code block (7 lines) in scripts/merge_to_supabase.py: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-439ca157cc74614f", "name": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/sync-cities.ts:117", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/sync-cities.ts:117"}, "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-9458f640f9cbca51", "name": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/sync-colleges.ts:66", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/sync-colleges.ts:66"}, "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-a735bd6670b47a33", "name": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/sync-colleges-uk.ts:464", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/sync-colleges-uk.ts:464"}, "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-e340dab547f3a00e", "name": "Commented-code block (5 lines) in scripts/scraper_qualifax.py:3", "shortDescription": {"text": "Commented-code block (5 lines) in scripts/scraper_qualifax.py: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-1a34d9498cba5503", "name": "Commented-code block (5 lines) in scripts/upsert-courses-ie.ts:86", "shortDescription": {"text": "Commented-code block (5 lines) in scripts/upsert-courses-ie.ts:86"}, "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-d97e1d3d9b4b1597", "name": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/upsert-courses-ie.ts:234", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/upsert-courses-ie.ts:234"}, "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-9e724a3973d78945", "name": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/scrape-tuition-au.ts:165", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/scrape-tuition-au.ts:165"}, "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-05df1d3090438f6c", "name": "Commented-code block (6 lines) in src/app/layout.tsx:28", "shortDescription": {"text": "Commented-code block (6 lines) in src/app/layout.tsx:28"}, "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-8a77c474f3931c3f", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/dashboard/page.tsx:226", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/dashboard/page.tsx:226"}, "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-942587fa36244287", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/api/exchange-rates/route.ts:6", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/api/exchange-rates/route.ts:6"}, "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-6ba8ee8e7de95b89", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/api/checklist/route.ts:57", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/api/checklist/route.ts:57"}, "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-077615dfeba3320a", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/checklist/page.tsx:174", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/checklist/page.tsx:174"}, "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-786e19236c2de75b", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/lib/currency.ts:16", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/lib/currency.ts:16"}, "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-d6779d7c5920ccc1", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/documents/page.tsx:137", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/documents/page.tsx:137"}, "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-806b9790eb269707", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/roi-explorer/RoiExplorerClient.tsx:529", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/roi-explorer/RoiExplorerClient.tsx:529"}, "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-ef3dd23f273ffc3d", "name": "Commented-code block (7 lines) in src/lib/career-stage.ts:13", "shortDescription": {"text": "Commented-code block (7 lines) in src/lib/career-stage.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}}]}}, "automationDetails": {"id": "repobility/24814"}, "properties": {"repository": "CampCareer/campcareer", "repoUrl": "https://github.com/CampCareer/campcareer", "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-0619f4446b87e8d7", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/test-degree-risk-majors.ts:67"}, "properties": {"repobilityId": "d072b5565bb9a211", "scanner": "scanner-primary", "fingerprint": "0619f4446b87e8d7", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-efe7ba5667f8de6c", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/sync-cities-ca.ts:43"}, "properties": {"repobilityId": "2a9a868baf03d608", "scanner": "scanner-primary", "fingerprint": "efe7ba5667f8de6c", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-096709de577b4b0a", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/sync-colleges-au.ts:155"}, "properties": {"repobilityId": "3fab3d56083c82f6", "scanner": "scanner-primary", "fingerprint": "096709de577b4b0a", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-4469f0f6bda19130", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/sync-programs.ts:111"}, "properties": {"repobilityId": "809442f7154df74a", "scanner": "scanner-primary", "fingerprint": "4469f0f6bda19130", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-577ec09acdcb7354", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/sync-colleges-ca.ts:240"}, "properties": {"repobilityId": "d3667caed7382c48", "scanner": "scanner-primary", "fingerprint": "577ec09acdcb7354", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-90f2d0ec9f391284", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/sync-colleges-ie.ts:126"}, "properties": {"repobilityId": "83bb99c7e68f6c59", "scanner": "scanner-primary", "fingerprint": "90f2d0ec9f391284", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-1eaf3a31bb837d2c", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/sync-cities-au.ts:43"}, "properties": {"repobilityId": "5c09ed387bed5cae", "scanner": "scanner-primary", "fingerprint": "1eaf3a31bb837d2c", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-640a63585d384c50", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/sync-cities.ts:145"}, "properties": {"repobilityId": "ace43713ea61d38d", "scanner": "scanner-primary", "fingerprint": "640a63585d384c50", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-cbf0901a86a75641", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/sync-cities-ie.ts:43"}, "properties": {"repobilityId": "91bfbf0c60df67dd", "scanner": "scanner-primary", "fingerprint": "cbf0901a86a75641", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-836711e637ffb6d1", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/sync-colleges.ts:103"}, "properties": {"repobilityId": "a30661cf88638ab1", "scanner": "scanner-primary", "fingerprint": "836711e637ffb6d1", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-5b72e27a2ff90942", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/sync-colleges-uk.ts:217"}, "properties": {"repobilityId": "2ae6a62cb04cece8", "scanner": "scanner-primary", "fingerprint": "5b72e27a2ff90942", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-c017ad5541fc399f", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/sync-cities-uk.ts:43"}, "properties": {"repobilityId": "d5f1770ad51bd822", "scanner": "scanner-primary", "fingerprint": "c017ad5541fc399f", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-0ba208b1b21b9fce", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/calc-roi.ts:109"}, "properties": {"repobilityId": "2861454df1e61af9", "scanner": "scanner-primary", "fingerprint": "0ba208b1b21b9fce", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-c8aeede95ed16d81", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/upsert-courses-ie.ts:136"}, "properties": {"repobilityId": "8af1c425f3c7b557", "scanner": "scanner-primary", "fingerprint": "c8aeede95ed16d81", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-c46f9c1b70268b7f", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/scrape-tuition-au.ts:121"}, "properties": {"repobilityId": "f96c16eb8f285352", "scanner": "scanner-primary", "fingerprint": "c46f9c1b70268b7f", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-b0383f06e2149a2f", "level": "none", "message": {"text": "TODO/FIXME marker in shipping code \u2014 src/app/layout.tsx:28"}, "properties": {"repobilityId": "03ad5f735cfc3ddb", "scanner": "scanner-primary", "fingerprint": "b0383f06e2149a2f", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.todo-marker"]}}, {"ruleId": "scanner-6eb58754264defca", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/page.tsx:102"}, "properties": {"repobilityId": "e498d41b9221bfd3", "scanner": "scanner-primary", "fingerprint": "6eb58754264defca", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-83c748b19330603b", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/dashboard/page.tsx:319"}, "properties": {"repobilityId": "4ba209c1bd3eacfd", "scanner": "scanner-primary", "fingerprint": "83c748b19330603b", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-ca1e3814e9e30cdd", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/checklist/page.tsx:364"}, "properties": {"repobilityId": "3d7ec6aece5846f5", "scanner": "scanner-primary", "fingerprint": "ca1e3814e9e30cdd", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-f9a24fa379d3a742", "level": "none", "message": {"text": "TODO/FIXME marker in shipping code \u2014 src/app/checklist/page.tsx:26"}, "properties": {"repobilityId": "94d7ab304df5811d", "scanner": "scanner-primary", "fingerprint": "f9a24fa379d3a742", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.todo-marker"]}}, {"ruleId": "scanner-1b31f2782c651057", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/timeline/page.tsx:723"}, "properties": {"repobilityId": "88448b496d457191", "scanner": "scanner-primary", "fingerprint": "1b31f2782c651057", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-8e08918a964bbe3f", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/compare/page.tsx:382"}, "properties": {"repobilityId": "796b7abbb91bcb2b", "scanner": "scanner-primary", "fingerprint": "8e08918a964bbe3f", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-1e00ea7702f90a39", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/onboarding/page.tsx:266"}, "properties": {"repobilityId": "3ebd2e76af223bcd", "scanner": "scanner-primary", "fingerprint": "1e00ea7702f90a39", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-24f9eb9a125a08e7", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/career-path/page.tsx:453"}, "properties": {"repobilityId": "f48d5a33d3c01bfb", "scanner": "scanner-primary", "fingerprint": "24f9eb9a125a08e7", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-ae4abf217272f16a", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/degree-risk/result/where-to-study.tsx:83"}, "properties": {"repobilityId": "1355593d607f3be7", "scanner": "scanner-primary", "fingerprint": "ae4abf217272f16a", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-1a7782159ec1c5b2", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/documents/page.tsx:301"}, "properties": {"repobilityId": "f2fbcb3f8d19c156", "scanner": "scanner-primary", "fingerprint": "1a7782159ec1c5b2", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-79e8b5491f9b50b7", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/app/roi-explorer/RoiExplorerClient.tsx:824"}, "properties": {"repobilityId": "c55b4754e3d67549", "scanner": "scanner-primary", "fingerprint": "79e8b5491f9b50b7", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-8b021181497ce6b1", "level": "none", "message": {"text": "TODO/FIXME marker in shipping code \u2014 src/app/roi-explorer/RoiExplorerClient.tsx:654"}, "properties": {"repobilityId": "3cc281c39f4e886d", "scanner": "scanner-primary", "fingerprint": "8b021181497ce6b1", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.todo-marker"]}}, {"ruleId": "scanner-4473ba3f1e519e68", "level": "none", "message": {"text": "TODO/FIXME marker in shipping code \u2014 src/app/roi-explorer/[country]/[college_id]/CollegeDetailClient.tsx:149"}, "properties": {"repobilityId": "4b1cecf5db2b0469", "scanner": "scanner-primary", "fingerprint": "4473ba3f1e519e68", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.todo-marker"]}}, {"ruleId": "scanner-33b37d001e5e2134", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 src/components/seo/json-ld.tsx:8"}, "properties": {"repobilityId": "55764ea7310258e2", "scanner": "scanner-primary", "fingerprint": "33b37d001e5e2134", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-dee46b36753ca619", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in src/components/seo/json-ld.tsx:8"}, "properties": {"repobilityId": "66802a6a4855f316", "scanner": "scanner-primary", "fingerprint": "dee46b36753ca619", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/components/seo/json-ld.tsx"}, "region": {"startLine": 8}}}]}, {"ruleId": "scanner-cb68c177fc467829", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/games/vacant-dublin.html:964"}, "properties": {"repobilityId": "2daca72e00f5ceda", "scanner": "scanner-primary", "fingerprint": "cb68c177fc467829", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "public/games/vacant-dublin.html"}, "region": {"startLine": 964}}}]}, {"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-3ab5d313dda8e5f9", "level": "note", "message": {"text": "Debug logging residue appears in source files"}, "properties": {"repobilityId": "749087c153a9ff3a", "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": "c976d3e2e4688f6c", "scanner": "scanner-primary", "fingerprint": "72b2a6250083a784", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "mock-data", "incomplete", "generated-repo-pattern"]}}, {"ruleId": "scanner-9d79c4077342a7d0", "level": "warning", "message": {"text": "Runtime service client appears to use placeholder configuration"}, "properties": {"repobilityId": "6b5977d23de17e46", "scanner": "scanner-primary", "fingerprint": "9d79c4077342a7d0", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "runtime-config", "service-client", "generated-repo-pattern"]}}, {"ruleId": "scanner-2d0c7b7ab8f8aacf", "level": "warning", "message": {"text": "Critical user flow still appears backed by mock or placeholder data"}, "properties": {"repobilityId": "ffe84e5cb0cae3c6", "scanner": "scanner-primary", "fingerprint": "2d0c7b7ab8f8aacf", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "mock-data", "critical-flow", "generated-repo-pattern"]}}, {"ruleId": "scanner-b9088664ace7f748", "level": "note", "message": {"text": "Composite production-readiness gap"}, "properties": {"repobilityId": "6114219d962fc551", "scanner": "scanner-primary", "fingerprint": "b9088664ace7f748", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["production-readiness", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-749d4bc1bd66df5f", "level": "warning", "message": {"text": "Agent instructions exist but release-hardening basics are missing"}, "properties": {"repobilityId": "e88688f04775064c", "scanner": "scanner-primary", "fingerprint": "749d4bc1bd66df5f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-2c5f98b152cddb6d", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: .claude/launch.json"}, "properties": {"repobilityId": "0de48c0f4ab303d8", "scanner": "scanner-primary", "fingerprint": "2c5f98b152cddb6d", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "claude_instruction"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".claude/launch.json"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-7d8321e747e4762d", "level": "none", "message": {"text": "Commented-code block (7 lines) in scripts/sync-colleges-au.ts:186"}, "properties": {"repobilityId": "f770917a3cbec4dd", "scanner": "scanner-primary", "fingerprint": "7d8321e747e4762d", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-6336d9a793d8b1bf", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/sync-colleges-au.ts:231"}, "properties": {"repobilityId": "b38236b831339fc1", "scanner": "scanner-primary", "fingerprint": "6336d9a793d8b1bf", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-da71bb62bafa6d67", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/sync-programs.ts:72"}, "properties": {"repobilityId": "0acea91c634f43b4", "scanner": "scanner-primary", "fingerprint": "da71bb62bafa6d67", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-57cf9af4894d880c", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/sync-colleges-ca.ts:383"}, "properties": {"repobilityId": "4cef10113845511a", "scanner": "scanner-primary", "fingerprint": "57cf9af4894d880c", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-0e6854cafdc60c5f", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/sync-colleges-ie.ts:237"}, "properties": {"repobilityId": "d9db70a25dba8446", "scanner": "scanner-primary", "fingerprint": "0e6854cafdc60c5f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-ae4bccb517494205", "level": "none", "message": {"text": "Commented-code block (7 lines) in scripts/merge_to_supabase.py:3"}, "properties": {"repobilityId": "f792e05a3825a68e", "scanner": "scanner-primary", "fingerprint": "ae4bccb517494205", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-439ca157cc74614f", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/sync-cities.ts:117"}, "properties": {"repobilityId": "c6868ba6dbeb7dfa", "scanner": "scanner-primary", "fingerprint": "439ca157cc74614f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-9458f640f9cbca51", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/sync-colleges.ts:66"}, "properties": {"repobilityId": "fcf49e28a2c22238", "scanner": "scanner-primary", "fingerprint": "9458f640f9cbca51", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-a735bd6670b47a33", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/sync-colleges-uk.ts:464"}, "properties": {"repobilityId": "ff949f8ad7585ae4", "scanner": "scanner-primary", "fingerprint": "a735bd6670b47a33", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-e340dab547f3a00e", "level": "none", "message": {"text": "Commented-code block (5 lines) in scripts/scraper_qualifax.py:3"}, "properties": {"repobilityId": "344c96eac7fe9dd7", "scanner": "scanner-primary", "fingerprint": "e340dab547f3a00e", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-1a34d9498cba5503", "level": "none", "message": {"text": "Commented-code block (5 lines) in scripts/upsert-courses-ie.ts:86"}, "properties": {"repobilityId": "9191f22dc443fac3", "scanner": "scanner-primary", "fingerprint": "1a34d9498cba5503", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-d97e1d3d9b4b1597", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/upsert-courses-ie.ts:234"}, "properties": {"repobilityId": "f263ea92a87a1515", "scanner": "scanner-primary", "fingerprint": "d97e1d3d9b4b1597", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-9e724a3973d78945", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/scrape-tuition-au.ts:165"}, "properties": {"repobilityId": "c83d118f1ff130d6", "scanner": "scanner-primary", "fingerprint": "9e724a3973d78945", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-05df1d3090438f6c", "level": "none", "message": {"text": "Commented-code block (6 lines) in src/app/layout.tsx:28"}, "properties": {"repobilityId": "7e5fbcd2eacc03e6", "scanner": "scanner-primary", "fingerprint": "05df1d3090438f6c", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-8a77c474f3931c3f", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/dashboard/page.tsx:226"}, "properties": {"repobilityId": "46c51ef597e751cb", "scanner": "scanner-primary", "fingerprint": "8a77c474f3931c3f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-942587fa36244287", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/api/exchange-rates/route.ts:6"}, "properties": {"repobilityId": "0fd80bee4a46879d", "scanner": "scanner-primary", "fingerprint": "942587fa36244287", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-6ba8ee8e7de95b89", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/api/checklist/route.ts:57"}, "properties": {"repobilityId": "c27cb90f6b992193", "scanner": "scanner-primary", "fingerprint": "6ba8ee8e7de95b89", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-077615dfeba3320a", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/checklist/page.tsx:174"}, "properties": {"repobilityId": "a53c0c55a07fb7d6", "scanner": "scanner-primary", "fingerprint": "077615dfeba3320a", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-786e19236c2de75b", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/lib/currency.ts:16"}, "properties": {"repobilityId": "208b537856823ef0", "scanner": "scanner-primary", "fingerprint": "786e19236c2de75b", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-d6779d7c5920ccc1", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/documents/page.tsx:137"}, "properties": {"repobilityId": "7b9f688a79bce174", "scanner": "scanner-primary", "fingerprint": "d6779d7c5920ccc1", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-806b9790eb269707", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/app/roi-explorer/RoiExplorerClient.tsx:529"}, "properties": {"repobilityId": "9f3ec2222e94be59", "scanner": "scanner-primary", "fingerprint": "806b9790eb269707", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-ef3dd23f273ffc3d", "level": "none", "message": {"text": "Commented-code block (7 lines) in src/lib/career-stage.ts:13"}, "properties": {"repobilityId": "50623c552ab87b5c", "scanner": "scanner-primary", "fingerprint": "ef3dd23f273ffc3d", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}]}]}