{"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-19f3a64e06944dcc", "name": "Stray `console.log` in TS/JS \u2014 api/generate-maths-feedback.ts:188", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 api/generate-maths-feedback.ts:188"}, "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-705d12123b80a8ae", "name": "Stray `console.log` in TS/JS \u2014 api/generate-feedback.ts:441", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 api/generate-feedback.ts:441"}, "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-c06eb20419d7d3da", "name": "Stray `console.log` in TS/JS \u2014 test/test-inline-suggestions.ts:68", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 test/test-inline-suggestions.ts:68"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-a386e01c312a81f0", "name": "Stray `console.log` in TS/JS \u2014 test/smoke-tool-use.ts:41", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 test/smoke-tool-use.ts:41"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-c7b290b5174059e7", "name": "Stray `console.log` in TS/JS \u2014 test/smoke-rubric-parse.ts:47", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 test/smoke-rubric-parse.ts:47"}, "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-d4ed31720bd75337", "name": "Stray `console.log` in TS/JS \u2014 test/evaluate-sample.ts:118", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 test/evaluate-sample.ts:118"}, "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-0e828dbdd9bb62a7", "name": "Stray `console.log` in TS/JS \u2014 scripts/generate-lti-keypair.ts:14", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/generate-lti-keypair.ts:14"}, "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-41d9cb81725cd318", "name": "Stray `console.log` in TS/JS \u2014 scripts/lti-smoke-test.ts:45", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/lti-smoke-test.ts:45"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-eb157725370db02d", "name": "Stray `console.log` in TS/JS \u2014 scripts/exam-smoke-test.ts:18", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/exam-smoke-test.ts:18"}, "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-9d8dd5ec3d999d71", "name": "Stray `console.log` in TS/JS \u2014 scripts/insights-student-smoke-test.ts:52", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/insights-student-smoke-test.ts:52"}, "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-39acf827031fb595", "name": "Stray `console.log` in TS/JS \u2014 scripts/diagnose-pcs-search.ts:34", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/diagnose-pcs-search.ts:34"}, "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-32380589e2b77703", "name": "Stray `console.log` in TS/JS \u2014 scripts/scrape-nesa-feedback.ts:184", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/scrape-nesa-feedback.ts:184"}, "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-6e54fcc376769338", "name": "Stray `console.log` in TS/JS \u2014 scripts/backfill-inline-suggestions.ts:82", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/backfill-inline-suggestions.ts:82"}, "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-db0623736f98b80a", "name": "Stray `console.log` in TS/JS \u2014 scripts/backfill-role-to-app-metadata.ts:76", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/backfill-role-to-app-metadata.ts:76"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-31b0d065ced0babf", "name": "Stray `console.log` in TS/JS \u2014 scripts/insights-teacher-smoke-test.ts:54", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/insights-teacher-smoke-test.ts:54"}, "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-48f047b7eecac384", "name": "Stray `console.log` in TS/JS \u2014 lib/anthropic-tool-call.ts:164", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 lib/anthropic-tool-call.ts:164"}, "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-3567fd0c596f9347", "name": "Stray `console.log` in TS/JS \u2014 lib/generate-inline-suggestions.ts:89", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 lib/generate-inline-suggestions.ts:89"}, "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-9710c8d059e53154", "name": "No frontend routes/components detected", "shortDescription": {"text": "No frontend routes/components detected"}, "fullDescription": {"text": "No React/Vue/Next routes were found. This is fine for backend-only repos."}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-ecd8c649c09e5dde", "name": "Insecure pattern 'node_child_process' in scripts/generate-lti-keypair.ts:3", "shortDescription": {"text": "Insecure pattern 'node_child_process' in scripts/generate-lti-keypair.ts:3"}, "fullDescription": {"text": "Found a known-risky pattern (node_child_process). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-e5f3fdf332a75d2e", "name": "Insecure pattern 'private_key_in_repo' in lib/lti/jwt.ts:25", "shortDescription": {"text": "Insecure pattern 'private_key_in_repo' in lib/lti/jwt.ts:25"}, "fullDescription": {"text": "Found a known-risky pattern (private_key_in_repo). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "critical", "confidence": 1.0}}, {"id": "scanner-4237595ef1a24795", "name": "Insecure pattern 'direct_innerhtml_assignment' in public/choose-role.html:204", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/choose-role.html:204"}, "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-032e58e07c58a804", "name": "Insecure pattern 'direct_innerhtml_assignment' in public/student.html:830", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/student.html:830"}, "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-c554ad776000fa3d", "name": "Insecure pattern 'direct_innerhtml_assignment' in public/feedback-maths.html:193", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/feedback-maths.html:193"}, "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-124604078a58a542", "name": "Insecure pattern 'direct_innerhtml_assignment' in public/class-view.html:83", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/class-view.html:83"}, "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-b24f16bf00b0198c", "name": "Insecure pattern 'direct_innerhtml_assignment' in public/submit-maths.html:188", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/submit-maths.html:188"}, "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-af2ad215f5b01322", "name": "Insecure pattern 'direct_innerhtml_assignment' in public/my-results.html:131", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/my-results.html:131"}, "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-f90df618ad1766de", "name": "Insecure pattern 'direct_innerhtml_assignment' in public/teacher-markbook.html:125", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/teacher-markbook.html:125"}, "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-3b5cb291f8c34edd", "name": "Insecure pattern 'direct_innerhtml_assignment' in public/lti-deep-link.html:91", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/lti-deep-link.html:91"}, "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-14237c27c883fbfe", "name": "Insecure pattern 'direct_innerhtml_assignment' in public/insights.html:639", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/insights.html:639"}, "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-ea237b7f03914c05", "name": "Insecure pattern 'direct_innerhtml_assignment' in public/mark-submission-maths.html:143", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/mark-submission-maths.html:143"}, "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-75c5064d781ab872", "name": "Insecure pattern 'direct_innerhtml_assignment' in public/submit.html:223", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/submit.html:223"}, "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-9ae0170d368b2477", "name": "Insecure pattern 'direct_innerhtml_assignment' in public/profile.html:171", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/profile.html:171"}, "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-9611e2fcfae69dc9", "name": "Insecure pattern 'direct_innerhtml_assignment' in public/admin.html:113", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/admin.html:113"}, "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-ca969a4423ae76f9", "name": "Insecure pattern 'direct_innerhtml_assignment' in public/task-detail.html:500", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/task-detail.html:500"}, "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-5515e4334d16217d", "name": "Insecure pattern 'direct_innerhtml_assignment' in public/new-task.html:946", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/new-task.html:946"}, "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-20e0a2fa35b4938c", "name": "Insecure pattern 'insert_adjacent_html' in public/new-task.html:781", "shortDescription": {"text": "Insecure pattern 'insert_adjacent_html' in public/new-task.html:781"}, "fullDescription": {"text": "Found a known-risky pattern (insert_adjacent_html). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-727805b5045e62c5", "name": "Insecure pattern 'direct_innerhtml_assignment' in public/mark-submission.html:295", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/mark-submission.html:295"}, "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-32cb08cfe31bff76", "name": "Insecure pattern 'direct_innerhtml_assignment' in public/feedback.html:577", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/feedback.html:577"}, "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-767469ffc00d26e1", "name": "Insecure pattern 'direct_innerhtml_assignment' in public/teacher.html:166", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/teacher.html:166"}, "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-0e5925e39644568b", "name": "Insecure pattern 'direct_innerhtml_assignment' in public/class-detail.html:175", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/class-detail.html:175"}, "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-f7fa6862de0b3df0", "name": "Insecure pattern 'direct_innerhtml_assignment' in public/js/contact-modal.js:57", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/js/contact-modal.js:57"}, "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-f8db564c78320ea2", "name": "Insecure pattern 'direct_innerhtml_assignment' in public/js/attachments.js:90", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/js/attachments.js:90"}, "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-e259aaff096e134f", "name": "Insecure pattern 'direct_innerhtml_assignment' in public/js/nesa-courses.js:87", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/js/nesa-courses.js:87"}, "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": "8 test file(s) for 92 source file(s) (ratio 0.09). Consider adding integration or unit tests for critical paths."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "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-faccb9061e9b52a0", "name": "No README detected", "shortDescription": {"text": "No README detected"}, "fullDescription": {"text": "No README file was found. Generated repos without README context are hard to operate, validate, or safely hand off."}, "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 102 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-b9088664ace7f748", "name": "Composite production-readiness gap", "shortDescription": {"text": "Composite production-readiness gap"}, "fullDescription": {"text": "Multiple low-cost hardening controls are missing together: license, operator-readme. 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-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-776e8d2566533911", "name": "Network/subprocess call without timeout or try/except \u2014 remix_pads.py:19", "shortDescription": {"text": "Network/subprocess call without timeout or try/except \u2014 remix_pads.py:19"}, "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-bc57c01fe7c4a724", "name": "Legacy-named symbol `eleven_multilingual_v2` in build_narrated.py:24", "shortDescription": {"text": "Legacy-named symbol `eleven_multilingual_v2` in build_narrated.py:24"}, "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-2e82b2e6003e8a06", "name": "Network/subprocess call without timeout or try/except \u2014 build_narrated.py:26", "shortDescription": {"text": "Network/subprocess call without timeout or try/except \u2014 build_narrated.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-8491096ebe139dc0", "name": "Network/subprocess call without timeout or try/except \u2014 build_video.py:183", "shortDescription": {"text": "Network/subprocess call without timeout or try/except \u2014 build_video.py:183"}, "fullDescription": {"text": "`subprocess.Popen(...)` 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-545f8ca3d4523e03", "name": "Network/subprocess call without timeout or try/except \u2014 build_hires.py:54", "shortDescription": {"text": "Network/subprocess call without timeout or try/except \u2014 build_hires.py:54"}, "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-ba6c63a18559acd9", "name": "Commented-code block (5 lines) in api/insights-detail.ts:116", "shortDescription": {"text": "Commented-code block (5 lines) in api/insights-detail.ts:116"}, "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-4c17a782113a7315", "name": "Commented-code block (6 lines) in api/insights-card-generate.ts:194", "shortDescription": {"text": "Commented-code block (6 lines) in api/insights-card-generate.ts:194"}, "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-87227f91e6f24f2c", "name": "Commented-code block (5 lines) in api/generate-maths-feedback.ts:292", "shortDescription": {"text": "Commented-code block (5 lines) in api/generate-maths-feedback.ts:292"}, "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-31bb8259ee8c65a2", "name": "Legacy-named symbol `avg_v1` in api/insights-student.ts:292", "shortDescription": {"text": "Legacy-named symbol `avg_v1` in api/insights-student.ts:292"}, "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-207202ba5ca49461", "name": "Commented-code block (5 lines) in api/insights-cards.ts:83", "shortDescription": {"text": "Commented-code block (5 lines) in api/insights-cards.ts:83"}, "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-3d7f20e982f498a7", "name": "Commented-code block (7 lines) in api/generate-feedback.ts:23", "shortDescription": {"text": "Commented-code block (7 lines) in api/generate-feedback.ts:23"}, "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-9d1a67704c9b9027", "name": "Commented-code block (5 lines) in api/signup.ts:13", "shortDescription": {"text": "Commented-code block (5 lines) in api/signup.ts:13"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-a89005b146b07550", "name": "Commented-code block (7 lines) in api/submit-for-marking.ts:34", "shortDescription": {"text": "Commented-code block (7 lines) in api/submit-for-marking.ts:34"}, "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-b6aad5615f854427", "name": "`fetch()` without try/.catch or AbortSignal \u2014 api/request-password-reset.ts:123", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 api/request-password-reset.ts:123"}, "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-5bc92ad46468d0aa", "name": "Commented-code block (6 lines) in api/generate-activity.ts:159", "shortDescription": {"text": "Commented-code block (6 lines) in api/generate-activity.ts:159"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-5c48ad55fe9b482f", "name": "Commented-code block (5 lines) in api/lti/launch.ts:93", "shortDescription": {"text": "Commented-code block (5 lines) in api/lti/launch.ts:93"}, "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-8565f3d36d1470cf", "name": "Commented-code block (7 lines) in test/evaluate-sample.ts:77", "shortDescription": {"text": "Commented-code block (7 lines) in test/evaluate-sample.ts:77"}, "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-c07cb5e13a5a7335", "name": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/lti-smoke-test.ts:79", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/lti-smoke-test.ts:79"}, "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-27495b08d611e82c", "name": "Commented-code block (5 lines) in scripts/insights-teacher-smoke-test.ts:204", "shortDescription": {"text": "Commented-code block (5 lines) in scripts/insights-teacher-smoke-test.ts:204"}, "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-695482a3519daece", "name": "Commented-code block (9 lines) in lib/exam-questions.ts:146", "shortDescription": {"text": "Commented-code block (9 lines) in lib/exam-questions.ts:146"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-e365699ef1eb1b8c", "name": "Commented-code block (7 lines) in lib/skill-profile.ts:41", "shortDescription": {"text": "Commented-code block (7 lines) in lib/skill-profile.ts:41"}, "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-e2570e162acc56aa", "name": "Commented-code block (5 lines) in lib/feedback-tools.ts:155", "shortDescription": {"text": "Commented-code block (5 lines) in lib/feedback-tools.ts:155"}, "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-01cfe6c5bd5774cf", "name": "`fetch()` without try/.catch or AbortSignal \u2014 lib/lti/ags.ts:16", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/lti/ags.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-01f7b280cfe886ee", "name": "`fetch()` without try/.catch or AbortSignal \u2014 lib/lti/service-auth.ts:23", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/lti/service-auth.ts:23"}, "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-9b738fb8c5dc0911", "name": "Commented-code block (5 lines) in lib/lti/user-provision.ts:93", "shortDescription": {"text": "Commented-code block (5 lines) in lib/lti/user-provision.ts:93"}, "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-18d0ad8c470fa17f", "name": "`fetch()` without try/.catch or AbortSignal \u2014 lib/lti/nrps.ts:29", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/lti/nrps.ts:29"}, "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-6f04ef4d3d664df5", "name": "Commented-code block (7 lines) in public/js/task-meta.js:11", "shortDescription": {"text": "Commented-code block (7 lines) in public/js/task-meta.js: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-2b8234a675b1d6e3", "name": "Commented-code block (5 lines) in public/js/app.js:62", "shortDescription": {"text": "Commented-code block (5 lines) in public/js/app.js:62"}, "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-468c8756a3d89568", "name": "`fetch()` without try/.catch or AbortSignal \u2014 public/js/app.js:72", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 public/js/app.js: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-bca6c87195678670", "name": "Commented-code block (5 lines) in public/js/rubric.js:19", "shortDescription": {"text": "Commented-code block (5 lines) in public/js/rubric.js:19"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-70fcae2d13c708b6", "name": "17 env vars used in code but missing from .env.example", "shortDescription": {"text": "17 env vars used in code but missing from .env.example"}, "fullDescription": {"text": "Drift between code and config docs. The first few: `ADMIN_EMAILS`, `ADMIN_USER_IDS`, `ELEVEN_API_KEY`, `ELEVEN_VOICE_ID`, `LTI_KEY_ID`, `LTI_PRIVATE_KEY`, `LTI_PRIVATE_KEY_HEX`, `LTI_SMOKE_BASE` + 9 more. Add them (with a placeholder/comment) to .env.example so onboarding doesn't break."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}]}}, "automationDetails": {"id": "repobility/18335"}, "properties": {"repository": "robsheahan/redraft", "repoUrl": "https://github.com/robsheahan/redraft", "branch": "main"}, "results": [{"ruleId": "scanner-19f3a64e06944dcc", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 api/generate-maths-feedback.ts:188"}, "properties": {"repobilityId": "5d8df48dc7561af7", "scanner": "scanner-primary", "fingerprint": "19f3a64e06944dcc", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-705d12123b80a8ae", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 api/generate-feedback.ts:441"}, "properties": {"repobilityId": "bb1fd4065de1c350", "scanner": "scanner-primary", "fingerprint": "705d12123b80a8ae", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-c06eb20419d7d3da", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 test/test-inline-suggestions.ts:68"}, "properties": {"repobilityId": "dc4b67e7a4efa3f3", "scanner": "scanner-primary", "fingerprint": "c06eb20419d7d3da", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-a386e01c312a81f0", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 test/smoke-tool-use.ts:41"}, "properties": {"repobilityId": "02a942ac1a8065c9", "scanner": "scanner-primary", "fingerprint": "a386e01c312a81f0", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-c7b290b5174059e7", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 test/smoke-rubric-parse.ts:47"}, "properties": {"repobilityId": "8d4fa81a0b702f1f", "scanner": "scanner-primary", "fingerprint": "c7b290b5174059e7", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-d4ed31720bd75337", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 test/evaluate-sample.ts:118"}, "properties": {"repobilityId": "36ba5b44c2122a78", "scanner": "scanner-primary", "fingerprint": "d4ed31720bd75337", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-0e828dbdd9bb62a7", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/generate-lti-keypair.ts:14"}, "properties": {"repobilityId": "bd978856e5d420dc", "scanner": "scanner-primary", "fingerprint": "0e828dbdd9bb62a7", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-41d9cb81725cd318", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/lti-smoke-test.ts:45"}, "properties": {"repobilityId": "894c411ee73d35eb", "scanner": "scanner-primary", "fingerprint": "41d9cb81725cd318", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-eb157725370db02d", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/exam-smoke-test.ts:18"}, "properties": {"repobilityId": "6e0b1d97f93d9a75", "scanner": "scanner-primary", "fingerprint": "eb157725370db02d", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-9d8dd5ec3d999d71", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/insights-student-smoke-test.ts:52"}, "properties": {"repobilityId": "0865d1fbaf4f937a", "scanner": "scanner-primary", "fingerprint": "9d8dd5ec3d999d71", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-39acf827031fb595", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/diagnose-pcs-search.ts:34"}, "properties": {"repobilityId": "9c7dd7ed79a0b21c", "scanner": "scanner-primary", "fingerprint": "39acf827031fb595", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-32380589e2b77703", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/scrape-nesa-feedback.ts:184"}, "properties": {"repobilityId": "fdfe72a75a0e383c", "scanner": "scanner-primary", "fingerprint": "32380589e2b77703", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-6e54fcc376769338", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/backfill-inline-suggestions.ts:82"}, "properties": {"repobilityId": "7f3a29b8afaab195", "scanner": "scanner-primary", "fingerprint": "6e54fcc376769338", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-db0623736f98b80a", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/backfill-role-to-app-metadata.ts:76"}, "properties": {"repobilityId": "ae9a5819a76246a8", "scanner": "scanner-primary", "fingerprint": "db0623736f98b80a", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-31b0d065ced0babf", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/insights-teacher-smoke-test.ts:54"}, "properties": {"repobilityId": "0e98672d1c7a18fa", "scanner": "scanner-primary", "fingerprint": "31b0d065ced0babf", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-48f047b7eecac384", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 lib/anthropic-tool-call.ts:164"}, "properties": {"repobilityId": "a32ee57c693bae19", "scanner": "scanner-primary", "fingerprint": "48f047b7eecac384", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-3567fd0c596f9347", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 lib/generate-inline-suggestions.ts:89"}, "properties": {"repobilityId": "2d671317347937bf", "scanner": "scanner-primary", "fingerprint": "3567fd0c596f9347", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-9710c8d059e53154", "level": "none", "message": {"text": "No frontend routes/components detected"}, "properties": {"repobilityId": "44ca61485762e494", "scanner": "scanner-primary", "fingerprint": "9710c8d059e53154", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["coverage"]}}, {"ruleId": "scanner-ecd8c649c09e5dde", "level": "warning", "message": {"text": "Insecure pattern 'node_child_process' in scripts/generate-lti-keypair.ts:3"}, "properties": {"repobilityId": "fd68978f8a780d1e", "scanner": "scanner-primary", "fingerprint": "ecd8c649c09e5dde", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "node_child_process"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "scripts/generate-lti-keypair.ts"}, "region": {"startLine": 3}}}]}, {"ruleId": "scanner-e5f3fdf332a75d2e", "level": "error", "message": {"text": "Insecure pattern 'private_key_in_repo' in lib/lti/jwt.ts:25"}, "properties": {"repobilityId": "053f05931d851bfe", "scanner": "scanner-primary", "fingerprint": "e5f3fdf332a75d2e", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["owasp", "private_key_in_repo"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "lib/lti/jwt.ts"}, "region": {"startLine": 25}}}]}, {"ruleId": "scanner-4237595ef1a24795", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/choose-role.html:204"}, "properties": {"repobilityId": "a614075f44016540", "scanner": "scanner-primary", "fingerprint": "4237595ef1a24795", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "public/choose-role.html"}, "region": {"startLine": 204}}}]}, {"ruleId": "scanner-032e58e07c58a804", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/student.html:830"}, "properties": {"repobilityId": "46b77d89cba8581c", "scanner": "scanner-primary", "fingerprint": "032e58e07c58a804", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "public/student.html"}, "region": {"startLine": 830}}}]}, {"ruleId": "scanner-c554ad776000fa3d", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/feedback-maths.html:193"}, "properties": {"repobilityId": "c71b08b49e5efa4d", "scanner": "scanner-primary", "fingerprint": "c554ad776000fa3d", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "public/feedback-maths.html"}, "region": {"startLine": 193}}}]}, {"ruleId": "scanner-124604078a58a542", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/class-view.html:83"}, "properties": {"repobilityId": "a0cb8a5d267f7214", "scanner": "scanner-primary", "fingerprint": "124604078a58a542", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "public/class-view.html"}, "region": {"startLine": 83}}}]}, {"ruleId": "scanner-b24f16bf00b0198c", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/submit-maths.html:188"}, "properties": {"repobilityId": "f15936cac3c80973", "scanner": "scanner-primary", "fingerprint": "b24f16bf00b0198c", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "public/submit-maths.html"}, "region": {"startLine": 188}}}]}, {"ruleId": "scanner-af2ad215f5b01322", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/my-results.html:131"}, "properties": {"repobilityId": "7d198540b3e4451a", "scanner": "scanner-primary", "fingerprint": "af2ad215f5b01322", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "public/my-results.html"}, "region": {"startLine": 131}}}]}, {"ruleId": "scanner-f90df618ad1766de", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/teacher-markbook.html:125"}, "properties": {"repobilityId": "c1a3c9c298c024c9", "scanner": "scanner-primary", "fingerprint": "f90df618ad1766de", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "public/teacher-markbook.html"}, "region": {"startLine": 125}}}]}, {"ruleId": "scanner-3b5cb291f8c34edd", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/lti-deep-link.html:91"}, "properties": {"repobilityId": "be9f1d7f237211cc", "scanner": "scanner-primary", "fingerprint": "3b5cb291f8c34edd", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "public/lti-deep-link.html"}, "region": {"startLine": 91}}}]}, {"ruleId": "scanner-14237c27c883fbfe", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/insights.html:639"}, "properties": {"repobilityId": "42fa5cb2955d8a70", "scanner": "scanner-primary", "fingerprint": "14237c27c883fbfe", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "public/insights.html"}, "region": {"startLine": 639}}}]}, {"ruleId": "scanner-ea237b7f03914c05", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/mark-submission-maths.html:143"}, "properties": {"repobilityId": "64df5a429afff397", "scanner": "scanner-primary", "fingerprint": "ea237b7f03914c05", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "public/mark-submission-maths.html"}, "region": {"startLine": 143}}}]}, {"ruleId": "scanner-75c5064d781ab872", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/submit.html:223"}, "properties": {"repobilityId": "0b9b16399894d0f0", "scanner": "scanner-primary", "fingerprint": "75c5064d781ab872", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "public/submit.html"}, "region": {"startLine": 223}}}]}, {"ruleId": "scanner-9ae0170d368b2477", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/profile.html:171"}, "properties": {"repobilityId": "abeafdd0f65a3754", "scanner": "scanner-primary", "fingerprint": "9ae0170d368b2477", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "public/profile.html"}, "region": {"startLine": 171}}}]}, {"ruleId": "scanner-9611e2fcfae69dc9", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/admin.html:113"}, "properties": {"repobilityId": "df5203f722eec321", "scanner": "scanner-primary", "fingerprint": "9611e2fcfae69dc9", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "public/admin.html"}, "region": {"startLine": 113}}}]}, {"ruleId": "scanner-ca969a4423ae76f9", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/task-detail.html:500"}, "properties": {"repobilityId": "92d5c3c53ed105e9", "scanner": "scanner-primary", "fingerprint": "ca969a4423ae76f9", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "public/task-detail.html"}, "region": {"startLine": 500}}}]}, {"ruleId": "scanner-5515e4334d16217d", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/new-task.html:946"}, "properties": {"repobilityId": "7c1fc6dd1ac3b086", "scanner": "scanner-primary", "fingerprint": "5515e4334d16217d", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "public/new-task.html"}, "region": {"startLine": 946}}}]}, {"ruleId": "scanner-20e0a2fa35b4938c", "level": "warning", "message": {"text": "Insecure pattern 'insert_adjacent_html' in public/new-task.html:781"}, "properties": {"repobilityId": "a9ab9ebbd51c0a9a", "scanner": "scanner-primary", "fingerprint": "20e0a2fa35b4938c", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "insert_adjacent_html"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "public/new-task.html"}, "region": {"startLine": 781}}}]}, {"ruleId": "scanner-727805b5045e62c5", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/mark-submission.html:295"}, "properties": {"repobilityId": "349ddaabdb15ab6e", "scanner": "scanner-primary", "fingerprint": "727805b5045e62c5", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "public/mark-submission.html"}, "region": {"startLine": 295}}}]}, {"ruleId": "scanner-32cb08cfe31bff76", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/feedback.html:577"}, "properties": {"repobilityId": "d4f467c916660c66", "scanner": "scanner-primary", "fingerprint": "32cb08cfe31bff76", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "public/feedback.html"}, "region": {"startLine": 577}}}]}, {"ruleId": "scanner-767469ffc00d26e1", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/teacher.html:166"}, "properties": {"repobilityId": "10ac1dcdacad16aa", "scanner": "scanner-primary", "fingerprint": "767469ffc00d26e1", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "public/teacher.html"}, "region": {"startLine": 166}}}]}, {"ruleId": "scanner-0e5925e39644568b", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/class-detail.html:175"}, "properties": {"repobilityId": "c2c7813315edb9e1", "scanner": "scanner-primary", "fingerprint": "0e5925e39644568b", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "public/class-detail.html"}, "region": {"startLine": 175}}}]}, {"ruleId": "scanner-f7fa6862de0b3df0", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/js/contact-modal.js:57"}, "properties": {"repobilityId": "29344a392cdc4505", "scanner": "scanner-primary", "fingerprint": "f7fa6862de0b3df0", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "public/js/contact-modal.js"}, "region": {"startLine": 57}}}]}, {"ruleId": "scanner-f8db564c78320ea2", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/js/attachments.js:90"}, "properties": {"repobilityId": "ab53f52beb6cc2e6", "scanner": "scanner-primary", "fingerprint": "f8db564c78320ea2", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "public/js/attachments.js"}, "region": {"startLine": 90}}}]}, {"ruleId": "scanner-e259aaff096e134f", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in public/js/nesa-courses.js:87"}, "properties": {"repobilityId": "b032867da288d865", "scanner": "scanner-primary", "fingerprint": "e259aaff096e134f", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "public/js/nesa-courses.js"}, "region": {"startLine": 87}}}]}, {"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-141b30a41e03817b", "level": "note", "message": {"text": "No license file detected"}, "properties": {"repobilityId": "00d36577a4c4e857", "scanner": "scanner-primary", "fingerprint": "141b30a41e03817b", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["license", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-faccb9061e9b52a0", "level": "note", "message": {"text": "No README detected"}, "properties": {"repobilityId": "aa7cc22fb243161d", "scanner": "scanner-primary", "fingerprint": "faccb9061e9b52a0", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["docs", "readme", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-3ab5d313dda8e5f9", "level": "note", "message": {"text": "Debug logging residue appears in source files"}, "properties": {"repobilityId": "5e6d26f373b6bce3", "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": "3f04e7ee707c1493", "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": "9ead878ba9cda9a5", "scanner": "scanner-primary", "fingerprint": "b9088664ace7f748", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["production-readiness", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-ea8f3013f588db25", "level": "note", "message": {"text": "Shallow git history limits provenance confidence"}, "properties": {"repobilityId": "1d8bb084a0bf3c43", "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": "b51ec773f80841d2", "scanner": "scanner-primary", "fingerprint": "8424db9c75e04ba4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["provenance", "git-history", "generated-repo-pattern"]}}, {"ruleId": "scanner-776e8d2566533911", "level": "warning", "message": {"text": "Network/subprocess call without timeout or try/except \u2014 remix_pads.py:19"}, "properties": {"repobilityId": "7cc29948160be531", "scanner": "scanner-primary", "fingerprint": "776e8d2566533911", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-bc57c01fe7c4a724", "level": "note", "message": {"text": "Legacy-named symbol `eleven_multilingual_v2` in build_narrated.py:24"}, "properties": {"repobilityId": "d294390940b78b2a", "scanner": "scanner-primary", "fingerprint": "bc57c01fe7c4a724", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-2e82b2e6003e8a06", "level": "warning", "message": {"text": "Network/subprocess call without timeout or try/except \u2014 build_narrated.py:26"}, "properties": {"repobilityId": "b1398cf0da8af650", "scanner": "scanner-primary", "fingerprint": "2e82b2e6003e8a06", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-8491096ebe139dc0", "level": "warning", "message": {"text": "Network/subprocess call without timeout or try/except \u2014 build_video.py:183"}, "properties": {"repobilityId": "6d00c8c5de32f1b0", "scanner": "scanner-primary", "fingerprint": "8491096ebe139dc0", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-545f8ca3d4523e03", "level": "warning", "message": {"text": "Network/subprocess call without timeout or try/except \u2014 build_hires.py:54"}, "properties": {"repobilityId": "eedad8e928292df1", "scanner": "scanner-primary", "fingerprint": "545f8ca3d4523e03", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-ba6c63a18559acd9", "level": "none", "message": {"text": "Commented-code block (5 lines) in api/insights-detail.ts:116"}, "properties": {"repobilityId": "9160d690304969ea", "scanner": "scanner-primary", "fingerprint": "ba6c63a18559acd9", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-4c17a782113a7315", "level": "none", "message": {"text": "Commented-code block (6 lines) in api/insights-card-generate.ts:194"}, "properties": {"repobilityId": "4836694bb258b743", "scanner": "scanner-primary", "fingerprint": "4c17a782113a7315", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-87227f91e6f24f2c", "level": "none", "message": {"text": "Commented-code block (5 lines) in api/generate-maths-feedback.ts:292"}, "properties": {"repobilityId": "eece2c8591b5e76a", "scanner": "scanner-primary", "fingerprint": "87227f91e6f24f2c", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-31bb8259ee8c65a2", "level": "note", "message": {"text": "Legacy-named symbol `avg_v1` in api/insights-student.ts:292"}, "properties": {"repobilityId": "2006a2301892167c", "scanner": "scanner-primary", "fingerprint": "31bb8259ee8c65a2", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-207202ba5ca49461", "level": "none", "message": {"text": "Commented-code block (5 lines) in api/insights-cards.ts:83"}, "properties": {"repobilityId": "277055b78ba1f9c6", "scanner": "scanner-primary", "fingerprint": "207202ba5ca49461", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-3d7f20e982f498a7", "level": "none", "message": {"text": "Commented-code block (7 lines) in api/generate-feedback.ts:23"}, "properties": {"repobilityId": "b228ba157bb851b0", "scanner": "scanner-primary", "fingerprint": "3d7f20e982f498a7", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-9d1a67704c9b9027", "level": "none", "message": {"text": "Commented-code block (5 lines) in api/signup.ts:13"}, "properties": {"repobilityId": "3fde55f82a6e3662", "scanner": "scanner-primary", "fingerprint": "9d1a67704c9b9027", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-a89005b146b07550", "level": "none", "message": {"text": "Commented-code block (7 lines) in api/submit-for-marking.ts:34"}, "properties": {"repobilityId": "f738e835472618c8", "scanner": "scanner-primary", "fingerprint": "a89005b146b07550", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-b6aad5615f854427", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 api/request-password-reset.ts:123"}, "properties": {"repobilityId": "68ebd03ac3d15f2b", "scanner": "scanner-primary", "fingerprint": "b6aad5615f854427", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-5bc92ad46468d0aa", "level": "none", "message": {"text": "Commented-code block (6 lines) in api/generate-activity.ts:159"}, "properties": {"repobilityId": "6279647226399649", "scanner": "scanner-primary", "fingerprint": "5bc92ad46468d0aa", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-5c48ad55fe9b482f", "level": "none", "message": {"text": "Commented-code block (5 lines) in api/lti/launch.ts:93"}, "properties": {"repobilityId": "e935afecd6d9c6cd", "scanner": "scanner-primary", "fingerprint": "5c48ad55fe9b482f", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-8565f3d36d1470cf", "level": "none", "message": {"text": "Commented-code block (7 lines) in test/evaluate-sample.ts:77"}, "properties": {"repobilityId": "1583c5e89f052954", "scanner": "scanner-primary", "fingerprint": "8565f3d36d1470cf", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-c07cb5e13a5a7335", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 scripts/lti-smoke-test.ts:79"}, "properties": {"repobilityId": "e8cda5de8709007b", "scanner": "scanner-primary", "fingerprint": "c07cb5e13a5a7335", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-27495b08d611e82c", "level": "none", "message": {"text": "Commented-code block (5 lines) in scripts/insights-teacher-smoke-test.ts:204"}, "properties": {"repobilityId": "179d78951aa7ca37", "scanner": "scanner-primary", "fingerprint": "27495b08d611e82c", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-695482a3519daece", "level": "none", "message": {"text": "Commented-code block (9 lines) in lib/exam-questions.ts:146"}, "properties": {"repobilityId": "263c9ae5be6b5bcc", "scanner": "scanner-primary", "fingerprint": "695482a3519daece", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-e365699ef1eb1b8c", "level": "none", "message": {"text": "Commented-code block (7 lines) in lib/skill-profile.ts:41"}, "properties": {"repobilityId": "ea860e3f71b2343e", "scanner": "scanner-primary", "fingerprint": "e365699ef1eb1b8c", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-e2570e162acc56aa", "level": "none", "message": {"text": "Commented-code block (5 lines) in lib/feedback-tools.ts:155"}, "properties": {"repobilityId": "ab169321ba4769a9", "scanner": "scanner-primary", "fingerprint": "e2570e162acc56aa", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-01cfe6c5bd5774cf", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/lti/ags.ts:16"}, "properties": {"repobilityId": "81c7c7a1b02fe291", "scanner": "scanner-primary", "fingerprint": "01cfe6c5bd5774cf", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-01f7b280cfe886ee", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/lti/service-auth.ts:23"}, "properties": {"repobilityId": "1111708886eab434", "scanner": "scanner-primary", "fingerprint": "01f7b280cfe886ee", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-9b738fb8c5dc0911", "level": "none", "message": {"text": "Commented-code block (5 lines) in lib/lti/user-provision.ts:93"}, "properties": {"repobilityId": "638120f67b015610", "scanner": "scanner-primary", "fingerprint": "9b738fb8c5dc0911", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-18d0ad8c470fa17f", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 lib/lti/nrps.ts:29"}, "properties": {"repobilityId": "806596ac09fd7883", "scanner": "scanner-primary", "fingerprint": "18d0ad8c470fa17f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-6f04ef4d3d664df5", "level": "none", "message": {"text": "Commented-code block (7 lines) in public/js/task-meta.js:11"}, "properties": {"repobilityId": "d019499510eb1bc3", "scanner": "scanner-primary", "fingerprint": "6f04ef4d3d664df5", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-2b8234a675b1d6e3", "level": "none", "message": {"text": "Commented-code block (5 lines) in public/js/app.js:62"}, "properties": {"repobilityId": "01ab48015afe9d74", "scanner": "scanner-primary", "fingerprint": "2b8234a675b1d6e3", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-468c8756a3d89568", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 public/js/app.js:72"}, "properties": {"repobilityId": "239e34f182ce67fd", "scanner": "scanner-primary", "fingerprint": "468c8756a3d89568", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-bca6c87195678670", "level": "none", "message": {"text": "Commented-code block (5 lines) in public/js/rubric.js:19"}, "properties": {"repobilityId": "d91d79ecf3009005", "scanner": "scanner-primary", "fingerprint": "bca6c87195678670", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-70fcae2d13c708b6", "level": "note", "message": {"text": "17 env vars used in code but missing from .env.example"}, "properties": {"repobilityId": "f21675bed249619c", "scanner": "scanner-primary", "fingerprint": "70fcae2d13c708b6", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "config-drift"]}}]}]}