{"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-e87aad74160c5d91", "name": "Possibly dead Python function: nll", "shortDescription": {"text": "Possibly dead Python function: nll"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-21b65277abe8b9e1", "name": "Possibly dead Python function: compute_loss", "shortDescription": {"text": "Possibly dead Python function: compute_loss"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-d82ecdca73844945", "name": "Possibly dead Python function: compute_metrics", "shortDescription": {"text": "Possibly dead Python function: compute_metrics"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-ed39159368e2a5e2", "name": "Possibly dead Python function: loss", "shortDescription": {"text": "Possibly dead Python function: loss"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-3ac0cfde51b532ec", "name": "Possibly dead Python function: produce_all", "shortDescription": {"text": "Possibly dead Python function: produce_all"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-372c36e349541451", "name": "Possibly dead Python function: produce_one", "shortDescription": {"text": "Possibly dead Python function: produce_one"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-035d1749f566796d", "name": "Possibly dead Python function: produce", "shortDescription": {"text": "Possibly dead Python function: produce"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-a365309ca2422481", "name": "Possibly dead Python function: produce", "shortDescription": {"text": "Possibly dead Python function: produce"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-ab084bb482b91093", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/components/auth-button.tsx:16", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/components/auth-button.tsx:16"}, "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-32db330f969c3e8f", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/components/prediction-row.tsx:36", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/components/prediction-row.tsx:36"}, "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-308dc344368101e7", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/app/watchlist/page.tsx:140", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/app/watchlist/page.tsx:140"}, "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-714c31ca9f474ae6", "name": "Docker base image is tag-pinned but not digest-pinned: python:3.12-slim", "shortDescription": {"text": "Docker base image is tag-pinned but not digest-pinned: python:3.12-slim"}, "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-ea3b5e389d8c9c0f", "name": "Low test-to-source ratio", "shortDescription": {"text": "Low test-to-source ratio"}, "fullDescription": {"text": "19 tests / 87 src (ratio 0.22)."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-141b30a41e03817b", "name": "No license file detected", "shortDescription": {"text": "No license file detected"}, "fullDescription": {"text": "No LICENSE/COPYING/NOTICE file was found. Generated repositories often omit licensing, which blocks reuse and automated intake."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-3ab5d313dda8e5f9", "name": "Debug logging residue appears in source files", "shortDescription": {"text": "Debug logging residue appears in source files"}, "fullDescription": {"text": "Found 152 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-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-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-44b6bc6a46006b06", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/lib/api.ts:26", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/lib/api.ts:26"}, "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-d1cc69429cd80bb4", "name": "Legacy-named symbol `tft_v2` in ml/notebooks/04_lgbm_training.py:60", "shortDescription": {"text": "Legacy-named symbol `tft_v2` in ml/notebooks/04_lgbm_training.py:60"}, "fullDescription": {"text": "Names with suffixes like `_old`, `_v1`, `_deprecated` usually indicate replaced-but-not-removed code (typical AI-coder leftover). Confirm and delete, or rename if it's the active version."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-e3a9c0603abf171d", "name": "Commented-code block (8 lines) in ml/notebooks/04_lgbm_training.py:9", "shortDescription": {"text": "Commented-code block (8 lines) in ml/notebooks/04_lgbm_training.py:9"}, "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-eb6c4c9b7da0011e", "name": "Commented-code block (8 lines) in ml/notebooks/06_sentiment_diagnostic.py:9", "shortDescription": {"text": "Commented-code block (8 lines) in ml/notebooks/06_sentiment_diagnostic.py:9"}, "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-b1ff6cd1ee0805ac", "name": "Commented-code block (8 lines) in ml/notebooks/02_sentiment_finetune.py:11", "shortDescription": {"text": "Commented-code block (8 lines) in ml/notebooks/02_sentiment_finetune.py:11"}, "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-070f1256ee5e13eb", "name": "Network/subprocess call without timeout or try/except \u2014 ml/notebooks/02_sentiment_finetune.py:38", "shortDescription": {"text": "Network/subprocess call without timeout or try/except \u2014 ml/notebooks/02_sentiment_finetune.py:38"}, "fullDescription": {"text": "`subprocess.run(...)` here lacks both a `timeout=` arg and an enclosing try/except. This is exactly the class of bug that took down our git-clone earlier (HTTP/2 stream cancel surfaced as a fatal). Add a `timeout=` and wrap in try/except, or use a wrapper that retries."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-e33bbcacd8a87df2", "name": "Legacy-named symbol `tft_v1` in ml/notebooks/03_tft_training_kaggle.py:45", "shortDescription": {"text": "Legacy-named symbol `tft_v1` in ml/notebooks/03_tft_training_kaggle.py:45"}, "fullDescription": {"text": "Names with suffixes like `_old`, `_v1`, `_deprecated` usually indicate replaced-but-not-removed code (typical AI-coder leftover). Confirm and delete, or rename if it's the active version."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-6fefeb7e3a50822f", "name": "Commented-code block (5 lines) in ml/notebooks/03_tft_training_kaggle.py:74", "shortDescription": {"text": "Commented-code block (5 lines) in ml/notebooks/03_tft_training_kaggle.py:74"}, "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-8507748a3bddd7de", "name": "Network/subprocess call without timeout or try/except \u2014 ml/notebooks/03_tft_training_kaggle.py:26", "shortDescription": {"text": "Network/subprocess call without timeout or try/except \u2014 ml/notebooks/03_tft_training_kaggle.py:26"}, "fullDescription": {"text": "`subprocess.run(...)` here lacks both a `timeout=` arg and an enclosing try/except. This is exactly the class of bug that took down our git-clone earlier (HTTP/2 stream cancel surfaced as a fatal). Add a `timeout=` and wrap in try/except, or use a wrapper that retries."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-56e920b31555a663", "name": "Legacy-named symbol `tft_v2` in ml/notebooks/03_tft_training.py:59", "shortDescription": {"text": "Legacy-named symbol `tft_v2` in ml/notebooks/03_tft_training.py:59"}, "fullDescription": {"text": "Names with suffixes like `_old`, `_v1`, `_deprecated` usually indicate replaced-but-not-removed code (typical AI-coder leftover). Confirm and delete, or rename if it's the active version."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-ac663a291cf70ec6", "name": "Commented-code block (5 lines) in ml/notebooks/03_tft_training.py:18", "shortDescription": {"text": "Commented-code block (5 lines) in ml/notebooks/03_tft_training.py:18"}, "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-1f9cdd73b1fab3fd", "name": "Network/subprocess call without timeout or try/except \u2014 ml/notebooks/03_tft_training.py:43", "shortDescription": {"text": "Network/subprocess call without timeout or try/except \u2014 ml/notebooks/03_tft_training.py:43"}, "fullDescription": {"text": "`subprocess.run(...)` here lacks both a `timeout=` arg and an enclosing try/except. This is exactly the class of bug that took down our git-clone earlier (HTTP/2 stream cancel surfaced as a fatal). Add a `timeout=` and wrap in try/except, or use a wrapper that retries."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-3438d84c9425652b", "name": "Legacy-named symbol `tft_v1` in backend/scripts/seed_predictions.py:5", "shortDescription": {"text": "Legacy-named symbol `tft_v1` in backend/scripts/seed_predictions.py:5"}, "fullDescription": {"text": "Names with suffixes like `_old`, `_v1`, `_deprecated` usually indicate replaced-but-not-removed code (typical AI-coder leftover). Confirm and delete, or rename if it's the active version."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-b334d875f2339fa1", "name": "5 env vars used in code but missing from .env.example", "shortDescription": {"text": "5 env vars used in code but missing from .env.example"}, "fullDescription": {"text": "Drift between code and config docs. The first few: `MODEL_VERSION`, `NEXT_PUBLIC_CI_BUILD`, `NEXT_RUNTIME`, `NODE_ENV`, `SENTRY_AUTH_TOKEN`. Add them (with a placeholder/comment) to .env.example so onboarding doesn't break."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-2c04133e54348533", "name": "Near-duplicate function bodies in 2 places", "shortDescription": {"text": "Near-duplicate function bodies in 2 places"}, "fullDescription": {"text": "Functions with the same first-5-line body hash:\nml/notebooks/04_lgbm_training.py:apply_temperature, ml/notebooks/06_sentiment_diagnostic.py:apply_temperature\n\nThis is *the* AI-coder failure mode (4\u00d7 more duplication in vibe-coded repos \u2014 see https://jw.hn/ai-code-hygiene). Consolidate or document why they're separate."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-be46ea126aa5d8dc", "name": "Near-duplicate function bodies in 3 places", "shortDescription": {"text": "Near-duplicate function bodies in 3 places"}, "fullDescription": {"text": "Functions with the same first-5-line body hash:\nbackend/services/sentiment_label.py:label_batch, backend/services/sentiment_label.py:label_batch, backend/services/sentiment_label.py:label_batch\n\nThis is *the* AI-coder failure mode (4\u00d7 more duplication in vibe-coded repos \u2014 see https://jw.hn/ai-code-hygiene). Consolidate or document why they're separate."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-70806e9ce848ad87", "name": "Unused endpoint: GET /predictions", "shortDescription": {"text": "Unused endpoint: GET /predictions"}, "fullDescription": {"text": "`backend/api/predictions.py` declares `GET /predictions` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-b3c395a9507edb1e", "name": "Unused endpoint: GET /stocks/{symbol}/history", "shortDescription": {"text": "Unused endpoint: GET /stocks/{symbol}/history"}, "fullDescription": {"text": "`backend/api/stocks.py` declares `GET /stocks/{symbol}/history` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-a20634ec0c061386", "name": "Unused endpoint: GET /accuracy", "shortDescription": {"text": "Unused endpoint: GET /accuracy"}, "fullDescription": {"text": "`backend/api/stocks.py` declares `GET /accuracy` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-f22b2880ee0bfd44", "name": "Unused endpoint: GET /news", "shortDescription": {"text": "Unused endpoint: GET /news"}, "fullDescription": {"text": "`backend/api/news.py` declares `GET /news` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}]}}, "automationDetails": {"id": "repobility/21431"}, "properties": {"repository": "toilact/TradePilot", "repoUrl": "https://github.com/toilact/TradePilot", "branch": "main"}, "results": [{"ruleId": "scanner-e87aad74160c5d91", "level": "note", "message": {"text": "Possibly dead Python function: nll"}, "properties": {"repobilityId": "5752c7fee5c8e0a5", "scanner": "scanner-primary", "fingerprint": "e87aad74160c5d91", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "ml/notebooks/04_lgbm_training.py:186"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-21b65277abe8b9e1", "level": "note", "message": {"text": "Possibly dead Python function: compute_loss"}, "properties": {"repobilityId": "70b270f82fffe454", "scanner": "scanner-primary", "fingerprint": "21b65277abe8b9e1", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "ml/notebooks/02_sentiment_finetune.py:203"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-d82ecdca73844945", "level": "note", "message": {"text": "Possibly dead Python function: compute_metrics"}, "properties": {"repobilityId": "601ab656627d3342", "scanner": "scanner-primary", "fingerprint": "d82ecdca73844945", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "ml/notebooks/02_sentiment_finetune.py:211"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-ed39159368e2a5e2", "level": "note", "message": {"text": "Possibly dead Python function: loss"}, "properties": {"repobilityId": "71d633161afe5e63", "scanner": "scanner-primary", "fingerprint": "ed39159368e2a5e2", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "ml/notebooks/03_tft_training.py:82"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-3ac0cfde51b532ec", "level": "note", "message": {"text": "Possibly dead Python function: produce_all"}, "properties": {"repobilityId": "e27d4bfd4fc331cc", "scanner": "scanner-primary", "fingerprint": "3ac0cfde51b532ec", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/api/predictions.py:20"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-372c36e349541451", "level": "note", "message": {"text": "Possibly dead Python function: produce_one"}, "properties": {"repobilityId": "492d2cdc097f309f", "scanner": "scanner-primary", "fingerprint": "372c36e349541451", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/api/predictions.py:27"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-035d1749f566796d", "level": "note", "message": {"text": "Possibly dead Python function: produce"}, "properties": {"repobilityId": "2b7be8fdcef56a01", "scanner": "scanner-primary", "fingerprint": "035d1749f566796d", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/api/stocks.py:25"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-a365309ca2422481", "level": "note", "message": {"text": "Possibly dead Python function: produce"}, "properties": {"repobilityId": "2b7be8fdcef56a01", "scanner": "scanner-primary", "fingerprint": "a365309ca2422481", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/api/news.py:21"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-ab084bb482b91093", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/components/auth-button.tsx:16"}, "properties": {"repobilityId": "ad54771754147eea", "scanner": "scanner-primary", "fingerprint": "ab084bb482b91093", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-32db330f969c3e8f", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/components/prediction-row.tsx:36"}, "properties": {"repobilityId": "540c8962da48e605", "scanner": "scanner-primary", "fingerprint": "32db330f969c3e8f", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-308dc344368101e7", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/app/watchlist/page.tsx:140"}, "properties": {"repobilityId": "de679a8fbb7a64d0", "scanner": "scanner-primary", "fingerprint": "308dc344368101e7", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-714c31ca9f474ae6", "level": "note", "message": {"text": "Docker base image is tag-pinned but not digest-pinned: python:3.12-slim"}, "properties": {"repobilityId": "f19b8eb3a0f1adb7", "scanner": "scanner-primary", "fingerprint": "714c31ca9f474ae6", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "docker", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/Dockerfile"}, "region": {"startLine": 4}}}]}, {"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-ea3b5e389d8c9c0f", "level": "note", "message": {"text": "Low test-to-source ratio"}, "properties": {"repobilityId": "ef7b2552cc00a375", "scanner": "scanner-primary", "fingerprint": "ea3b5e389d8c9c0f", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["tests"]}}, {"ruleId": "scanner-141b30a41e03817b", "level": "note", "message": {"text": "No license file detected"}, "properties": {"repobilityId": "6d3cad0c7ea24ba2", "scanner": "scanner-primary", "fingerprint": "141b30a41e03817b", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["license", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-3ab5d313dda8e5f9", "level": "note", "message": {"text": "Debug logging residue appears in source files"}, "properties": {"repobilityId": "aceb4cb63ba6b7f5", "scanner": "scanner-primary", "fingerprint": "3ab5d313dda8e5f9", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["debug", "cleanup", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-2d0c7b7ab8f8aacf", "level": "warning", "message": {"text": "Critical user flow still appears backed by mock or placeholder data"}, "properties": {"repobilityId": "0498d24cb488f86f", "scanner": "scanner-primary", "fingerprint": "2d0c7b7ab8f8aacf", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "mock-data", "critical-flow", "generated-repo-pattern"]}}, {"ruleId": "scanner-ea8f3013f588db25", "level": "note", "message": {"text": "Shallow git history limits provenance confidence"}, "properties": {"repobilityId": "a31c0a15ba083749", "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": "408b31299380a2ec", "scanner": "scanner-primary", "fingerprint": "8424db9c75e04ba4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["provenance", "git-history", "generated-repo-pattern"]}}, {"ruleId": "scanner-44b6bc6a46006b06", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/lib/api.ts:26"}, "properties": {"repobilityId": "a09d899e4391f189", "scanner": "scanner-primary", "fingerprint": "44b6bc6a46006b06", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-d1cc69429cd80bb4", "level": "note", "message": {"text": "Legacy-named symbol `tft_v2` in ml/notebooks/04_lgbm_training.py:60"}, "properties": {"repobilityId": "7f019515ef188b0f", "scanner": "scanner-primary", "fingerprint": "d1cc69429cd80bb4", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-e3a9c0603abf171d", "level": "none", "message": {"text": "Commented-code block (8 lines) in ml/notebooks/04_lgbm_training.py:9"}, "properties": {"repobilityId": "7b6bcdd5c782fe11", "scanner": "scanner-primary", "fingerprint": "e3a9c0603abf171d", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-eb6c4c9b7da0011e", "level": "none", "message": {"text": "Commented-code block (8 lines) in ml/notebooks/06_sentiment_diagnostic.py:9"}, "properties": {"repobilityId": "5e96e063f3e1f271", "scanner": "scanner-primary", "fingerprint": "eb6c4c9b7da0011e", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-b1ff6cd1ee0805ac", "level": "none", "message": {"text": "Commented-code block (8 lines) in ml/notebooks/02_sentiment_finetune.py:11"}, "properties": {"repobilityId": "9534a79b2005fbce", "scanner": "scanner-primary", "fingerprint": "b1ff6cd1ee0805ac", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-070f1256ee5e13eb", "level": "warning", "message": {"text": "Network/subprocess call without timeout or try/except \u2014 ml/notebooks/02_sentiment_finetune.py:38"}, "properties": {"repobilityId": "8f337bbd38625bf6", "scanner": "scanner-primary", "fingerprint": "070f1256ee5e13eb", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-e33bbcacd8a87df2", "level": "note", "message": {"text": "Legacy-named symbol `tft_v1` in ml/notebooks/03_tft_training_kaggle.py:45"}, "properties": {"repobilityId": "57bb711c276db4ea", "scanner": "scanner-primary", "fingerprint": "e33bbcacd8a87df2", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-6fefeb7e3a50822f", "level": "none", "message": {"text": "Commented-code block (5 lines) in ml/notebooks/03_tft_training_kaggle.py:74"}, "properties": {"repobilityId": "e57b9f902907db37", "scanner": "scanner-primary", "fingerprint": "6fefeb7e3a50822f", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-8507748a3bddd7de", "level": "warning", "message": {"text": "Network/subprocess call without timeout or try/except \u2014 ml/notebooks/03_tft_training_kaggle.py:26"}, "properties": {"repobilityId": "cc97677c01cd9789", "scanner": "scanner-primary", "fingerprint": "8507748a3bddd7de", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-56e920b31555a663", "level": "note", "message": {"text": "Legacy-named symbol `tft_v2` in ml/notebooks/03_tft_training.py:59"}, "properties": {"repobilityId": "84a1fd02f177bee8", "scanner": "scanner-primary", "fingerprint": "56e920b31555a663", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-ac663a291cf70ec6", "level": "none", "message": {"text": "Commented-code block (5 lines) in ml/notebooks/03_tft_training.py:18"}, "properties": {"repobilityId": "3cc9546b78f42f2f", "scanner": "scanner-primary", "fingerprint": "ac663a291cf70ec6", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-1f9cdd73b1fab3fd", "level": "warning", "message": {"text": "Network/subprocess call without timeout or try/except \u2014 ml/notebooks/03_tft_training.py:43"}, "properties": {"repobilityId": "ad5a766caa95dfb3", "scanner": "scanner-primary", "fingerprint": "1f9cdd73b1fab3fd", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-3438d84c9425652b", "level": "note", "message": {"text": "Legacy-named symbol `tft_v1` in backend/scripts/seed_predictions.py:5"}, "properties": {"repobilityId": "fd641c718b086053", "scanner": "scanner-primary", "fingerprint": "3438d84c9425652b", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-b334d875f2339fa1", "level": "note", "message": {"text": "5 env vars used in code but missing from .env.example"}, "properties": {"repobilityId": "faa38682016f5d53", "scanner": "scanner-primary", "fingerprint": "b334d875f2339fa1", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "config-drift"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "673e4c306ad632d2", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "c6fbca65d6582680", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "8711224428cae437", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-be46ea126aa5d8dc", "level": "note", "message": {"text": "Near-duplicate function bodies in 3 places"}, "properties": {"repobilityId": "d77c927091005e28", "scanner": "scanner-primary", "fingerprint": "be46ea126aa5d8dc", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-be46ea126aa5d8dc", "level": "note", "message": {"text": "Near-duplicate function bodies in 3 places"}, "properties": {"repobilityId": "e81f36bac259e1dc", "scanner": "scanner-primary", "fingerprint": "be46ea126aa5d8dc", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-70806e9ce848ad87", "level": "note", "message": {"text": "Unused endpoint: GET /predictions"}, "properties": {"repobilityId": "70c542242ca4c22d", "scanner": "scanner-primary", "fingerprint": "70806e9ce848ad87", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-b3c395a9507edb1e", "level": "note", "message": {"text": "Unused endpoint: GET /stocks/{symbol}/history"}, "properties": {"repobilityId": "9d9e2390f4dfdfbf", "scanner": "scanner-primary", "fingerprint": "b3c395a9507edb1e", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-a20634ec0c061386", "level": "note", "message": {"text": "Unused endpoint: GET /accuracy"}, "properties": {"repobilityId": "622e9f353a68b363", "scanner": "scanner-primary", "fingerprint": "a20634ec0c061386", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-f22b2880ee0bfd44", "level": "note", "message": {"text": "Unused endpoint: GET /news"}, "properties": {"repobilityId": "6c9fa8977f11888a", "scanner": "scanner-primary", "fingerprint": "f22b2880ee0bfd44", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}]}]}