{"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-5dfc79a2212e5534", "name": "Possibly dead Python function: file_hash", "shortDescription": {"text": "Possibly dead Python function: file_hash"}, "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-2e3f131ec420c6ba", "name": "Possibly dead Python function: create_secure_file", "shortDescription": {"text": "Possibly dead Python function: create_secure_file"}, "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-c952e77ea0665c92", "name": "Possibly dead Python function: is_git_repo", "shortDescription": {"text": "Possibly dead Python function: is_git_repo"}, "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-d0be066c42f43fa9", "name": "Possibly dead Python function: git_graceful_operation", "shortDescription": {"text": "Possibly dead Python function: git_graceful_operation"}, "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-c86a12a49480cd7c", "name": "Possibly dead Python function: extract_ai_replacement_vocab", "shortDescription": {"text": "Possibly dead Python function: extract_ai_replacement_vocab"}, "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-60d6219320897c52", "name": "Possibly dead Python function: extract_strong_chapter_end_hooks", "shortDescription": {"text": "Possibly dead Python function: extract_strong_chapter_end_hooks"}, "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-74ff8f89459df959", "name": "Possibly dead Python function: extract_emotion_earned_forced", "shortDescription": {"text": "Possibly dead Python function: extract_emotion_earned_forced"}, "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-a824f147491908f7", "name": "Possibly dead Python function: extract_canon_violations", "shortDescription": {"text": "Possibly dead Python function: extract_canon_violations"}, "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-80c75eaef67320a8", "name": "Possibly dead Python function: list_snapshots", "shortDescription": {"text": "Possibly dead Python function: list_snapshots"}, "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-39873e4d19587389", "name": "Possibly dead Python function: apply_confidence_filter", "shortDescription": {"text": "Possibly dead Python function: apply_confidence_filter"}, "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-537f5b1e55e1fccf", "name": "Possibly dead Python function: cmd_sync_agents", "shortDescription": {"text": "Possibly dead Python function: cmd_sync_agents"}, "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-6eb44a80d883685d", "name": "Possibly dead Python function: cmd_sync_cache", "shortDescription": {"text": "Possibly dead Python function: cmd_sync_cache"}, "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-1196e02236669725", "name": "Possibly dead Python function: cmd_normalize_checker_scores", "shortDescription": {"text": "Possibly dead Python function: cmd_normalize_checker_scores"}, "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-04a4b2d52d340d14", "name": "`truncate` class without `title=` for hover reveal \u2014 webnovel-writer/dashboard/frontend/src/App.jsx:212", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 webnovel-writer/dashboard/frontend/src/App.jsx:212"}, "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-f10351888efb2a4b", "name": "Insecure pattern 'cors_wildcard' in webnovel-writer/dashboard/app.py:65", "shortDescription": {"text": "Insecure pattern 'cors_wildcard' in webnovel-writer/dashboard/app.py:65"}, "fullDescription": {"text": "Found a known-risky pattern (cors_wildcard). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-6372cebde0220094", "name": "No auth library detected", "shortDescription": {"text": "No auth library detected"}, "fullDescription": {"text": "The scanner did not find any standard auth library (JWT, OAuth, NextAuth, Auth0, etc.). The repo has auth/admin/session surface indicators, so auth may live in custom code, in a separate service, or be missing."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-0d0af982afccb800", "name": "GitHub Action is tag-pinned rather than SHA-pinned", "shortDescription": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "fullDescription": {"text": "actions/checkout@v4 can move without a code change in this repo. Pin third-party actions to a reviewed 40-character commit SHA."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "low", "confidence": 1.0}}, {"id": "scanner-1ecc4cc96fdccd9a", "name": "GitHub Action is tag-pinned rather than SHA-pinned", "shortDescription": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "fullDescription": {"text": "actions/checkout@v4 can move without a code change in this repo. Pin third-party actions to a reviewed 40-character commit SHA."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "low", "confidence": 1.0}}, {"id": "scanner-f2da95b6b75dbd8c", "name": "GitHub Actions workflow grants broad write permissions", "shortDescription": {"text": "GitHub Actions workflow grants broad write permissions"}, "fullDescription": {"text": "CI tokens with write permissions increase blast radius when an action, dependency, or PR workflow is compromised. Prefer job-level least-privilege permissions."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-e14dc728a6208329", "name": "Very large file: webnovel-writer/scripts/workflow_manager.py (1505 lines)", "shortDescription": {"text": "Very large file: webnovel-writer/scripts/workflow_manager.py (1505 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-5b1f03a2499f2906", "name": "Very large file: webnovel-writer/scripts/hygiene_check.py (4514 lines)", "shortDescription": {"text": "Very large file: webnovel-writer/scripts/hygiene_check.py (4514 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-6bbb4dfc5f411cfe", "name": "Very large file: webnovel-writer/scripts/external_review.py (2630 lines)", "shortDescription": {"text": "Very large file: webnovel-writer/scripts/external_review.py (2630 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-dd651c7a7a8e9fe6", "name": "Very large file: webnovel-writer/scripts/post_draft_check.py (1058 lines)", "shortDescription": {"text": "Very large file: webnovel-writer/scripts/post_draft_check.py (1058 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-2cddcdf938be7a83", "name": "Very large file: webnovel-writer/scripts/data_modules/chapter_audit.py (3034 lines)", "shortDescription": {"text": "Very large file: webnovel-writer/scripts/data_modules/chapter_audit.py (3034 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-a04f078eace390ed", "name": "Very large file: webnovel-writer/scripts/data_modules/rag_adapter.py (1663 lines)", "shortDescription": {"text": "Very large file: webnovel-writer/scripts/data_modules/rag_adapter.py (1663 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-467fd5251b86ce24", "name": "Very large file: webnovel-writer/scripts/data_modules/state_manager.py (2836 lines)", "shortDescription": {"text": "Very large file: webnovel-writer/scripts/data_modules/state_manager.py (2836 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-233a1f8425d54415", "name": "Very large file: webnovel-writer/scripts/data_modules/index_manager.py (1536 lines)", "shortDescription": {"text": "Very large file: webnovel-writer/scripts/data_modules/index_manager.py (1536 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-63f798a05c88710c", "name": "Very large file: webnovel-writer/scripts/data_modules/webnovel.py (1408 lines)", "shortDescription": {"text": "Very large file: webnovel-writer/scripts/data_modules/webnovel.py (1408 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-b6541f20857e22a8", "name": "Very large file: webnovel-writer/scripts/data_modules/tests/test_data_modules.py (1414 lines)", "shortDescription": {"text": "Very large file: webnovel-writer/scripts/data_modules/tests/test_data_modules.py (1414 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-db4f5c200261afd7", "name": "Very large file: webnovel-writer/scripts/data_modules/tests/test_chapter_audit.py (1980 lines)", "shortDescription": {"text": "Very large file: webnovel-writer/scripts/data_modules/tests/test_chapter_audit.py (1980 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-3ab5d313dda8e5f9", "name": "Debug logging residue appears in source files", "shortDescription": {"text": "Debug logging residue appears in source files"}, "fullDescription": {"text": "Found 608 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-87ca2d277fcdc8f3", "name": "Agent authority lacks a verifier contract: .cursor/rules/webnovel-workflow.mdc", "shortDescription": {"text": "Agent authority lacks a verifier contract: .cursor/rules/webnovel-workflow.mdc"}, "fullDescription": {"text": "This agent instruction grants code or shell authority but does not state the verification gate that decides promotion. The recurring safe pattern is: LLM proposes; deterministic tests/build/security checks verify; only verified code promotes."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-2130b4876f14a2dc", "name": "Agent authority lacks a verifier contract: webnovel-writer/skills/webnovel-review/SKILL.md", "shortDescription": {"text": "Agent authority lacks a verifier contract: webnovel-writer/skills/webnovel-review/SKILL.md"}, "fullDescription": {"text": "This agent instruction grants code or shell authority but does not state the verification gate that decides promotion. The recurring safe pattern is: LLM proposes; deterministic tests/build/security checks verify; only verified code promotes."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-9a58f63a7341332a", "name": "Agent authority lacks a verifier contract: webnovel-writer/skills/webnovel-resume/SKILL.md", "shortDescription": {"text": "Agent authority lacks a verifier contract: webnovel-writer/skills/webnovel-resume/SKILL.md"}, "fullDescription": {"text": "This agent instruction grants code or shell authority but does not state the verification gate that decides promotion. The recurring safe pattern is: LLM proposes; deterministic tests/build/security checks verify; only verified code promotes."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-1ff731d2ab2917ef", "name": "Agent authority lacks a verifier contract: webnovel-writer/skills/webnovel-dashboard/SKILL.md", "shortDescription": {"text": "Agent authority lacks a verifier contract: webnovel-writer/skills/webnovel-dashboard/SKILL.md"}, "fullDescription": {"text": "This agent instruction grants code or shell authority but does not state the verification gate that decides promotion. The recurring safe pattern is: LLM proposes; deterministic tests/build/security checks verify; only verified code promotes."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-deb7f66b176a5b9e", "name": "Agent authority lacks a verifier contract: webnovel-writer/skills/webnovel-learn/SKILL.md", "shortDescription": {"text": "Agent authority lacks a verifier contract: webnovel-writer/skills/webnovel-learn/SKILL.md"}, "fullDescription": {"text": "This agent instruction grants code or shell authority but does not state the verification gate that decides promotion. The recurring safe pattern is: LLM proposes; deterministic tests/build/security checks verify; only verified code promotes."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-0fdfb1760d056ba0", "name": "Agent authority lacks a verifier contract: webnovel-writer/skills/webnovel-query/SKILL.md", "shortDescription": {"text": "Agent authority lacks a verifier contract: webnovel-writer/skills/webnovel-query/SKILL.md"}, "fullDescription": {"text": "This agent instruction grants code or shell authority but does not state the verification gate that decides promotion. The recurring safe pattern is: LLM proposes; deterministic tests/build/security checks verify; only verified code promotes."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-8a91da3553b62e62", "name": "Commented-code block (5 lines) in webnovel-writer/scripts/workflow_manager.py:154", "shortDescription": {"text": "Commented-code block (5 lines) in webnovel-writer/scripts/workflow_manager.py:154"}, "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-a1b8653973d72e58", "name": "Network/subprocess call without timeout or try/except \u2014 webnovel-writer/scripts/workflow_manager.py:1263", "shortDescription": {"text": "Network/subprocess call without timeout or try/except \u2014 webnovel-writer/scripts/workflow_manager.py:1263"}, "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-cfb77b78aa374f2b", "name": "Commented-code block (5 lines) in webnovel-writer/scripts/hygiene_check.py:985", "shortDescription": {"text": "Commented-code block (5 lines) in webnovel-writer/scripts/hygiene_check.py:985"}, "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-599bb6c6b676c9ab", "name": "Legacy-named symbol `state_copy` in webnovel-writer/scripts/external_review.py:1255", "shortDescription": {"text": "Legacy-named symbol `state_copy` in webnovel-writer/scripts/external_review.py:1255"}, "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-5895664a2cddb8cc", "name": "Commented-code block (6 lines) in webnovel-writer/scripts/external_review.py:160", "shortDescription": {"text": "Commented-code block (6 lines) in webnovel-writer/scripts/external_review.py:160"}, "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-f882fac38168a08b", "name": "Legacy-named symbol `resolved_legacy` in webnovel-writer/scripts/archive_manager.py:197", "shortDescription": {"text": "Legacy-named symbol `resolved_legacy` in webnovel-writer/scripts/archive_manager.py:197"}, "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-b4be53c9945afeac", "name": "Commented-code block (9 lines) in webnovel-writer/scripts/polish_cycle.py:238", "shortDescription": {"text": "Commented-code block (9 lines) in webnovel-writer/scripts/polish_cycle.py:238"}, "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-b1cb68c1ae58364a", "name": "Legacy-named symbol `restore_from_backup` in webnovel-writer/scripts/update_state.py:60", "shortDescription": {"text": "Legacy-named symbol `restore_from_backup` in webnovel-writer/scripts/update_state.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-c7e3fed1df669253", "name": "Network/subprocess call without timeout or try/except \u2014 webnovel-writer/scripts/init_project.py:778", "shortDescription": {"text": "Network/subprocess call without timeout or try/except \u2014 webnovel-writer/scripts/init_project.py:778"}, "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-c1eab7eb8ab37d8f", "name": "Legacy-named symbol `restore_from_backup` in webnovel-writer/scripts/security_utils.py:478", "shortDescription": {"text": "Legacy-named symbol `restore_from_backup` in webnovel-writer/scripts/security_utils.py:478"}, "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-56e98447ebbb6f02", "name": "Commented-code block (6 lines) in webnovel-writer/scripts/post_draft_check.py:426", "shortDescription": {"text": "Commented-code block (6 lines) in webnovel-writer/scripts/post_draft_check.py:426"}, "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-8a9e4b6be7a511e7", "name": "Commented-code block (6 lines) in webnovel-writer/scripts/chapter_outline_loader.py:101", "shortDescription": {"text": "Commented-code block (6 lines) in webnovel-writer/scripts/chapter_outline_loader.py:101"}, "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-504988ca0e228c73", "name": "Legacy-named symbol `_local_backup` in webnovel-writer/scripts/backup_manager.py:170", "shortDescription": {"text": "Legacy-named symbol `_local_backup` in webnovel-writer/scripts/backup_manager.py:170"}, "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-42214bf70c08633a", "name": "Network/subprocess call without timeout or try/except \u2014 webnovel-writer/scripts/backup_manager.py:124", "shortDescription": {"text": "Network/subprocess call without timeout or try/except \u2014 webnovel-writer/scripts/backup_manager.py:124"}, "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-0875da16eb1301de", "name": "Legacy-named symbol `expected_v2` in webnovel-writer/scripts/data_modules/chapter_audit.py:391", "shortDescription": {"text": "Legacy-named symbol `expected_v2` in webnovel-writer/scripts/data_modules/chapter_audit.py:391"}, "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-313a27bbeb29ece8", "name": "Commented-code block (5 lines) in webnovel-writer/scripts/data_modules/chapter_audit.py:522", "shortDescription": {"text": "Commented-code block (5 lines) in webnovel-writer/scripts/data_modules/chapter_audit.py:522"}, "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-04480c6371b49b36", "name": "Commented-code block (5 lines) in webnovel-writer/scripts/data_modules/config.py:317", "shortDescription": {"text": "Commented-code block (5 lines) in webnovel-writer/scripts/data_modules/config.py:317"}, "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-050e496af51d80bb", "name": "Legacy-named symbol `no_backup` in webnovel-writer/scripts/data_modules/migrate_state_to_sqlite.py:344", "shortDescription": {"text": "Legacy-named symbol `no_backup` in webnovel-writer/scripts/data_modules/migrate_state_to_sqlite.py:344"}, "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-67d13cf6a8b0262d", "name": "Legacy-named symbol `_restore_vector_db_from_backup` in webnovel-writer/scripts/data_modules/rag_adapter.py:107", "shortDescription": {"text": "Legacy-named symbol `_restore_vector_db_from_backup` in webnovel-writer/scripts/data_modules/rag_adapter.py:107"}, "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-f86d8a6423ee0b04", "name": "Commented-code block (9 lines) in webnovel-writer/scripts/data_modules/state_manager.py:2050", "shortDescription": {"text": "Commented-code block (9 lines) in webnovel-writer/scripts/data_modules/state_manager.py:2050"}, "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-11ba58fd99604034", "name": "Legacy-named symbol `p_backup` in webnovel-writer/scripts/data_modules/webnovel.py:1308", "shortDescription": {"text": "Legacy-named symbol `p_backup` in webnovel-writer/scripts/data_modules/webnovel.py:1308"}, "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-94165edbb040875b", "name": "Network/subprocess call without timeout or try/except \u2014 webnovel-writer/scripts/data_modules/webnovel.py:100", "shortDescription": {"text": "Network/subprocess call without timeout or try/except \u2014 webnovel-writer/scripts/data_modules/webnovel.py:100"}, "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-489406cc74c06c49", "name": "Legacy-named symbol `test_cleanup_artifacts_confirm_deletes_with_backup` in webnovel-writer/scripts/data_modules/tests/t", "shortDescription": {"text": "Legacy-named symbol `test_cleanup_artifacts_confirm_deletes_with_backup` in webnovel-writer/scripts/data_modules/tests/test_workflow_manager.py:448"}, "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-fb3172841dc0de51", "name": "Legacy-named symbol `test_h72_warns_when_polished_but_v1` in webnovel-writer/scripts/data_modules/tests/test_ch26_round2", "shortDescription": {"text": "Legacy-named symbol `test_h72_warns_when_polished_but_v1` in webnovel-writer/scripts/data_modules/tests/test_ch26_round28_4_rca_fixes.py:208"}, "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-6e0e2d2cee7983e2", "name": "Legacy-named symbol `test_R6_narrative_version_default_v1` in webnovel-writer/scripts/data_modules/tests/test_round27_1_", "shortDescription": {"text": "Legacy-named symbol `test_R6_narrative_version_default_v1` in webnovel-writer/scripts/data_modules/tests/test_round27_1_ch23_rca_fixes.py:27"}, "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-652f118e0d0e1a93", "name": "`fetch()` without try/.catch or AbortSignal \u2014 webnovel-writer/dashboard/frontend/src/api.js:12", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 webnovel-writer/dashboard/frontend/src/api.js:12"}, "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-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:\nwebnovel-writer/scripts/post_draft_check.py:check_editor_notes_word_drift, webnovel-writer/scripts/post_draft_check.py:check\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:\nwebnovel-writer/scripts/data_modules/api_client.py:close, webnovel-writer/scripts/data_modules/api_client.py:close, webnovel-writer/scripts/data_modules/api_client.py:close\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-49c98f7cedd9c977", "name": "Near-duplicate function bodies in 4 places", "shortDescription": {"text": "Near-duplicate function bodies in 4 places"}, "fullDescription": {"text": "Functions with the same first-5-line body hash:\nwebnovel-writer/scripts/data_modules/entity_linker.py:emit_error, webnovel-writer/scripts/data_modules/sql_state_manager.py:emit_error, webnovel-writer/scripts/data_modules/state_manager.py:emit_error, webnovel-writer/scripts/data_modules/style_sampler.py:emit_error\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-a4c871792ea5ee82", "name": "Unused endpoint: GET /api/project/info", "shortDescription": {"text": "Unused endpoint: GET /api/project/info"}, "fullDescription": {"text": "`webnovel-writer/dashboard/app.py` declares `GET /api/project/info` 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-8d986db2b8e26c97", "name": "Unused endpoint: GET /api/entities", "shortDescription": {"text": "Unused endpoint: GET /api/entities"}, "fullDescription": {"text": "`webnovel-writer/dashboard/app.py` declares `GET /api/entities` 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-e85fd2933109137a", "name": "Unused endpoint: GET /api/entities/{entity_id}", "shortDescription": {"text": "Unused endpoint: GET /api/entities/{entity_id}"}, "fullDescription": {"text": "`webnovel-writer/dashboard/app.py` declares `GET /api/entities/{entity_id}` 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-23cd77b44d25185a", "name": "Unused endpoint: GET /api/relationships", "shortDescription": {"text": "Unused endpoint: GET /api/relationships"}, "fullDescription": {"text": "`webnovel-writer/dashboard/app.py` declares `GET /api/relationships` 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-0f2abc83100ed46a", "name": "Unused endpoint: GET /api/relationship-events", "shortDescription": {"text": "Unused endpoint: GET /api/relationship-events"}, "fullDescription": {"text": "`webnovel-writer/dashboard/app.py` declares `GET /api/relationship-events` 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-7c40107ff2a95ffe", "name": "Unused endpoint: GET /api/chapters", "shortDescription": {"text": "Unused endpoint: GET /api/chapters"}, "fullDescription": {"text": "`webnovel-writer/dashboard/app.py` declares `GET /api/chapters` 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-3b7f970817c78304", "name": "Unused endpoint: GET /api/scenes", "shortDescription": {"text": "Unused endpoint: GET /api/scenes"}, "fullDescription": {"text": "`webnovel-writer/dashboard/app.py` declares `GET /api/scenes` 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-c8a6e3ca68c26338", "name": "Unused endpoint: GET /api/reading-power", "shortDescription": {"text": "Unused endpoint: GET /api/reading-power"}, "fullDescription": {"text": "`webnovel-writer/dashboard/app.py` declares `GET /api/reading-power` 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-2887aa651ffe3972", "name": "Unused endpoint: GET /api/review-metrics", "shortDescription": {"text": "Unused endpoint: GET /api/review-metrics"}, "fullDescription": {"text": "`webnovel-writer/dashboard/app.py` declares `GET /api/review-metrics` 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-1c79fb4287df65b9", "name": "Unused endpoint: GET /api/state-changes", "shortDescription": {"text": "Unused endpoint: GET /api/state-changes"}, "fullDescription": {"text": "`webnovel-writer/dashboard/app.py` declares `GET /api/state-changes` 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-de549c44c2acf1b0", "name": "Unused endpoint: GET /api/aliases", "shortDescription": {"text": "Unused endpoint: GET /api/aliases"}, "fullDescription": {"text": "`webnovel-writer/dashboard/app.py` declares `GET /api/aliases` 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-6b3ec383677ae2c9", "name": "Unused endpoint: GET /api/overrides", "shortDescription": {"text": "Unused endpoint: GET /api/overrides"}, "fullDescription": {"text": "`webnovel-writer/dashboard/app.py` declares `GET /api/overrides` 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-fd1f58a4d728885f", "name": "Unused endpoint: GET /api/debts", "shortDescription": {"text": "Unused endpoint: GET /api/debts"}, "fullDescription": {"text": "`webnovel-writer/dashboard/app.py` declares `GET /api/debts` 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-62b81e6e0b7d9857", "name": "Unused endpoint: GET /api/debt-events", "shortDescription": {"text": "Unused endpoint: GET /api/debt-events"}, "fullDescription": {"text": "`webnovel-writer/dashboard/app.py` declares `GET /api/debt-events` 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-02313e36f4e2010e", "name": "Unused endpoint: GET /api/invalid-facts", "shortDescription": {"text": "Unused endpoint: GET /api/invalid-facts"}, "fullDescription": {"text": "`webnovel-writer/dashboard/app.py` declares `GET /api/invalid-facts` 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-ef1e1fcec8406e41", "name": "Unused endpoint: GET /api/rag-queries", "shortDescription": {"text": "Unused endpoint: GET /api/rag-queries"}, "fullDescription": {"text": "`webnovel-writer/dashboard/app.py` declares `GET /api/rag-queries` 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-0de5869b15c8003f", "name": "Unused endpoint: GET /api/tool-stats", "shortDescription": {"text": "Unused endpoint: GET /api/tool-stats"}, "fullDescription": {"text": "`webnovel-writer/dashboard/app.py` declares `GET /api/tool-stats` 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-0ed392c7769c0432", "name": "Unused endpoint: GET /api/checklist-scores", "shortDescription": {"text": "Unused endpoint: GET /api/checklist-scores"}, "fullDescription": {"text": "`webnovel-writer/dashboard/app.py` declares `GET /api/checklist-scores` 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-d6757b90cf564d75", "name": "Unused endpoint: GET /api/files/tree", "shortDescription": {"text": "Unused endpoint: GET /api/files/tree"}, "fullDescription": {"text": "`webnovel-writer/dashboard/app.py` declares `GET /api/files/tree` 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-f56cb40f17427ebc", "name": "Unused endpoint: GET /api/files/read", "shortDescription": {"text": "Unused endpoint: GET /api/files/read"}, "fullDescription": {"text": "`webnovel-writer/dashboard/app.py` declares `GET /api/files/read` 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-32af5edd087acbbc", "name": "Unused endpoint: GET /api/events", "shortDescription": {"text": "Unused endpoint: GET /api/events"}, "fullDescription": {"text": "`webnovel-writer/dashboard/app.py` declares `GET /api/events` 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-1b1d5926fda286fa", "name": "Unused endpoint: GET /{full_path:path}", "shortDescription": {"text": "Unused endpoint: GET /{full_path:path}"}, "fullDescription": {"text": "`webnovel-writer/dashboard/app.py` declares `GET /{full_path:path}` 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-5baa8971ebe192a1", "name": "Unused endpoint: GET /", "shortDescription": {"text": "Unused endpoint: GET /"}, "fullDescription": {"text": "`webnovel-writer/dashboard/app.py` declares `GET /` 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/23069"}, "properties": {"repository": "XuanRanL/webnovelwriter", "repoUrl": "https://github.com/XuanRanL/webnovelwriter", "branch": "main"}, "results": [{"ruleId": "scanner-5dfc79a2212e5534", "level": "note", "message": {"text": "Possibly dead Python function: file_hash"}, "properties": {"repobilityId": "f886fb0eb79e29b4", "scanner": "scanner-primary", "fingerprint": "5dfc79a2212e5534", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "webnovel-writer/scripts/polish_cycle.py:87"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-2e3f131ec420c6ba", "level": "note", "message": {"text": "Possibly dead Python function: create_secure_file"}, "properties": {"repobilityId": "9c35c16405c9945b", "scanner": "scanner-primary", "fingerprint": "2e3f131ec420c6ba", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "webnovel-writer/scripts/security_utils.py:175"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-c952e77ea0665c92", "level": "note", "message": {"text": "Possibly dead Python function: is_git_repo"}, "properties": {"repobilityId": "6d352f283c9916e9", "scanner": "scanner-primary", "fingerprint": "c952e77ea0665c92", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "webnovel-writer/scripts/security_utils.py:266"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-d0be066c42f43fa9", "level": "note", "message": {"text": "Possibly dead Python function: git_graceful_operation"}, "properties": {"repobilityId": "4ff212b0d2f21679", "scanner": "scanner-primary", "fingerprint": "d0be066c42f43fa9", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "webnovel-writer/scripts/security_utils.py:284"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-c86a12a49480cd7c", "level": "note", "message": {"text": "Possibly dead Python function: extract_ai_replacement_vocab"}, "properties": {"repobilityId": "94b6b779c89e89de", "scanner": "scanner-primary", "fingerprint": "c86a12a49480cd7c", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "webnovel-writer/scripts/private_csv_extractor.py:166"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-60d6219320897c52", "level": "note", "message": {"text": "Possibly dead Python function: extract_strong_chapter_end_hooks"}, "properties": {"repobilityId": "2d3ae5cf05c2c643", "scanner": "scanner-primary", "fingerprint": "60d6219320897c52", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "webnovel-writer/scripts/private_csv_extractor.py:194"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-74ff8f89459df959", "level": "note", "message": {"text": "Possibly dead Python function: extract_emotion_earned_forced"}, "properties": {"repobilityId": "19f7bdda22e18094", "scanner": "scanner-primary", "fingerprint": "74ff8f89459df959", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "webnovel-writer/scripts/private_csv_extractor.py:242"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-a824f147491908f7", "level": "note", "message": {"text": "Possibly dead Python function: extract_canon_violations"}, "properties": {"repobilityId": "8e44708ae383f4c3", "scanner": "scanner-primary", "fingerprint": "a824f147491908f7", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "webnovel-writer/scripts/private_csv_extractor.py:322"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-80c75eaef67320a8", "level": "note", "message": {"text": "Possibly dead Python function: list_snapshots"}, "properties": {"repobilityId": "f8d6d17afaca36e4", "scanner": "scanner-primary", "fingerprint": "80c75eaef67320a8", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "webnovel-writer/scripts/data_modules/snapshot_manager.py:91"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-39873e4d19587389", "level": "note", "message": {"text": "Possibly dead Python function: apply_confidence_filter"}, "properties": {"repobilityId": "5358167c884817a0", "scanner": "scanner-primary", "fingerprint": "39873e4d19587389", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "webnovel-writer/scripts/data_modules/context_manager.py:181"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-537f5b1e55e1fccf", "level": "note", "message": {"text": "Possibly dead Python function: cmd_sync_agents"}, "properties": {"repobilityId": "73f3737168646409", "scanner": "scanner-primary", "fingerprint": "537f5b1e55e1fccf", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "webnovel-writer/scripts/data_modules/webnovel.py:645"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-6eb44a80d883685d", "level": "note", "message": {"text": "Possibly dead Python function: cmd_sync_cache"}, "properties": {"repobilityId": "6c8b8cfb0c9990be", "scanner": "scanner-primary", "fingerprint": "6eb44a80d883685d", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "webnovel-writer/scripts/data_modules/webnovel.py:901"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-1196e02236669725", "level": "note", "message": {"text": "Possibly dead Python function: cmd_normalize_checker_scores"}, "properties": {"repobilityId": "e17ef03157f624b2", "scanner": "scanner-primary", "fingerprint": "1196e02236669725", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "webnovel-writer/scripts/data_modules/webnovel.py:1119"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-04a4b2d52d340d14", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 webnovel-writer/dashboard/frontend/src/App.jsx:212"}, "properties": {"repobilityId": "cdf6689caff2527d", "scanner": "scanner-primary", "fingerprint": "04a4b2d52d340d14", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-f10351888efb2a4b", "level": "warning", "message": {"text": "Insecure pattern 'cors_wildcard' in webnovel-writer/dashboard/app.py:65"}, "properties": {"repobilityId": "ff02d9a4bff78efa", "scanner": "scanner-primary", "fingerprint": "f10351888efb2a4b", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "cors_wildcard"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "webnovel-writer/dashboard/app.py"}, "region": {"startLine": 65}}}]}, {"ruleId": "scanner-6372cebde0220094", "level": "warning", "message": {"text": "No auth library detected"}, "properties": {"repobilityId": "a5b6035a5bbf8054", "scanner": "scanner-primary", "fingerprint": "6372cebde0220094", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["coverage", "auth"]}}, {"ruleId": "scanner-0d0af982afccb800", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "0bff3b2538d0fee1", "scanner": "scanner-primary", "fingerprint": "0d0af982afccb800", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/plugin-version.yml"}, "region": {"startLine": 24}}}]}, {"ruleId": "scanner-0d0af982afccb800", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "7cefa39e5d1a5ae4", "scanner": "scanner-primary", "fingerprint": "0d0af982afccb800", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/plugin-version.yml"}, "region": {"startLine": 27}}}]}, {"ruleId": "scanner-1ecc4cc96fdccd9a", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "2cbe98078903a733", "scanner": "scanner-primary", "fingerprint": "1ecc4cc96fdccd9a", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/plugin-release.yml"}, "region": {"startLine": 26}}}]}, {"ruleId": "scanner-1ecc4cc96fdccd9a", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "83536bb45e95c621", "scanner": "scanner-primary", "fingerprint": "1ecc4cc96fdccd9a", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/plugin-release.yml"}, "region": {"startLine": 31}}}]}, {"ruleId": "scanner-1ecc4cc96fdccd9a", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "da1625a3615e403e", "scanner": "scanner-primary", "fingerprint": "1ecc4cc96fdccd9a", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/plugin-release.yml"}, "region": {"startLine": 52}}}]}, {"ruleId": "scanner-f2da95b6b75dbd8c", "level": "warning", "message": {"text": "GitHub Actions workflow grants broad write permissions"}, "properties": {"repobilityId": "ab7efafe114e8341", "scanner": "scanner-primary", "fingerprint": "f2da95b6b75dbd8c", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "least-privilege"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/plugin-release.yml"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-e14dc728a6208329", "level": "note", "message": {"text": "Very large file: webnovel-writer/scripts/workflow_manager.py (1505 lines)"}, "properties": {"repobilityId": "a070092571d82902", "scanner": "scanner-primary", "fingerprint": "e14dc728a6208329", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-5b1f03a2499f2906", "level": "note", "message": {"text": "Very large file: webnovel-writer/scripts/hygiene_check.py (4514 lines)"}, "properties": {"repobilityId": "0c01fed61edf8842", "scanner": "scanner-primary", "fingerprint": "5b1f03a2499f2906", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-6bbb4dfc5f411cfe", "level": "note", "message": {"text": "Very large file: webnovel-writer/scripts/external_review.py (2630 lines)"}, "properties": {"repobilityId": "aeda775c6169f02b", "scanner": "scanner-primary", "fingerprint": "6bbb4dfc5f411cfe", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-dd651c7a7a8e9fe6", "level": "note", "message": {"text": "Very large file: webnovel-writer/scripts/post_draft_check.py (1058 lines)"}, "properties": {"repobilityId": "77d88936cdbe9f00", "scanner": "scanner-primary", "fingerprint": "dd651c7a7a8e9fe6", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-2cddcdf938be7a83", "level": "note", "message": {"text": "Very large file: webnovel-writer/scripts/data_modules/chapter_audit.py (3034 lines)"}, "properties": {"repobilityId": "24e85e540d55c3ed", "scanner": "scanner-primary", "fingerprint": "2cddcdf938be7a83", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-a04f078eace390ed", "level": "note", "message": {"text": "Very large file: webnovel-writer/scripts/data_modules/rag_adapter.py (1663 lines)"}, "properties": {"repobilityId": "011bebee8d64cadb", "scanner": "scanner-primary", "fingerprint": "a04f078eace390ed", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-467fd5251b86ce24", "level": "note", "message": {"text": "Very large file: webnovel-writer/scripts/data_modules/state_manager.py (2836 lines)"}, "properties": {"repobilityId": "5ec636d85d8f60ea", "scanner": "scanner-primary", "fingerprint": "467fd5251b86ce24", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-233a1f8425d54415", "level": "note", "message": {"text": "Very large file: webnovel-writer/scripts/data_modules/index_manager.py (1536 lines)"}, "properties": {"repobilityId": "ebac50a3cf1fe48f", "scanner": "scanner-primary", "fingerprint": "233a1f8425d54415", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-63f798a05c88710c", "level": "note", "message": {"text": "Very large file: webnovel-writer/scripts/data_modules/webnovel.py (1408 lines)"}, "properties": {"repobilityId": "9d38e1835d7a8456", "scanner": "scanner-primary", "fingerprint": "63f798a05c88710c", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-b6541f20857e22a8", "level": "note", "message": {"text": "Very large file: webnovel-writer/scripts/data_modules/tests/test_data_modules.py (1414 lines)"}, "properties": {"repobilityId": "813f4fb82c5258f4", "scanner": "scanner-primary", "fingerprint": "b6541f20857e22a8", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-db4f5c200261afd7", "level": "note", "message": {"text": "Very large file: webnovel-writer/scripts/data_modules/tests/test_chapter_audit.py (1980 lines)"}, "properties": {"repobilityId": "70d1a443d60f4e37", "scanner": "scanner-primary", "fingerprint": "db4f5c200261afd7", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-3ab5d313dda8e5f9", "level": "note", "message": {"text": "Debug logging residue appears in source files"}, "properties": {"repobilityId": "c32ad1e4edc9ecf2", "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": "b57486c96de9510c", "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": "07fb1ef0eda90edb", "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": "e2dceb358da07a75", "scanner": "scanner-primary", "fingerprint": "8424db9c75e04ba4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["provenance", "git-history", "generated-repo-pattern"]}}, {"ruleId": "scanner-87ca2d277fcdc8f3", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: .cursor/rules/webnovel-workflow.mdc"}, "properties": {"repobilityId": "45677c4ac3347fe9", "scanner": "scanner-primary", "fingerprint": "87ca2d277fcdc8f3", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "cursor_rule"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".cursor/rules/webnovel-workflow.mdc"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-2130b4876f14a2dc", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: webnovel-writer/skills/webnovel-review/SKILL.md"}, "properties": {"repobilityId": "da5d6535febaad00", "scanner": "scanner-primary", "fingerprint": "2130b4876f14a2dc", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "skill_file"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "webnovel-writer/skills/webnovel-review/SKILL.md"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-9a58f63a7341332a", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: webnovel-writer/skills/webnovel-resume/SKILL.md"}, "properties": {"repobilityId": "06191bd46f9d0398", "scanner": "scanner-primary", "fingerprint": "9a58f63a7341332a", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "skill_file"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "webnovel-writer/skills/webnovel-resume/SKILL.md"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-1ff731d2ab2917ef", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: webnovel-writer/skills/webnovel-dashboard/SKILL.md"}, "properties": {"repobilityId": "b15634f2ebb67564", "scanner": "scanner-primary", "fingerprint": "1ff731d2ab2917ef", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "skill_file"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "webnovel-writer/skills/webnovel-dashboard/SKILL.md"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-deb7f66b176a5b9e", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: webnovel-writer/skills/webnovel-learn/SKILL.md"}, "properties": {"repobilityId": "a36e27ac130100d2", "scanner": "scanner-primary", "fingerprint": "deb7f66b176a5b9e", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "skill_file"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "webnovel-writer/skills/webnovel-learn/SKILL.md"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-0fdfb1760d056ba0", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: webnovel-writer/skills/webnovel-query/SKILL.md"}, "properties": {"repobilityId": "772f3acc4ab5fab8", "scanner": "scanner-primary", "fingerprint": "0fdfb1760d056ba0", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "skill_file"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "webnovel-writer/skills/webnovel-query/SKILL.md"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-8a91da3553b62e62", "level": "none", "message": {"text": "Commented-code block (5 lines) in webnovel-writer/scripts/workflow_manager.py:154"}, "properties": {"repobilityId": "bf02d6827a2c691c", "scanner": "scanner-primary", "fingerprint": "8a91da3553b62e62", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-a1b8653973d72e58", "level": "warning", "message": {"text": "Network/subprocess call without timeout or try/except \u2014 webnovel-writer/scripts/workflow_manager.py:1263"}, "properties": {"repobilityId": "d0bc3f578e6afbcf", "scanner": "scanner-primary", "fingerprint": "a1b8653973d72e58", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-cfb77b78aa374f2b", "level": "none", "message": {"text": "Commented-code block (5 lines) in webnovel-writer/scripts/hygiene_check.py:985"}, "properties": {"repobilityId": "6e6d188b26b017e1", "scanner": "scanner-primary", "fingerprint": "cfb77b78aa374f2b", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-599bb6c6b676c9ab", "level": "note", "message": {"text": "Legacy-named symbol `state_copy` in webnovel-writer/scripts/external_review.py:1255"}, "properties": {"repobilityId": "f196e3958405f914", "scanner": "scanner-primary", "fingerprint": "599bb6c6b676c9ab", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-5895664a2cddb8cc", "level": "none", "message": {"text": "Commented-code block (6 lines) in webnovel-writer/scripts/external_review.py:160"}, "properties": {"repobilityId": "07a2e57da6f35310", "scanner": "scanner-primary", "fingerprint": "5895664a2cddb8cc", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-f882fac38168a08b", "level": "note", "message": {"text": "Legacy-named symbol `resolved_legacy` in webnovel-writer/scripts/archive_manager.py:197"}, "properties": {"repobilityId": "08fa64dd8d686620", "scanner": "scanner-primary", "fingerprint": "f882fac38168a08b", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-b4be53c9945afeac", "level": "none", "message": {"text": "Commented-code block (9 lines) in webnovel-writer/scripts/polish_cycle.py:238"}, "properties": {"repobilityId": "6fc0829b76ea78f1", "scanner": "scanner-primary", "fingerprint": "b4be53c9945afeac", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-b1cb68c1ae58364a", "level": "note", "message": {"text": "Legacy-named symbol `restore_from_backup` in webnovel-writer/scripts/update_state.py:60"}, "properties": {"repobilityId": "a5ec9f7787f35073", "scanner": "scanner-primary", "fingerprint": "b1cb68c1ae58364a", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-c7e3fed1df669253", "level": "warning", "message": {"text": "Network/subprocess call without timeout or try/except \u2014 webnovel-writer/scripts/init_project.py:778"}, "properties": {"repobilityId": "7200620f6cacc533", "scanner": "scanner-primary", "fingerprint": "c7e3fed1df669253", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-c1eab7eb8ab37d8f", "level": "note", "message": {"text": "Legacy-named symbol `restore_from_backup` in webnovel-writer/scripts/security_utils.py:478"}, "properties": {"repobilityId": "4d3ef87b2a8efb52", "scanner": "scanner-primary", "fingerprint": "c1eab7eb8ab37d8f", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-56e98447ebbb6f02", "level": "none", "message": {"text": "Commented-code block (6 lines) in webnovel-writer/scripts/post_draft_check.py:426"}, "properties": {"repobilityId": "8dfa62e75b329365", "scanner": "scanner-primary", "fingerprint": "56e98447ebbb6f02", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-8a9e4b6be7a511e7", "level": "none", "message": {"text": "Commented-code block (6 lines) in webnovel-writer/scripts/chapter_outline_loader.py:101"}, "properties": {"repobilityId": "1f11c41648c65e42", "scanner": "scanner-primary", "fingerprint": "8a9e4b6be7a511e7", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-504988ca0e228c73", "level": "note", "message": {"text": "Legacy-named symbol `_local_backup` in webnovel-writer/scripts/backup_manager.py:170"}, "properties": {"repobilityId": "f2fd898b5aed41ef", "scanner": "scanner-primary", "fingerprint": "504988ca0e228c73", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-42214bf70c08633a", "level": "warning", "message": {"text": "Network/subprocess call without timeout or try/except \u2014 webnovel-writer/scripts/backup_manager.py:124"}, "properties": {"repobilityId": "eee737b982f05b2b", "scanner": "scanner-primary", "fingerprint": "42214bf70c08633a", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-0875da16eb1301de", "level": "note", "message": {"text": "Legacy-named symbol `expected_v2` in webnovel-writer/scripts/data_modules/chapter_audit.py:391"}, "properties": {"repobilityId": "b31ee3646a250ba4", "scanner": "scanner-primary", "fingerprint": "0875da16eb1301de", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-313a27bbeb29ece8", "level": "none", "message": {"text": "Commented-code block (5 lines) in webnovel-writer/scripts/data_modules/chapter_audit.py:522"}, "properties": {"repobilityId": "7f0e576bb744b2c8", "scanner": "scanner-primary", "fingerprint": "313a27bbeb29ece8", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-04480c6371b49b36", "level": "none", "message": {"text": "Commented-code block (5 lines) in webnovel-writer/scripts/data_modules/config.py:317"}, "properties": {"repobilityId": "3c1c0f8f6941a3af", "scanner": "scanner-primary", "fingerprint": "04480c6371b49b36", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-050e496af51d80bb", "level": "note", "message": {"text": "Legacy-named symbol `no_backup` in webnovel-writer/scripts/data_modules/migrate_state_to_sqlite.py:344"}, "properties": {"repobilityId": "200f3c6c25567f98", "scanner": "scanner-primary", "fingerprint": "050e496af51d80bb", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-67d13cf6a8b0262d", "level": "note", "message": {"text": "Legacy-named symbol `_restore_vector_db_from_backup` in webnovel-writer/scripts/data_modules/rag_adapter.py:107"}, "properties": {"repobilityId": "80e73585274aadc2", "scanner": "scanner-primary", "fingerprint": "67d13cf6a8b0262d", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-f86d8a6423ee0b04", "level": "none", "message": {"text": "Commented-code block (9 lines) in webnovel-writer/scripts/data_modules/state_manager.py:2050"}, "properties": {"repobilityId": "dc0c6c8167b28732", "scanner": "scanner-primary", "fingerprint": "f86d8a6423ee0b04", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-11ba58fd99604034", "level": "note", "message": {"text": "Legacy-named symbol `p_backup` in webnovel-writer/scripts/data_modules/webnovel.py:1308"}, "properties": {"repobilityId": "130afca441323e7e", "scanner": "scanner-primary", "fingerprint": "11ba58fd99604034", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-94165edbb040875b", "level": "warning", "message": {"text": "Network/subprocess call without timeout or try/except \u2014 webnovel-writer/scripts/data_modules/webnovel.py:100"}, "properties": {"repobilityId": "09703ac736e4cc48", "scanner": "scanner-primary", "fingerprint": "94165edbb040875b", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-489406cc74c06c49", "level": "note", "message": {"text": "Legacy-named symbol `test_cleanup_artifacts_confirm_deletes_with_backup` in webnovel-writer/scripts/data_modules/tests/test_workflow_manager.py:448"}, "properties": {"repobilityId": "c31a91b65762644a", "scanner": "scanner-primary", "fingerprint": "489406cc74c06c49", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-fb3172841dc0de51", "level": "note", "message": {"text": "Legacy-named symbol `test_h72_warns_when_polished_but_v1` in webnovel-writer/scripts/data_modules/tests/test_ch26_round28_4_rca_fixes.py:208"}, "properties": {"repobilityId": "f50963d716170cfc", "scanner": "scanner-primary", "fingerprint": "fb3172841dc0de51", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-6e0e2d2cee7983e2", "level": "note", "message": {"text": "Legacy-named symbol `test_R6_narrative_version_default_v1` in webnovel-writer/scripts/data_modules/tests/test_round27_1_ch23_rca_fixes.py:27"}, "properties": {"repobilityId": "6ac35c51de0ef507", "scanner": "scanner-primary", "fingerprint": "6e0e2d2cee7983e2", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-652f118e0d0e1a93", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 webnovel-writer/dashboard/frontend/src/api.js:12"}, "properties": {"repobilityId": "aa7847565fd038b5", "scanner": "scanner-primary", "fingerprint": "652f118e0d0e1a93", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "c6d06904271cefdf", "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": "1360a329cd7eeefc", "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": "cd48ff3342c18897", "scanner": "scanner-primary", "fingerprint": "be46ea126aa5d8dc", "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": "26c5c69aefd660c4", "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": "26afe3cfdbf1bbcb", "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": "fb153ec9d2ce9da7", "scanner": "scanner-primary", "fingerprint": "be46ea126aa5d8dc", "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": "d01bf483e807cec4", "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": "72a5c9ea707a2048", "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": "fba9fce3b8b91311", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-49c98f7cedd9c977", "level": "note", "message": {"text": "Near-duplicate function bodies in 4 places"}, "properties": {"repobilityId": "f7c4c690aec3588d", "scanner": "scanner-primary", "fingerprint": "49c98f7cedd9c977", "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": "d3aae9ddd1a222ee", "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": "827ea1ce3955983a", "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": "94562227b7e904a2", "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": "6f0fa1206a41aa7e", "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": "659e138bfbdb691a", "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": "48c41a3c292be747", "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": "f707a0e32dc2aa7e", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-a4c871792ea5ee82", "level": "note", "message": {"text": "Unused endpoint: GET /api/project/info"}, "properties": {"repobilityId": "542ac6f2d2e3c6b6", "scanner": "scanner-primary", "fingerprint": "a4c871792ea5ee82", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-8d986db2b8e26c97", "level": "note", "message": {"text": "Unused endpoint: GET /api/entities"}, "properties": {"repobilityId": "d60bca864bb03eef", "scanner": "scanner-primary", "fingerprint": "8d986db2b8e26c97", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-e85fd2933109137a", "level": "note", "message": {"text": "Unused endpoint: GET /api/entities/{entity_id}"}, "properties": {"repobilityId": "e3389c586ee1405e", "scanner": "scanner-primary", "fingerprint": "e85fd2933109137a", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-23cd77b44d25185a", "level": "note", "message": {"text": "Unused endpoint: GET /api/relationships"}, "properties": {"repobilityId": "f01ccc3226b4344c", "scanner": "scanner-primary", "fingerprint": "23cd77b44d25185a", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-0f2abc83100ed46a", "level": "note", "message": {"text": "Unused endpoint: GET /api/relationship-events"}, "properties": {"repobilityId": "448383de21f400f2", "scanner": "scanner-primary", "fingerprint": "0f2abc83100ed46a", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-7c40107ff2a95ffe", "level": "note", "message": {"text": "Unused endpoint: GET /api/chapters"}, "properties": {"repobilityId": "99b54bf9ad786c66", "scanner": "scanner-primary", "fingerprint": "7c40107ff2a95ffe", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-3b7f970817c78304", "level": "note", "message": {"text": "Unused endpoint: GET /api/scenes"}, "properties": {"repobilityId": "c5f84a98613b6d6b", "scanner": "scanner-primary", "fingerprint": "3b7f970817c78304", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-c8a6e3ca68c26338", "level": "note", "message": {"text": "Unused endpoint: GET /api/reading-power"}, "properties": {"repobilityId": "f2233379b8f5ef8f", "scanner": "scanner-primary", "fingerprint": "c8a6e3ca68c26338", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-2887aa651ffe3972", "level": "note", "message": {"text": "Unused endpoint: GET /api/review-metrics"}, "properties": {"repobilityId": "98cba60d38e40d0f", "scanner": "scanner-primary", "fingerprint": "2887aa651ffe3972", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-1c79fb4287df65b9", "level": "note", "message": {"text": "Unused endpoint: GET /api/state-changes"}, "properties": {"repobilityId": "2261546f252f6d8c", "scanner": "scanner-primary", "fingerprint": "1c79fb4287df65b9", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-de549c44c2acf1b0", "level": "note", "message": {"text": "Unused endpoint: GET /api/aliases"}, "properties": {"repobilityId": "ae8bd1e7c90689f9", "scanner": "scanner-primary", "fingerprint": "de549c44c2acf1b0", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-6b3ec383677ae2c9", "level": "note", "message": {"text": "Unused endpoint: GET /api/overrides"}, "properties": {"repobilityId": "3aadadca4edd311b", "scanner": "scanner-primary", "fingerprint": "6b3ec383677ae2c9", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-fd1f58a4d728885f", "level": "note", "message": {"text": "Unused endpoint: GET /api/debts"}, "properties": {"repobilityId": "f3176a034c7cd706", "scanner": "scanner-primary", "fingerprint": "fd1f58a4d728885f", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-62b81e6e0b7d9857", "level": "note", "message": {"text": "Unused endpoint: GET /api/debt-events"}, "properties": {"repobilityId": "8334ddfe38720872", "scanner": "scanner-primary", "fingerprint": "62b81e6e0b7d9857", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-02313e36f4e2010e", "level": "note", "message": {"text": "Unused endpoint: GET /api/invalid-facts"}, "properties": {"repobilityId": "e2e16f26f1e72231", "scanner": "scanner-primary", "fingerprint": "02313e36f4e2010e", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-ef1e1fcec8406e41", "level": "note", "message": {"text": "Unused endpoint: GET /api/rag-queries"}, "properties": {"repobilityId": "bea95191039e290d", "scanner": "scanner-primary", "fingerprint": "ef1e1fcec8406e41", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-0de5869b15c8003f", "level": "note", "message": {"text": "Unused endpoint: GET /api/tool-stats"}, "properties": {"repobilityId": "7672ffcdbc4da3f2", "scanner": "scanner-primary", "fingerprint": "0de5869b15c8003f", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-0ed392c7769c0432", "level": "note", "message": {"text": "Unused endpoint: GET /api/checklist-scores"}, "properties": {"repobilityId": "b41028a7ff72baaf", "scanner": "scanner-primary", "fingerprint": "0ed392c7769c0432", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-d6757b90cf564d75", "level": "note", "message": {"text": "Unused endpoint: GET /api/files/tree"}, "properties": {"repobilityId": "2d894e243d7cfef6", "scanner": "scanner-primary", "fingerprint": "d6757b90cf564d75", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-f56cb40f17427ebc", "level": "note", "message": {"text": "Unused endpoint: GET /api/files/read"}, "properties": {"repobilityId": "b88a62cdf51e1acd", "scanner": "scanner-primary", "fingerprint": "f56cb40f17427ebc", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-32af5edd087acbbc", "level": "note", "message": {"text": "Unused endpoint: GET /api/events"}, "properties": {"repobilityId": "39d5f3046d1d2d0d", "scanner": "scanner-primary", "fingerprint": "32af5edd087acbbc", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-1b1d5926fda286fa", "level": "note", "message": {"text": "Unused endpoint: GET /{full_path:path}"}, "properties": {"repobilityId": "9ab434a6c405f95b", "scanner": "scanner-primary", "fingerprint": "1b1d5926fda286fa", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-5baa8971ebe192a1", "level": "note", "message": {"text": "Unused endpoint: GET /"}, "properties": {"repobilityId": "595b353565bf63b0", "scanner": "scanner-primary", "fingerprint": "5baa8971ebe192a1", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}]}]}