{"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": "foundry_unresolved_feedback", "name": "Foundry mined unresolved feedback: robertknowles/ignito-project-kit", "shortDescription": {"text": "Foundry mined unresolved feedback: robertknowles/ignito-project-kit"}, "fullDescription": {"text": "Graph query export: Human feedback without linked fix evidence\nQuery id: unresolved_feedback\nQuery type: motif_query\nIntent: Negative/unresolved examples that should not be hallucinated into fixes.\nMotif: unlinked_feedback_needs_evidence\nTraining usage: negative_or_unresolved\nGraph gold label: needs_more_evidence\nRepo: robertknowles/ignito-project-kit\nThread: robertknowles/ignito-project-kit#1\nEvidence:\nGraph motif: Human feedback exists without a linked fix\nMotif id: unlinked_feedback_needs_evidence\nPolarity: bad\nTraining usage: negative_or_unresolved\nSeverity: medium\nRepo: robertknowles/ignito-project-kit\nThread: robertknowles/ignito-project-kit#1\nGraph gold label: needs_more_evidence\nThread graph evidence:\nGitHub issue/PR evidence subgraph\nThread: robertknowles/ignito-project-kit#1\nRepo: robertknowles/ignito-project-kit\nIssue/PR number: 1\nGraph consistency label: needs_more_evidence\nNodes: 59\nEdges: 99\nNode types: {'pr_file': 47, 'link_quality': 4, 'comment': 2, 'comment_chain': 2, "}, "properties": {"scanner": "foundry_dataset", "category": "practices", "severity": "medium", "confidence": 0.7, "cwe": "", "owasp": ""}}, {"id": "foundry_bad_chain", "name": "Foundry mined bad chains: robertknowles/ignito-project-kit", "shortDescription": {"text": "Foundry mined bad chains: robertknowles/ignito-project-kit"}, "fullDescription": {"text": "Comment chain pattern product: bad_chains\nRepo: robertknowles/ignito-project-kit\nThread: robertknowles/ignito-project-kit#1\nOutcome: not_resolved_or_not_observed\nThread label: thread_has_human_issue_without_fix_context\nSource graph label: source_backed_multi_signal_graph\nReasons: source_graph_has_real_artifacts, source_graph_has_verification_artifacts, repo_has_isolated_helicopter_views, link_quality_unresolved, high_risk_human_feedback_label\nChain evidence:\nIssue/PR evidence chain: robertknowles/ignito-project-kit#1\nRepo: robertknowles/ignito-project-kit\nThread label: thread_has_human_issue_without_fix_context\nOutcome: not_resolved_or_not_observed\nComment count: 2\nLinked commit count: 0\nLinked CI commit count: 0\nLinked CI labels: {}\nChanged file count: 47\nLabels: {'runtime_failure': 1, 'deployment_env_gap': 1}\nPolarities: {'bad': 2}\nChanged file labels: {'ui_or_frontend': 47}\nExamples:\n[\n  {\n    \"id\": \"github-feedback-comment-d5fd01834806a8d7\",\n    \"kind\": \"pull_request_body\",\n    \"la"}, "properties": {"scanner": "foundry_dataset", "category": "practices", "severity": "high", "confidence": 0.84, "cwe": "", "owasp": ""}}, {"id": "scanner-bead75b0f9233e05", "name": "No API endpoints detected", "shortDescription": {"text": "No API endpoints detected"}, "fullDescription": {"text": "The scanner did not find FastAPI/Flask/Express/NestJS/GraphQL/gRPC routes. If this repo exposes APIs, the framework may be unsupported."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "info", "confidence": 1.0}}, {"id": "scanner-52e66fba28636d0b", "name": "Icon-only button without accessible name \u2014 incoming-redesign/src/App.tsx:463", "shortDescription": {"text": "Icon-only button without accessible name \u2014 incoming-redesign/src/App.tsx:463"}, "fullDescription": {"text": "A `<button>` whose only child is a single glyph or symbol needs `title=` or `aria-label=` so screen readers (and tooltips on hover) work.\n\nWhy: P3 in CHECKLIST.md \u2014 icon-only buttons skipped a title.\nRule id: fq.button.no-label"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-c1005674bd0a3db5", "name": "Stray `console.log` in TS/JS \u2014 _archive/cursor-sessions/verify-static-rent-fix.js:16", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 _archive/cursor-sessions/verify-static-rent-fix.js:16"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-421705826fe0d549", "name": "Stray `console.log` in TS/JS \u2014 _archive/cursor-sessions/verify-property-instances-schema.js:186", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 _archive/cursor-sessions/verify-property-instances-schema.js:186"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-e52d40596af7390f", "name": "Stray `console.log` in TS/JS \u2014 _archive/cursor-sessions/verify-lmi.js:14", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 _archive/cursor-sessions/verify-lmi.js:14"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-cee3042462f55d77", "name": "Stray `console.log` in TS/JS \u2014 _archive/cursor-sessions/test-all-39-fields.js:78", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 _archive/cursor-sessions/test-all-39-fields.js:78"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-d39ad16891dd7118", "name": "Stray `console.log` in TS/JS \u2014 _archive/cursor-sessions/verify-property-instance-persistence.js:27", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 _archive/cursor-sessions/verify-property-instance-persistence.js:27"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-df87d5c4065db546", "name": "Stray `console.log` in TS/JS \u2014 scripts/migrate-saved-scenarios.ts:155", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 scripts/migrate-saved-scenarios.ts:155"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-4f72c71e6a94dcee", "name": "Stray `console.log` in TS/JS \u2014 supabase/functions/stripe-webhook/index.ts:74", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 supabase/functions/stripe-webhook/index.ts:74"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-5a257ce91c924221", "name": "Stray `console.log` in TS/JS \u2014 evals/run-evals.ts:330", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 evals/run-evals.ts:330"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-9b63a453cc2addfc", "name": "Stray `console.log` in TS/JS \u2014 evals/ab-compare.ts:240", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 evals/ab-compare.ts:240"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-39be0bebf1ef1894", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/ChatOptionCard.tsx:57", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/ChatOptionCard.tsx:57"}, "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-f372d0407bec5a36", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/AppSidebar.tsx:254", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/AppSidebar.tsx:254"}, "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-840f4184db8a4306", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/OwnedPropertyCard.tsx:113", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/OwnedPropertyCard.tsx:113"}, "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-463170fcd2a0babd", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/PropertySummaryCard.tsx:130", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/PropertySummaryCard.tsx:130"}, "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-091f325000711573", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/NewClientView.tsx:376", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/NewClientView.tsx:376"}, "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-f2dd4f276bc73c62", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/FormTemplateEditor.tsx:96", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/FormTemplateEditor.tsx:96"}, "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-05d5164730731695", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/TimelinePanel.tsx:88", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/TimelinePanel.tsx:88"}, "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-a1ee5e9a0875d1cf", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/ClientSelector.tsx:203", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/ClientSelector.tsx:203"}, "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-a3e13171f6b2fb42", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/PropertyTimeline.tsx:81", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/PropertyTimeline.tsx:81"}, "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-cf3456791f25afff", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/AddToTimelineModal.tsx:130", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/AddToTimelineModal.tsx:130"}, "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-e0d57b49d86685dc", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/ClientFormModal.tsx:58", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/ClientFormModal.tsx:58"}, "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-a68d083fbf35aeeb", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/ChatPanel.tsx:1186", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/ChatPanel.tsx:1186"}, "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-c3d892c5abdd6f6d", "name": "Stray `console.log` in TS/JS \u2014 src/components/ChatPanel.tsx:836", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 src/components/ChatPanel.tsx:836"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-b209c77e83b119fd", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 src/components/ui/chart.tsx:70", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 src/components/ui/chart.tsx:70"}, "fullDescription": {"text": "Open XSS surface unless the input is provably trusted. Replace with explicit JSX or sanitize via a vetted library.\n\nWhy: OWASP basics. Already partially flagged by the security analyzer.\nRule id: fq.dangerous-html"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-e909add39d71bc2b", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/crm/PipelineCard.tsx:82", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/crm/PipelineCard.tsx:82"}, "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-dc877f7a3fa66033", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/crm/CrmKanban.tsx:162", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/crm/CrmKanban.tsx:162"}, "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-17d91e1610c71c44", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/crm/CompanyColumn.tsx:61", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/crm/CompanyColumn.tsx:61"}, "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-8106581973f6dcfb", "name": "`truncate` class without `title=` for hover reveal \u2014 src/pages/ClientScenarios.tsx:1164", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/pages/ClientScenarios.tsx:1164"}, "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-f83280f03c5339ab", "name": "`truncate` class without `title=` for hover reveal \u2014 src/pages/DataAssumptions.tsx:714", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/pages/DataAssumptions.tsx:714"}, "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-d40effc3ea818ebb", "name": "`truncate` class without `title=` for hover reveal \u2014 src/pages/AgentHome.tsx:365", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/pages/AgentHome.tsx:365"}, "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-a9a4c4c2729750bc", "name": "\"active\" state uses light bg in a dark theme \u2014 src/landing/components-new/Hero.tsx:141", "shortDescription": {"text": "\"active\" state uses light bg in a dark theme \u2014 src/landing/components-new/Hero.tsx:141"}, "fullDescription": {"text": "A ternary like `active ? 'bg-white' : '...'` (or bg-gray-100/200) on a dark theme produces jarring white pills. Use a dark-emphasized active state instead \u2014 border + ring or slightly brighter dark bg. Example: `active ? 'bg-gray-800 border-gray-500 ring-1 ring-blue-500/30' : '\u2026'`.\n\nWhy: P-E in CHECKLIST.md \u2014 light bg in a dark theme is a class of regression.\nRule id: fq.active-light-bg"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-56c4f03d18e1ad7a", "name": "React Flow edge with `label=` but no project-wide edge-label CSS override \u2014 src/hooks/usePortfolioProjection.ts:1293", "shortDescription": {"text": "React Flow edge with `label=` but no project-wide edge-label CSS override \u2014 src/hooks/usePortfolioProjection.ts:1293"}, "fullDescription": {"text": "React Flow edge labels render with a white rectangle behind the text by default, which scatters bright boxes across a dark canvas. Either drop the label, or override `.react-flow__edge-textbg` and `.react-flow__edge-text` in your stylesheet.\n\nWhy: P-H in CHECKLIST.md \u2014 vendor edge labels bleed white through a dark canvas.\nRule id: fq.edge-label.no-bg"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-5ebc64979a52f0dd", "name": "`truncate` class without `title=` for hover reveal \u2014 src/portal/PortalSidebar.tsx:135", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/portal/PortalSidebar.tsx:135"}, "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-2e9f9f4ec1d44b7a", "name": "\"active\" state uses light bg in a dark theme \u2014 src/portal/PortalSidebar.tsx:91", "shortDescription": {"text": "\"active\" state uses light bg in a dark theme \u2014 src/portal/PortalSidebar.tsx:91"}, "fullDescription": {"text": "A ternary like `active ? 'bg-white' : '...'` (or bg-gray-100/200) on a dark theme produces jarring white pills. Use a dark-emphasized active state instead \u2014 border + ring or slightly brighter dark bg. Example: `active ? 'bg-gray-800 border-gray-500 ring-1 ring-blue-500/30' : '\u2026'`.\n\nWhy: P-E in CHECKLIST.md \u2014 light bg in a dark theme is a class of regression.\nRule id: fq.active-light-bg"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-7176e5d95d18d844", "name": "Runtime dotenv file present in repo: .env", "shortDescription": {"text": "Runtime dotenv file present in repo: .env"}, "fullDescription": {"text": "`.env` looks like a runtime dotenv file. It contains secret-looking assignments for VITE_SUPABASE_PUBLISHABLE_KEY. Move real values to a secret manager and keep only `.env.example` style templates in source control."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "critical", "confidence": 1.0}}, {"id": "scanner-9bbb1bc9b6930892", "name": "Insecure pattern 'cors_wildcard' in supabase/functions/create-client-user/index.ts:25", "shortDescription": {"text": "Insecure pattern 'cors_wildcard' in supabase/functions/create-client-user/index.ts:25"}, "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-6abe34d880fb2fcc", "name": "Insecure pattern 'cors_wildcard' in supabase/functions/create-checkout/index.ts:21", "shortDescription": {"text": "Insecure pattern 'cors_wildcard' in supabase/functions/create-checkout/index.ts:21"}, "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-629fd991944e2218", "name": "Insecure pattern 'cors_wildcard' in supabase/functions/send-onboarding-form/index.ts:12", "shortDescription": {"text": "Insecure pattern 'cors_wildcard' in supabase/functions/send-onboarding-form/index.ts:12"}, "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-7c0986aaf1065e1e", "name": "Insecure pattern 'cors_wildcard' in supabase/functions/nl-parse/index.ts:28", "shortDescription": {"text": "Insecure pattern 'cors_wildcard' in supabase/functions/nl-parse/index.ts:28"}, "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-1e5accbfe9032448", "name": "Possible secret in src/components/TopBar.tsx", "shortDescription": {"text": "Possible secret in src/components/TopBar.tsx"}, "fullDescription": {"text": "Detected pattern matching password_literal. Rotate the credential and move to a secret manager."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "critical", "confidence": 1.0}}, {"id": "scanner-93d0283845aa2c2d", "name": "Insecure pattern 'dangerous_innerhtml' in src/components/ui/chart.tsx:70", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in src/components/ui/chart.tsx:70"}, "fullDescription": {"text": "Found a known-risky pattern (dangerous_innerhtml). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-2deb6416e3711d08", "name": "Possible secret in src/client-view/ClientDashboard.tsx", "shortDescription": {"text": "Possible secret in src/client-view/ClientDashboard.tsx"}, "fullDescription": {"text": "Detected pattern matching password_literal. Rotate the credential and move to a secret manager."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "critical", "confidence": 1.0}}, {"id": "scanner-3a5ba31820f16a3c", "name": "Possible secret in src/pages/ClientScenarios.tsx", "shortDescription": {"text": "Possible secret in src/pages/ClientScenarios.tsx"}, "fullDescription": {"text": "Detected pattern matching password_literal. Rotate the credential and move to a secret manager."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "critical", "confidence": 1.0}}, {"id": "scanner-4601e3ad3bb28677", "name": "No CI/CD pipelines detected", "shortDescription": {"text": "No CI/CD pipelines detected"}, "fullDescription": {"text": "No GitHub Actions, GitLab CI, or CircleCI configs found. Without CI you can't gate deploys on tests/lints."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-dd776f2f450eee20", "name": "Very large file: incoming-redesign/src/App.tsx (1078 lines)", "shortDescription": {"text": "Very large file: incoming-redesign/src/App.tsx (1078 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-15349b99e449d25f", "name": "Very large file: supabase/functions/nl-parse/system-prompt.ts (1277 lines)", "shortDescription": {"text": "Very large file: supabase/functions/nl-parse/system-prompt.ts (1277 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-134ff1233b0e4612", "name": "Very large file: src/components/GuardrailFixModal.tsx (1159 lines)", "shortDescription": {"text": "Very large file: src/components/GuardrailFixModal.tsx (1159 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-ce2a173489a0b47b", "name": "Very large file: src/components/ConfirmationBrief.tsx (1131 lines)", "shortDescription": {"text": "Very large file: src/components/ConfirmationBrief.tsx (1131 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-d69a4b18c9c94f19", "name": "Very large file: src/components/TimelinePanel.tsx (1406 lines)", "shortDescription": {"text": "Very large file: src/components/TimelinePanel.tsx (1406 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-fbbb3d0bb86c4c44", "name": "Very large file: src/components/ChatPanel.tsx (1262 lines)", "shortDescription": {"text": "Very large file: src/components/ChatPanel.tsx (1262 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-31c2f5800a74f7ee", "name": "Very large file: src/pages/ClientScenarios.tsx (1659 lines)", "shortDescription": {"text": "Very large file: src/pages/ClientScenarios.tsx (1659 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-0303330ab749a747", "name": "Very large file: src/pages/DataAssumptions.tsx (1148 lines)", "shortDescription": {"text": "Very large file: src/pages/DataAssumptions.tsx (1148 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-126e83b0e84e2d4d", "name": "Very large file: src/hooks/useAffordabilityCalculator.ts (1286 lines)", "shortDescription": {"text": "Very large file: src/hooks/useAffordabilityCalculator.ts (1286 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-e92abf93c6261492", "name": "Very large file: src/hooks/usePortfolioProjection.ts (1519 lines)", "shortDescription": {"text": "Very large file: src/hooks/usePortfolioProjection.ts (1519 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-6893a6c8b0861585", "name": "Very low test-to-source ratio", "shortDescription": {"text": "Very low test-to-source ratio"}, "fullDescription": {"text": "7 test file(s) for 411 source file(s) (ratio 0.02). Consider adding integration or unit tests for critical paths."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-141b30a41e03817b", "name": "No license file detected", "shortDescription": {"text": "No license file detected"}, "fullDescription": {"text": "No LICENSE/COPYING/NOTICE file was found. Generated repositories often omit licensing, which blocks reuse and automated intake."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-fba0e969ecc76135", "name": "Node manifest has dependencies but no lockfile: incoming-redesign/package.json", "shortDescription": {"text": "Node manifest has dependencies but no lockfile: incoming-redesign/package.json"}, "fullDescription": {"text": "`package.json` declares dependencies, but no same-directory npm/pnpm/yarn/bun lockfile was found. Generated projects without lockfiles are less reproducible and harder to secure-scan precisely."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-3ab5d313dda8e5f9", "name": "Debug logging residue appears in source files", "shortDescription": {"text": "Debug logging residue appears in source files"}, "fullDescription": {"text": "Found 307 console/debugger/print-style debug statements in non-test source. This is a common fast-generation residue before production cleanup."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-72b2a6250083a784", "name": "Placeholder or mock-heavy implementation detected", "shortDescription": {"text": "Placeholder or mock-heavy implementation detected"}, "fullDescription": {"text": "Found 147 placeholder/mock markers across 54 source files. This often means the repo looks complete while core flows still use generated scaffolding or fake data."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-2d0c7b7ab8f8aacf", "name": "Critical user flow still appears backed by mock or placeholder data", "shortDescription": {"text": "Critical user flow still appears backed by mock or placeholder data"}, "fullDescription": {"text": "A payment/auth/admin/order/billing-style flow contains mock, fake, TODO, dummy, or placeholder markers in runtime source. In the Fable corpus this is a high-leverage completeness smell: the app can look finished while the money, identity, or tenant flow is still scaffolded."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-b9088664ace7f748", "name": "Composite production-readiness gap", "shortDescription": {"text": "Composite production-readiness gap"}, "fullDescription": {"text": "Multiple low-cost hardening controls are missing together: license, ci, lockfile. Opus verification showed these co-occurring gaps are a better readiness signal than reading each flag in isolation."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-749d4bc1bd66df5f", "name": "Agent instructions exist but release-hardening basics are missing", "shortDescription": {"text": "Agent instructions exist but release-hardening basics are missing"}, "fullDescription": {"text": "AI-coder instruction files were found, but the repo is missing license, ci, lockfile. Treat this as a contract gap: the agent is guided, but the generated output is not yet guarded by the controls that make it repeatable."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-ea8f3013f588db25", "name": "Shallow git history limits provenance confidence", "shortDescription": {"text": "Shallow git history limits provenance confidence"}, "fullDescription": {"text": "The repository is a shallow clone. Origin/evolution analysis cannot distinguish fresh generation, imported legacy code, or long-lived human code with high confidence."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8424db9c75e04ba4", "name": "Very short observed git history", "shortDescription": {"text": "Very short observed git history"}, "fullDescription": {"text": "The repo has multiple source files but two or fewer visible commits. This is not a failure by itself, but it lowers confidence in evolution-based diagnosis."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-2c5f98b152cddb6d", "name": "Agent authority lacks a verifier contract: .claude/launch.json", "shortDescription": {"text": "Agent authority lacks a verifier contract: .claude/launch.json"}, "fullDescription": {"text": "This agent instruction grants code or shell authority but does not state the verification gate that decides promotion. The recurring safe pattern is: LLM proposes; deterministic tests/build/security checks verify; only verified code promotes."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-5790ec01f39dd067", "name": "Legacy-named symbol `nOld` in _archive/cursor-sessions/verify-static-rent-fix.cjs:166", "shortDescription": {"text": "Legacy-named symbol `nOld` in _archive/cursor-sessions/verify-static-rent-fix.cjs:166"}, "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-83fc968cc1cd5eec", "name": "Legacy-named symbol `nOld` in _archive/cursor-sessions/verify-static-rent-fix.js:166", "shortDescription": {"text": "Legacy-named symbol `nOld` in _archive/cursor-sessions/verify-static-rent-fix.js:166"}, "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-65be53d8a533e227", "name": "Commented-code block (6 lines) in remotion/src/scenes/Scene4Timeline.tsx:44", "shortDescription": {"text": "Commented-code block (6 lines) in remotion/src/scenes/Scene4Timeline.tsx:44"}, "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-292906289dba90b4", "name": "Legacy-named symbol `Client_Report_FINAL_v2` in remotion/src/scenes/Scene2Problem.tsx:73", "shortDescription": {"text": "Legacy-named symbol `Client_Report_FINAL_v2` in remotion/src/scenes/Scene2Problem.tsx:73"}, "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-150c1ee8bae6bb2e", "name": "`fetch()` without try/.catch or AbortSignal \u2014 supabase/functions/send-onboarding-form/index.ts:164", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 supabase/functions/send-onboarding-form/index.ts:164"}, "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-46f45e310ad97551", "name": "Legacy-named symbol `proppath_legacy_scenario_wipe_v1` in src/main.tsx:18", "shortDescription": {"text": "Legacy-named symbol `proppath_legacy_scenario_wipe_v1` in src/main.tsx:18"}, "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-02deb10a6c366f65", "name": "Commented-code block (7 lines) in src/constants/financialParams.ts:282", "shortDescription": {"text": "Commented-code block (7 lines) in src/constants/financialParams.ts:282"}, "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-793322c6d873e038", "name": "Commented-code block (6 lines) in src/utils/metricsCalculator.ts:444", "shortDescription": {"text": "Commented-code block (6 lines) in src/utils/metricsCalculator.ts:444"}, "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-37ca235e57f90c35", "name": "Commented-code block (5 lines) in src/utils/suggestedFixes.ts:329", "shortDescription": {"text": "Commented-code block (5 lines) in src/utils/suggestedFixes.ts:329"}, "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-f02ff56d08b31493", "name": "Commented-code block (6 lines) in src/utils/nlDataMapper.ts:446", "shortDescription": {"text": "Commented-code block (6 lines) in src/utils/nlDataMapper.ts:446"}, "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-36ce006011178065", "name": "Commented-code block (5 lines) in src/utils/borrowingPowerCalculator.ts:253", "shortDescription": {"text": "Commented-code block (5 lines) in src/utils/borrowingPowerCalculator.ts:253"}, "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-2f2a6b9878f76910", "name": "Legacy-named symbol `normalisedLegacy` in src/utils/propertyInstanceDefaults.ts:89", "shortDescription": {"text": "Legacy-named symbol `normalisedLegacy` in src/utils/propertyInstanceDefaults.ts:89"}, "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-cb6ff2093a138131", "name": "Commented-code block (7 lines) in src/components/ChatLoadingSteps.tsx:53", "shortDescription": {"text": "Commented-code block (7 lines) in src/components/ChatLoadingSteps.tsx:53"}, "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-5fccf40dece11c01", "name": "Commented-code block (6 lines) in src/components/SummaryBar.tsx:50", "shortDescription": {"text": "Commented-code block (6 lines) in src/components/SummaryBar.tsx:50"}, "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-6bdd67db1d5cb42b", "name": "Commented-code block (7 lines) in src/components/TopBar.tsx:237", "shortDescription": {"text": "Commented-code block (7 lines) in src/components/TopBar.tsx:237"}, "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-07ee9091ee085929", "name": "Commented-code block (5 lines) in src/components/ChatPanel.tsx:174", "shortDescription": {"text": "Commented-code block (5 lines) in src/components/ChatPanel.tsx:174"}, "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-063d37d062cb6002", "name": "Commented-code block (5 lines) in src/contexts/PropertyDragDropContext.tsx:143", "shortDescription": {"text": "Commented-code block (5 lines) in src/contexts/PropertyDragDropContext.tsx:143"}, "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-27a590e362c20b7e", "name": "Commented-code block (5 lines) in src/contexts/ClientContext.tsx:178", "shortDescription": {"text": "Commented-code block (5 lines) in src/contexts/ClientContext.tsx:178"}, "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-0db65364e3c19b9d", "name": "Commented-code block (5 lines) in src/contexts/ScenarioSaveContext.tsx:195", "shortDescription": {"text": "Commented-code block (5 lines) in src/contexts/ScenarioSaveContext.tsx:195"}, "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-4cb4bbfb7a2f7648", "name": "Commented-code block (6 lines) in src/contexts/MultiScenarioContext.tsx:145", "shortDescription": {"text": "Commented-code block (6 lines) in src/contexts/MultiScenarioContext.tsx:145"}, "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-dd0fab64971a0f40", "name": "Commented-code block (5 lines) in src/contexts/DataAssumptionsContext.tsx:238", "shortDescription": {"text": "Commented-code block (5 lines) in src/contexts/DataAssumptionsContext.tsx: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-f1085eb537f8d72c", "name": "Commented-code block (5 lines) in src/hooks/useSharedScenario.ts:106", "shortDescription": {"text": "Commented-code block (5 lines) in src/hooks/useSharedScenario.ts:106"}, "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-b5039da7cdd863b4", "name": "Commented-code block (5 lines) in src/hooks/useClientSwitching.ts:18", "shortDescription": {"text": "Commented-code block (5 lines) in src/hooks/useClientSwitching.ts:18"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-2b4b07a6e9252ec6", "name": "Commented-code block (5 lines) in src/hooks/useAffordabilityCalculator.ts:846", "shortDescription": {"text": "Commented-code block (5 lines) in src/hooks/useAffordabilityCalculator.ts:846"}, "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-8383a548bd1db776", "name": "Commented-code block (7 lines) in src/hooks/useChatConversation.ts:114", "shortDescription": {"text": "Commented-code block (7 lines) in src/hooks/useChatConversation.ts:114"}, "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-cc002e54aa967c4b", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/portal/PortalPortfolio.tsx:102", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/portal/PortalPortfolio.tsx:102"}, "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-cbb4b5747cde92cb", "name": "Commented-code block (5 lines) in src/engine/planPreCheck.ts:553", "shortDescription": {"text": "Commented-code block (5 lines) in src/engine/planPreCheck.ts:553"}, "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-b334d875f2339fa1", "name": "5 env vars used in code but missing from .env.example", "shortDescription": {"text": "5 env vars used in code but missing from .env.example"}, "fullDescription": {"text": "Drift between code and config docs. The first few: `ANTHROPIC_API_KEY`, `DISABLE_HMR`, `NODE_ENV`, `SUPABASE_SERVICE_ROLE_KEY`, `SUPABASE_URL`. Add them (with a placeholder/comment) to .env.example so onboarding doesn't break."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-ab1a013c936a9236", "name": "Frontend route `/reset-password` has no Link/navigate to it \u2014 src/AppRouter.tsx", "shortDescription": {"text": "Frontend route `/reset-password` has no Link/navigate to it \u2014 src/AppRouter.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-111478dee77fa0c1", "name": "Frontend route `/email-confirmed` has no Link/navigate to it \u2014 src/AppRouter.tsx", "shortDescription": {"text": "Frontend route `/email-confirmed` has no Link/navigate to it \u2014 src/AppRouter.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-eea58a0644314ac3", "name": "Frontend route `/client-view` has no Link/navigate to it \u2014 src/AppRouter.tsx", "shortDescription": {"text": "Frontend route `/client-view` has no Link/navigate to it \u2014 src/AppRouter.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-7478ea05f5c8fc73", "name": "Frontend route `/onboarding/:onboardingId` has no Link/navigate to it \u2014 src/AppRouter.tsx", "shortDescription": {"text": "Frontend route `/onboarding/:onboardingId` has no Link/navigate to it \u2014 src/AppRouter.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-0213a6ea3b9b5ae3", "name": "Frontend route `/retirement` has no Link/navigate to it \u2014 src/AppRouter.tsx", "shortDescription": {"text": "Frontend route `/retirement` has no Link/navigate to it \u2014 src/AppRouter.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-a93dc77ba7b4ab9e", "name": "Frontend route `/assumptions` has no Link/navigate to it \u2014 src/AppRouter.tsx", "shortDescription": {"text": "Frontend route `/assumptions` has no Link/navigate to it \u2014 src/AppRouter.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-b60624dfbd797a17", "name": "Frontend route `/data` has no Link/navigate to it \u2014 src/AppRouter.tsx", "shortDescription": {"text": "Frontend route `/data` has no Link/navigate to it \u2014 src/AppRouter.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-fa35ae244d718d66", "name": "Frontend route `profile` has no Link/navigate to it \u2014 src/AppRouter.tsx", "shortDescription": {"text": "Frontend route `profile` has no Link/navigate to it \u2014 src/AppRouter.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}]}}, "automationDetails": {"id": "repobility/18288"}, "properties": {"repository": "robertknowles/ignito-project-kit", "repoUrl": "https://github.com/robertknowles/ignito-project-kit", "branch": "main"}, "results": [{"ruleId": "foundry_unresolved_feedback", "level": "warning", "message": {"text": "Foundry mined unresolved feedback: robertknowles/ignito-project-kit"}, "properties": {"repobilityId": 466749, "scanner": "foundry_dataset", "fingerprint": "70431459706ef9af86f19f188069489ed107a1a7edd58cdc976be45fa897cda6", "category": "practices", "severity": "medium", "confidence": 0.7, "triageState": "open", "verdict": "needs_review", "isResolved": false, "reason": "Imported from mined Foundry/Fable5 evidence with real GitHub/source provenance. Review source_id before acting.", "evidence": {"meta": {"kind": "graph_query_record", "title": "Human feedback without linked fix evidence", "intent": "Negative/unresolved examples that should not be hallucinated into fixes.", "labels": {"ui_or_frontend": 47, "runtime_failure": 1, "deployment_env_gap": 1, "issue_or_pull_request_thread": 1, "not_resolved_or_not_observed": 4, "human_reported_issue_no_linked_fix": 2, "thread_has_human_issue_without_fix_context": 2}, "source": "graph_query_export", "motif_id": "unlinked_feedback_needs_evidence", "outcomes": {"not_resolved_or_not_observed": 8}, "polarity": "bad", "query_id": "unresolved_feedback", "severity": "medium", "ci_labels": {}, "synthetic": false, "edge_count": 99, "edge_types": {"repo_has_thread": 1, "comment_has_chain": 2, "thread_has_comment": 2, "thread_touches_file": 47, "chain_has_link_quality": 4, "thread_has_fix_outcome": 1, "thread_has_issue_chain": 1, "issue_chain_touches_file": 12, "thread_has_comment_chain": 2, "comment_chain_touches_file": 24, "issue_chain_has_fix_outcome": 1, "issue_chain_has_comment_chain": 2}, "node_count": 59, "node_types": {"repo": 1, "thread": 1, "comment": 2, "pr_file": 47, "fix_outcome": 1, "issue_chain": 1, "link_quality": 4, "comment_chain": 2}, "query_type": "motif_query", "thread_key": "robertknowles/ignito-project-kit#1", "issue_number": "1", "quality_tiers": {"unresolved": 4}, "repo_full_name": "robertknowles/ignito-project-kit", "training_usage": "negative_or_unresolved", "source_motif_id": "graph-pattern-motif-thread-e0fa5d2901458347", "graph_gold_label": "needs_more_evidence", "changed_file_labels": {"ui_or_frontend": 235}}, "text": "Graph query export: Human feedback without linked fix evidence\nQuery id: unresolved_feedback\nQuery type: motif_query\nIntent: Negative/unresolved examples that should not be hallucinated into fixes.\nMotif: unlinked_feedback_needs_evidence\nTraining usage: negative_or_unresolved\nGraph gold label: needs_more_evidence\nRepo: robertknowles/ignito-project-kit\nThread: robertknowles/ignito-project-kit#1\nEvidence:\nGraph motif: Human feedback exists without a linked fix\nMotif id: unlinked_feedback_needs_evidence\nPolarity: bad\nTraining usage: negative_or_unresolved\nSeverity: medium\nRepo: robertknowles/ignito-project-kit\nThread: robertknowles/ignito-project-kit#1\nGraph gold label: needs_more_evidence\nThread graph evidence:\nGitHub issue/PR evidence subgraph\nThread: robertknowles/ignito-project-kit#1\nRepo: robertknowles/ignito-project-kit\nIssue/PR number: 1\nGraph consistency label: needs_more_evidence\nNodes: 59\nEdges: 99\nNode types: {'pr_file': 47, 'link_quality': 4, 'comment': 2, 'comment_chain': 2, 'thread': 1, 'repo': 1, 'issue_chain': 1, 'fix_outcome': 1}\nEdge types: {'thread_touches_file': 47, 'comment_chain_touches_file': 24, 'issue_chain_touches_file': 12, 'chain_has_link_quality': 4, 'thread_has_comment': 2, 'thread_has_comment_chain': 2, 'comment_has_chain': 2, 'issue_chain_has_comment_chain': 2, 'repo_has_thread': 1, 'thread_has_issue_chain': 1, 'thread_has_fix_outcome': 1, 'issue_chain_has_fix_outcome': 1}\nLabels: {'ui_or_frontend': 47, 'not_resolved_or_not_observed': 4, 'human_reported_issue_no_linked_fix': 2, 'thread_has_human_issue_without_fix_context': 2, 'issue_or_pull_request_thread': 1, 'runtime_failure': 1, 'deployment_env_gap': 1}\nOutcomes: {'not_resolved_or_not_observed': 8}\nQuality tiers: {'unresolved': 4}\nCI labels: {}\nCurriculum targets:\n- Teach models to preserve unresolved human feedback instead of hallucinating fixes.\n- Build issue-to-regression examples where no accepted fix exists yet.\nAssumption checks:\n- Can a commit be linked by issue number, SHA, changed path, or time window?\n- If no link exists, is this explicitly labelled unresolved?", "source": "foundry_mined_dataset", "repo_url": "https://github.com/robertknowles/ignito-project-kit", "source_id": "graph-query-motif_query-5a96e55d8082deb2", "synthetic": false, "gold_label": "", "graph_label": "", "source_path": "/data/distillate/foundry_data/graph_queries/unresolved_feedback/shard-0.jsonl", "bundle_label": "", "priority_band": "", "priority_score": 0, "repo_full_name": "robertknowles/ignito-project-kit", "source_dataset": "graph_queries/unresolved_feedback", "training_usage": "negative_or_unresolved"}}}, {"ruleId": "foundry_bad_chain", "level": "error", "message": {"text": "Foundry mined bad chains: robertknowles/ignito-project-kit"}, "properties": {"repobilityId": 444601, "scanner": "foundry_dataset", "fingerprint": "9d0d20d0fdf505d1d091efc9f4ec225c6998c7cff05a501ebf8d8de1acbaefeb", "category": "practices", "severity": "high", "confidence": 0.84, "triageState": "open", "verdict": "confirmed", "isResolved": false, "reason": "Imported from mined Foundry/Fable5 evidence with real GitHub/source provenance. Review source_id before acting.", "evidence": {"meta": {"kind": "comment_chain_pattern_product", "source": "comment_chain_pattern_miner", "product": "bad_chains", "synthetic": false, "thread_key": "robertknowles/ignito-project-kit#1", "human_labels": ["deployment_env_gap", "runtime_failure", "ui_or_frontend"], "issue_number": "1", "thread_label": "thread_has_human_issue_without_fix_context", "outcome_label": "not_resolved_or_not_observed", "source_backed": true, "max_confidence": 0.0, "repo_full_name": "robertknowles/ignito-project-kit", "training_usage": "negative_or_unresolved", "confidence_tier": "unresolved", "source_chain_id": "evidence-chain-issue_chain-cf5be5bb8f07b381", "helicopter_views": {"graphs": 2, "schemas": 2}, "artifact_families": {"ci": 1, "docs": 6, "generated_claims": 1}, "source_chain_kind": "issue_chain", "changed_file_count": 47, "source_graph_label": "source_backed_multi_signal_graph", "changed_file_labels": {"ui_or_frontend": 47}, "linked_commit_count": 0, "helicopter_view_count": 4, "source_artifact_count": 8, "classification_reasons": ["source_graph_has_real_artifacts", "source_graph_has_verification_artifacts", "repo_has_isolated_helicopter_views", "link_quality_unresolved", "high_risk_human_feedback_label"], "linked_ci_commit_count": 0, "verification_artifact_count": 1, "design_schema_api_artifact_count": 0}, "text": "Comment chain pattern product: bad_chains\nRepo: robertknowles/ignito-project-kit\nThread: robertknowles/ignito-project-kit#1\nOutcome: not_resolved_or_not_observed\nThread label: thread_has_human_issue_without_fix_context\nSource graph label: source_backed_multi_signal_graph\nReasons: source_graph_has_real_artifacts, source_graph_has_verification_artifacts, repo_has_isolated_helicopter_views, link_quality_unresolved, high_risk_human_feedback_label\nChain evidence:\nIssue/PR evidence chain: robertknowles/ignito-project-kit#1\nRepo: robertknowles/ignito-project-kit\nThread label: thread_has_human_issue_without_fix_context\nOutcome: not_resolved_or_not_observed\nComment count: 2\nLinked commit count: 0\nLinked CI commit count: 0\nLinked CI labels: {}\nChanged file count: 47\nLabels: {'runtime_failure': 1, 'deployment_env_gap': 1}\nPolarities: {'bad': 2}\nChanged file labels: {'ui_or_frontend': 47}\nExamples:\n[\n  {\n    \"id\": \"github-feedback-comment-d5fd01834806a8d7\",\n    \"kind\": \"pull_request_body\",\n    \"label\": \"runtime_failure\",\n    \"polarity\": \"bad\",\n    \"url\": \"https://github.com/robertknowles/ignito-project-kit/pull/1\",\n    \"text\": \"GitHub feedback: runtime_failure\\nPolarity: bad\\nKind: pull_request_body\\nRepo: robertknowles/ignito-project-kit\\nAuthor: jamescb40-hash (User)\\nURL: https://github.com/robertknowles/ignito-project-kit/pull/1\\nTitle: Remove 47 unused and duplicate components\\nBody:\\nDelete dead code identified through import analysis:\\r\\n- 24 unused components from src/components/\\r\\n- 4 orphaned page files (Index, NotFound, PublicReport variants)\\r\\n- 8 old landing page files (replaced by components-new/)\\r\\n- 11 client-view duplicates (components 2/, pages 2/, ClientView 2)\\r\\n\\r\\nBuild verified \u2014 no broken imports.\"\n  },\n  {\n    \"id\": \"github-feedback-comment-ac7a7b325808495d\",\n    \"kind\": \"issue_comment\",\n    \"label\": \"deployment_env_gap\",\n    \"polarity\": \"bad\",\n    \"url\": \"https://github.com/robertknowles/ignito-project-kit/pull/1#issuecomment-4066944492\",\n    \"text\": \"GitHub feedback: deployment_env_gap\\nPolarity: bad\\nKind: issue_comment\\nRepo: robertknowles/ignito-project-kit\\nAuthor: vercel[bot] (Bot)\\nURL: https://github.com/robertknowles/ignito-project-kit/pull/1#issuecomment-4066944492\\nTitle: \\nBody:\\n[vc]: #PMU0P/UKmdKrdC8ZOn6D/tZH7TDdY7ptDlXJpdumcIM=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJpZ25pdG8tcHJvamVjdC1raXQiLCJwcm9qZWN0SWQiOiJwcmpfOVl0bjJZeVJ4QVVGcXc0V0pSQWRXZ0dCZnllVyIsImxpdmVGZWVkYmFjayI6eyJyZXNvbHZlZCI6MCwidW5yZXNvbHZlZCI6MCwidG90YWwiOjAsImxpbmsiOiJpZ25pdG8tcHJvamVjdC1raXQtZ2l0LWNsYXVkZS1hZmZlYy05ZDNkYWUtcm9iLWtub3dsZXMtcHJvamVjdHMudmVyY2VsLmFwcCJ9LCJpbnNwZWN0b3JVcmwiOiJodHRwczovL3ZlcmNlbC5jb20vcm9iLWtub3dsZXMtcHJvamVjdHMvaWduaXRvLXByb2plY3Qta2l0LzNObmpwSDJIeHZHTHJjanpmV2FUTTlDRE1OYTMiLCJwcmV2aWV3VXJsIjoiaWduaXRvLXByb2plY3Qta2l0LWdpdC1jbGF1ZGUtYWZmZWMtOWQzZGFlLXJvYi1rbm93bGVzLXByb2plY3RzLnZlcmNlbC5hcHAiLCJuZXh0Q29tbWl0U3RhdHVzIjoiREVQTE9ZRUQifV19\\nThe latest up\n[truncated by importer]", "source": "foundry_mined_dataset", "repo_url": "https://github.com/robertknowles/ignito-project-kit", "source_id": "comment-chain-pattern-bad_chains-ba91bc726a78555e", "synthetic": false, "gold_label": "", "graph_label": "source_backed_multi_signal_graph", "source_path": "/data/distillate/foundry_data/comment_chain_patterns/bad_chains/shard-0.jsonl", "bundle_label": "", "priority_band": "", "priority_score": 0, "repo_full_name": "robertknowles/ignito-project-kit", "source_dataset": "comment_chain_patterns/bad_chains", "training_usage": "negative_or_unresolved"}}}, {"ruleId": "scanner-bead75b0f9233e05", "level": "none", "message": {"text": "No API endpoints detected"}, "properties": {"repobilityId": "0f8bb852027c38f8", "scanner": "scanner-primary", "fingerprint": "bead75b0f9233e05", "layer": "api", "severity": "info", "confidence": 1.0, "tags": ["coverage"]}}, {"ruleId": "scanner-52e66fba28636d0b", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 incoming-redesign/src/App.tsx:463"}, "properties": {"repobilityId": "0ba2da71cbc765fb", "scanner": "scanner-primary", "fingerprint": "52e66fba28636d0b", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-c1005674bd0a3db5", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 _archive/cursor-sessions/verify-static-rent-fix.js:16"}, "properties": {"repobilityId": "b78f10e88e94591c", "scanner": "scanner-primary", "fingerprint": "c1005674bd0a3db5", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-421705826fe0d549", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 _archive/cursor-sessions/verify-property-instances-schema.js:186"}, "properties": {"repobilityId": "a5b86a115af96aee", "scanner": "scanner-primary", "fingerprint": "421705826fe0d549", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-e52d40596af7390f", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 _archive/cursor-sessions/verify-lmi.js:14"}, "properties": {"repobilityId": "df736219d4cb06d8", "scanner": "scanner-primary", "fingerprint": "e52d40596af7390f", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-cee3042462f55d77", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 _archive/cursor-sessions/test-all-39-fields.js:78"}, "properties": {"repobilityId": "aad7560ce1e09bd1", "scanner": "scanner-primary", "fingerprint": "cee3042462f55d77", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-d39ad16891dd7118", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 _archive/cursor-sessions/verify-property-instance-persistence.js:27"}, "properties": {"repobilityId": "cd3a188a18f44ada", "scanner": "scanner-primary", "fingerprint": "d39ad16891dd7118", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-df87d5c4065db546", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 scripts/migrate-saved-scenarios.ts:155"}, "properties": {"repobilityId": "eee33fbd5d9f35b2", "scanner": "scanner-primary", "fingerprint": "df87d5c4065db546", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-4f72c71e6a94dcee", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 supabase/functions/stripe-webhook/index.ts:74"}, "properties": {"repobilityId": "7c738a141c293866", "scanner": "scanner-primary", "fingerprint": "4f72c71e6a94dcee", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-5a257ce91c924221", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 evals/run-evals.ts:330"}, "properties": {"repobilityId": "47a782f420c4f05d", "scanner": "scanner-primary", "fingerprint": "5a257ce91c924221", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-9b63a453cc2addfc", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 evals/ab-compare.ts:240"}, "properties": {"repobilityId": "c7e6d15e0bfe1fe3", "scanner": "scanner-primary", "fingerprint": "9b63a453cc2addfc", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-39be0bebf1ef1894", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/ChatOptionCard.tsx:57"}, "properties": {"repobilityId": "a6e8526561546376", "scanner": "scanner-primary", "fingerprint": "39be0bebf1ef1894", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-f372d0407bec5a36", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/AppSidebar.tsx:254"}, "properties": {"repobilityId": "be1e4cca3f3be8bc", "scanner": "scanner-primary", "fingerprint": "f372d0407bec5a36", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-840f4184db8a4306", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/OwnedPropertyCard.tsx:113"}, "properties": {"repobilityId": "94c3f559ceabc668", "scanner": "scanner-primary", "fingerprint": "840f4184db8a4306", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-463170fcd2a0babd", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/PropertySummaryCard.tsx:130"}, "properties": {"repobilityId": "7e3c7406b0db75ca", "scanner": "scanner-primary", "fingerprint": "463170fcd2a0babd", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-091f325000711573", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/NewClientView.tsx:376"}, "properties": {"repobilityId": "11c58f580e82c756", "scanner": "scanner-primary", "fingerprint": "091f325000711573", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-f2dd4f276bc73c62", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/FormTemplateEditor.tsx:96"}, "properties": {"repobilityId": "cbcb5699098f9151", "scanner": "scanner-primary", "fingerprint": "f2dd4f276bc73c62", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-05d5164730731695", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/TimelinePanel.tsx:88"}, "properties": {"repobilityId": "1039cacf07eb6eb3", "scanner": "scanner-primary", "fingerprint": "05d5164730731695", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-a1ee5e9a0875d1cf", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/ClientSelector.tsx:203"}, "properties": {"repobilityId": "c246b536813dce90", "scanner": "scanner-primary", "fingerprint": "a1ee5e9a0875d1cf", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-a3e13171f6b2fb42", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/PropertyTimeline.tsx:81"}, "properties": {"repobilityId": "b33ba89222257438", "scanner": "scanner-primary", "fingerprint": "a3e13171f6b2fb42", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-cf3456791f25afff", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/AddToTimelineModal.tsx:130"}, "properties": {"repobilityId": "a377da4ebef824bc", "scanner": "scanner-primary", "fingerprint": "cf3456791f25afff", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-e0d57b49d86685dc", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/ClientFormModal.tsx:58"}, "properties": {"repobilityId": "1f06b9a536637147", "scanner": "scanner-primary", "fingerprint": "e0d57b49d86685dc", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-a68d083fbf35aeeb", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/ChatPanel.tsx:1186"}, "properties": {"repobilityId": "7144c59fc28663d1", "scanner": "scanner-primary", "fingerprint": "a68d083fbf35aeeb", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-c3d892c5abdd6f6d", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 src/components/ChatPanel.tsx:836"}, "properties": {"repobilityId": "b6f58bb7cab72aa2", "scanner": "scanner-primary", "fingerprint": "c3d892c5abdd6f6d", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-b209c77e83b119fd", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 src/components/ui/chart.tsx:70"}, "properties": {"repobilityId": "b8c68f17a4018107", "scanner": "scanner-primary", "fingerprint": "b209c77e83b119fd", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-e909add39d71bc2b", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/crm/PipelineCard.tsx:82"}, "properties": {"repobilityId": "7e480a4fdde98ab0", "scanner": "scanner-primary", "fingerprint": "e909add39d71bc2b", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-dc877f7a3fa66033", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/crm/CrmKanban.tsx:162"}, "properties": {"repobilityId": "3aba5ada0378709c", "scanner": "scanner-primary", "fingerprint": "dc877f7a3fa66033", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-17d91e1610c71c44", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/crm/CompanyColumn.tsx:61"}, "properties": {"repobilityId": "40299013e4f327ee", "scanner": "scanner-primary", "fingerprint": "17d91e1610c71c44", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-8106581973f6dcfb", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/pages/ClientScenarios.tsx:1164"}, "properties": {"repobilityId": "65d7c0c68b9be34f", "scanner": "scanner-primary", "fingerprint": "8106581973f6dcfb", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-f83280f03c5339ab", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/pages/DataAssumptions.tsx:714"}, "properties": {"repobilityId": "3600eb7c6c197a49", "scanner": "scanner-primary", "fingerprint": "f83280f03c5339ab", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-d40effc3ea818ebb", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/pages/AgentHome.tsx:365"}, "properties": {"repobilityId": "df2ba8f4c30eeba3", "scanner": "scanner-primary", "fingerprint": "d40effc3ea818ebb", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-a9a4c4c2729750bc", "level": "note", "message": {"text": "\"active\" state uses light bg in a dark theme \u2014 src/landing/components-new/Hero.tsx:141"}, "properties": {"repobilityId": "e054a9f6c1d4ac4f", "scanner": "scanner-primary", "fingerprint": "a9a4c4c2729750bc", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.active-light-bg"]}}, {"ruleId": "scanner-56c4f03d18e1ad7a", "level": "note", "message": {"text": "React Flow edge with `label=` but no project-wide edge-label CSS override \u2014 src/hooks/usePortfolioProjection.ts:1293"}, "properties": {"repobilityId": "9bcd226978e4d534", "scanner": "scanner-primary", "fingerprint": "56c4f03d18e1ad7a", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.edge-label.no-bg"]}}, {"ruleId": "scanner-5ebc64979a52f0dd", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/portal/PortalSidebar.tsx:135"}, "properties": {"repobilityId": "5186c3fd54e81d01", "scanner": "scanner-primary", "fingerprint": "5ebc64979a52f0dd", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-2e9f9f4ec1d44b7a", "level": "note", "message": {"text": "\"active\" state uses light bg in a dark theme \u2014 src/portal/PortalSidebar.tsx:91"}, "properties": {"repobilityId": "965cfacdd692f0d7", "scanner": "scanner-primary", "fingerprint": "2e9f9f4ec1d44b7a", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.active-light-bg"]}}, {"ruleId": "scanner-7176e5d95d18d844", "level": "error", "message": {"text": "Runtime dotenv file present in repo: .env"}, "properties": {"repobilityId": "4b9c737a445874ba", "scanner": "scanner-primary", "fingerprint": "7176e5d95d18d844", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets", "config", "env-file", "runtime-env", "env_file_with_secret"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".env"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-9bbb1bc9b6930892", "level": "warning", "message": {"text": "Insecure pattern 'cors_wildcard' in supabase/functions/create-client-user/index.ts:25"}, "properties": {"repobilityId": "0110a2b0bce31feb", "scanner": "scanner-primary", "fingerprint": "9bbb1bc9b6930892", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "cors_wildcard"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "supabase/functions/create-client-user/index.ts"}, "region": {"startLine": 25}}}]}, {"ruleId": "scanner-6abe34d880fb2fcc", "level": "warning", "message": {"text": "Insecure pattern 'cors_wildcard' in supabase/functions/create-checkout/index.ts:21"}, "properties": {"repobilityId": "1fb7bfc2c2e287bc", "scanner": "scanner-primary", "fingerprint": "6abe34d880fb2fcc", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "cors_wildcard"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "supabase/functions/create-checkout/index.ts"}, "region": {"startLine": 21}}}]}, {"ruleId": "scanner-629fd991944e2218", "level": "warning", "message": {"text": "Insecure pattern 'cors_wildcard' in supabase/functions/send-onboarding-form/index.ts:12"}, "properties": {"repobilityId": "c34d3884eacfeaa0", "scanner": "scanner-primary", "fingerprint": "629fd991944e2218", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "cors_wildcard"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "supabase/functions/send-onboarding-form/index.ts"}, "region": {"startLine": 12}}}]}, {"ruleId": "scanner-7c0986aaf1065e1e", "level": "warning", "message": {"text": "Insecure pattern 'cors_wildcard' in supabase/functions/nl-parse/index.ts:28"}, "properties": {"repobilityId": "18cd414396f4049f", "scanner": "scanner-primary", "fingerprint": "7c0986aaf1065e1e", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "cors_wildcard"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "supabase/functions/nl-parse/index.ts"}, "region": {"startLine": 28}}}]}, {"ruleId": "scanner-1e5accbfe9032448", "level": "error", "message": {"text": "Possible secret in src/components/TopBar.tsx"}, "properties": {"repobilityId": "4ef3bc3f81dbbd21", "scanner": "scanner-primary", "fingerprint": "1e5accbfe9032448", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/components/TopBar.tsx"}, "region": {"startLine": 223}}}]}, {"ruleId": "scanner-1e5accbfe9032448", "level": "error", "message": {"text": "Possible secret in src/components/TopBar.tsx"}, "properties": {"repobilityId": "4ef3bc3f81dbbd21", "scanner": "scanner-primary", "fingerprint": "1e5accbfe9032448", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/components/TopBar.tsx"}, "region": {"startLine": 264}}}]}, {"ruleId": "scanner-1e5accbfe9032448", "level": "error", "message": {"text": "Possible secret in src/components/TopBar.tsx"}, "properties": {"repobilityId": "4ef3bc3f81dbbd21", "scanner": "scanner-primary", "fingerprint": "1e5accbfe9032448", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/components/TopBar.tsx"}, "region": {"startLine": 328}}}]}, {"ruleId": "scanner-93d0283845aa2c2d", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in src/components/ui/chart.tsx:70"}, "properties": {"repobilityId": "33f10636e53b4298", "scanner": "scanner-primary", "fingerprint": "93d0283845aa2c2d", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/components/ui/chart.tsx"}, "region": {"startLine": 70}}}]}, {"ruleId": "scanner-2deb6416e3711d08", "level": "error", "message": {"text": "Possible secret in src/client-view/ClientDashboard.tsx"}, "properties": {"repobilityId": "9175aa94f416eeaf", "scanner": "scanner-primary", "fingerprint": "2deb6416e3711d08", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/client-view/ClientDashboard.tsx"}, "region": {"startLine": 152}}}]}, {"ruleId": "scanner-3a5ba31820f16a3c", "level": "error", "message": {"text": "Possible secret in src/pages/ClientScenarios.tsx"}, "properties": {"repobilityId": "6f33dc58b0afe49b", "scanner": "scanner-primary", "fingerprint": "3a5ba31820f16a3c", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/pages/ClientScenarios.tsx"}, "region": {"startLine": 838}}}]}, {"ruleId": "scanner-4601e3ad3bb28677", "level": "warning", "message": {"text": "No CI/CD pipelines detected"}, "properties": {"repobilityId": "c3ee439bce2bc51e", "scanner": "scanner-primary", "fingerprint": "4601e3ad3bb28677", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["coverage"]}}, {"ruleId": "scanner-dd776f2f450eee20", "level": "note", "message": {"text": "Very large file: incoming-redesign/src/App.tsx (1078 lines)"}, "properties": {"repobilityId": "f2d59bc21581577a", "scanner": "scanner-primary", "fingerprint": "dd776f2f450eee20", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-15349b99e449d25f", "level": "note", "message": {"text": "Very large file: supabase/functions/nl-parse/system-prompt.ts (1277 lines)"}, "properties": {"repobilityId": "2bf92dc2f3d2ed63", "scanner": "scanner-primary", "fingerprint": "15349b99e449d25f", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-134ff1233b0e4612", "level": "note", "message": {"text": "Very large file: src/components/GuardrailFixModal.tsx (1159 lines)"}, "properties": {"repobilityId": "2516d38a78a1ea42", "scanner": "scanner-primary", "fingerprint": "134ff1233b0e4612", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-ce2a173489a0b47b", "level": "note", "message": {"text": "Very large file: src/components/ConfirmationBrief.tsx (1131 lines)"}, "properties": {"repobilityId": "df3ca16347ab97f0", "scanner": "scanner-primary", "fingerprint": "ce2a173489a0b47b", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-d69a4b18c9c94f19", "level": "note", "message": {"text": "Very large file: src/components/TimelinePanel.tsx (1406 lines)"}, "properties": {"repobilityId": "b2ba03c3fc9854a4", "scanner": "scanner-primary", "fingerprint": "d69a4b18c9c94f19", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-fbbb3d0bb86c4c44", "level": "note", "message": {"text": "Very large file: src/components/ChatPanel.tsx (1262 lines)"}, "properties": {"repobilityId": "7adaa492e35fe5ac", "scanner": "scanner-primary", "fingerprint": "fbbb3d0bb86c4c44", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-31c2f5800a74f7ee", "level": "note", "message": {"text": "Very large file: src/pages/ClientScenarios.tsx (1659 lines)"}, "properties": {"repobilityId": "bf5081eea8758de8", "scanner": "scanner-primary", "fingerprint": "31c2f5800a74f7ee", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-0303330ab749a747", "level": "note", "message": {"text": "Very large file: src/pages/DataAssumptions.tsx (1148 lines)"}, "properties": {"repobilityId": "54e64e9eba61342d", "scanner": "scanner-primary", "fingerprint": "0303330ab749a747", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-126e83b0e84e2d4d", "level": "note", "message": {"text": "Very large file: src/hooks/useAffordabilityCalculator.ts (1286 lines)"}, "properties": {"repobilityId": "3fb92a3bcea6dce6", "scanner": "scanner-primary", "fingerprint": "126e83b0e84e2d4d", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-e92abf93c6261492", "level": "note", "message": {"text": "Very large file: src/hooks/usePortfolioProjection.ts (1519 lines)"}, "properties": {"repobilityId": "a02a78079988bd4a", "scanner": "scanner-primary", "fingerprint": "e92abf93c6261492", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-6893a6c8b0861585", "level": "warning", "message": {"text": "Very low test-to-source ratio"}, "properties": {"repobilityId": "54a7de3f06314bf0", "scanner": "scanner-primary", "fingerprint": "6893a6c8b0861585", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["tests", "coverage"]}}, {"ruleId": "scanner-141b30a41e03817b", "level": "note", "message": {"text": "No license file detected"}, "properties": {"repobilityId": "4627a7edccea418e", "scanner": "scanner-primary", "fingerprint": "141b30a41e03817b", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["license", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-fba0e969ecc76135", "level": "note", "message": {"text": "Node manifest has dependencies but no lockfile: incoming-redesign/package.json"}, "properties": {"repobilityId": "b4b3afac300c1bef", "scanner": "scanner-primary", "fingerprint": "fba0e969ecc76135", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["dependency", "lockfile", "reproducibility", "generated-repo-pattern"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "incoming-redesign/package.json"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-3ab5d313dda8e5f9", "level": "note", "message": {"text": "Debug logging residue appears in source files"}, "properties": {"repobilityId": "64655a3af0d2cb0f", "scanner": "scanner-primary", "fingerprint": "3ab5d313dda8e5f9", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["debug", "cleanup", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-72b2a6250083a784", "level": "warning", "message": {"text": "Placeholder or mock-heavy implementation detected"}, "properties": {"repobilityId": "bd9a628519b0abc3", "scanner": "scanner-primary", "fingerprint": "72b2a6250083a784", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "mock-data", "incomplete", "generated-repo-pattern"]}}, {"ruleId": "scanner-2d0c7b7ab8f8aacf", "level": "warning", "message": {"text": "Critical user flow still appears backed by mock or placeholder data"}, "properties": {"repobilityId": "242be64d29625fa7", "scanner": "scanner-primary", "fingerprint": "2d0c7b7ab8f8aacf", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "mock-data", "critical-flow", "generated-repo-pattern"]}}, {"ruleId": "scanner-b9088664ace7f748", "level": "warning", "message": {"text": "Composite production-readiness gap"}, "properties": {"repobilityId": "e52008c05e2f188b", "scanner": "scanner-primary", "fingerprint": "b9088664ace7f748", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["production-readiness", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-749d4bc1bd66df5f", "level": "warning", "message": {"text": "Agent instructions exist but release-hardening basics are missing"}, "properties": {"repobilityId": "1e1df2f81b86d1c9", "scanner": "scanner-primary", "fingerprint": "749d4bc1bd66df5f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-ea8f3013f588db25", "level": "note", "message": {"text": "Shallow git history limits provenance confidence"}, "properties": {"repobilityId": "c42999eb1c172595", "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": "d432e2b34e9f9ad0", "scanner": "scanner-primary", "fingerprint": "8424db9c75e04ba4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["provenance", "git-history", "generated-repo-pattern"]}}, {"ruleId": "scanner-2c5f98b152cddb6d", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: .claude/launch.json"}, "properties": {"repobilityId": "0de48c0f4ab303d8", "scanner": "scanner-primary", "fingerprint": "2c5f98b152cddb6d", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "claude_instruction"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".claude/launch.json"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-5790ec01f39dd067", "level": "note", "message": {"text": "Legacy-named symbol `nOld` in _archive/cursor-sessions/verify-static-rent-fix.cjs:166"}, "properties": {"repobilityId": "8ad75932122b66ec", "scanner": "scanner-primary", "fingerprint": "5790ec01f39dd067", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-83fc968cc1cd5eec", "level": "note", "message": {"text": "Legacy-named symbol `nOld` in _archive/cursor-sessions/verify-static-rent-fix.js:166"}, "properties": {"repobilityId": "936ee5ab5c3995f8", "scanner": "scanner-primary", "fingerprint": "83fc968cc1cd5eec", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-65be53d8a533e227", "level": "none", "message": {"text": "Commented-code block (6 lines) in remotion/src/scenes/Scene4Timeline.tsx:44"}, "properties": {"repobilityId": "fa9b6eee8ecba954", "scanner": "scanner-primary", "fingerprint": "65be53d8a533e227", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-292906289dba90b4", "level": "note", "message": {"text": "Legacy-named symbol `Client_Report_FINAL_v2` in remotion/src/scenes/Scene2Problem.tsx:73"}, "properties": {"repobilityId": "f482aaa912977442", "scanner": "scanner-primary", "fingerprint": "292906289dba90b4", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-150c1ee8bae6bb2e", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 supabase/functions/send-onboarding-form/index.ts:164"}, "properties": {"repobilityId": "f958435baad7ed4e", "scanner": "scanner-primary", "fingerprint": "150c1ee8bae6bb2e", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-46f45e310ad97551", "level": "note", "message": {"text": "Legacy-named symbol `proppath_legacy_scenario_wipe_v1` in src/main.tsx:18"}, "properties": {"repobilityId": "cd70cefd8751e1ca", "scanner": "scanner-primary", "fingerprint": "46f45e310ad97551", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-02deb10a6c366f65", "level": "none", "message": {"text": "Commented-code block (7 lines) in src/constants/financialParams.ts:282"}, "properties": {"repobilityId": "48c34eda0a54b9a7", "scanner": "scanner-primary", "fingerprint": "02deb10a6c366f65", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-793322c6d873e038", "level": "none", "message": {"text": "Commented-code block (6 lines) in src/utils/metricsCalculator.ts:444"}, "properties": {"repobilityId": "d4e4c5ef7bef61b6", "scanner": "scanner-primary", "fingerprint": "793322c6d873e038", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-37ca235e57f90c35", "level": "none", "message": {"text": "Commented-code block (5 lines) in src/utils/suggestedFixes.ts:329"}, "properties": {"repobilityId": "9f6d62f903da2567", "scanner": "scanner-primary", "fingerprint": "37ca235e57f90c35", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-f02ff56d08b31493", "level": "none", "message": {"text": "Commented-code block (6 lines) in src/utils/nlDataMapper.ts:446"}, "properties": {"repobilityId": "e13a6b0c91aeb877", "scanner": "scanner-primary", "fingerprint": "f02ff56d08b31493", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-36ce006011178065", "level": "none", "message": {"text": "Commented-code block (5 lines) in src/utils/borrowingPowerCalculator.ts:253"}, "properties": {"repobilityId": "131cec48fbf72209", "scanner": "scanner-primary", "fingerprint": "36ce006011178065", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-2f2a6b9878f76910", "level": "note", "message": {"text": "Legacy-named symbol `normalisedLegacy` in src/utils/propertyInstanceDefaults.ts:89"}, "properties": {"repobilityId": "1828c284728aa571", "scanner": "scanner-primary", "fingerprint": "2f2a6b9878f76910", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-cb6ff2093a138131", "level": "none", "message": {"text": "Commented-code block (7 lines) in src/components/ChatLoadingSteps.tsx:53"}, "properties": {"repobilityId": "c1d2ba3c8d2b2ab2", "scanner": "scanner-primary", "fingerprint": "cb6ff2093a138131", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-5fccf40dece11c01", "level": "none", "message": {"text": "Commented-code block (6 lines) in src/components/SummaryBar.tsx:50"}, "properties": {"repobilityId": "a4e35e0c40952438", "scanner": "scanner-primary", "fingerprint": "5fccf40dece11c01", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-6bdd67db1d5cb42b", "level": "none", "message": {"text": "Commented-code block (7 lines) in src/components/TopBar.tsx:237"}, "properties": {"repobilityId": "14f570c7748fa70f", "scanner": "scanner-primary", "fingerprint": "6bdd67db1d5cb42b", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-07ee9091ee085929", "level": "none", "message": {"text": "Commented-code block (5 lines) in src/components/ChatPanel.tsx:174"}, "properties": {"repobilityId": "50024d0cf659cdfb", "scanner": "scanner-primary", "fingerprint": "07ee9091ee085929", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-063d37d062cb6002", "level": "none", "message": {"text": "Commented-code block (5 lines) in src/contexts/PropertyDragDropContext.tsx:143"}, "properties": {"repobilityId": "fdd6b6ea8ac1befb", "scanner": "scanner-primary", "fingerprint": "063d37d062cb6002", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-27a590e362c20b7e", "level": "none", "message": {"text": "Commented-code block (5 lines) in src/contexts/ClientContext.tsx:178"}, "properties": {"repobilityId": "bd3ea2fadfaebfdf", "scanner": "scanner-primary", "fingerprint": "27a590e362c20b7e", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-0db65364e3c19b9d", "level": "none", "message": {"text": "Commented-code block (5 lines) in src/contexts/ScenarioSaveContext.tsx:195"}, "properties": {"repobilityId": "0209fd84aea32d9b", "scanner": "scanner-primary", "fingerprint": "0db65364e3c19b9d", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-4cb4bbfb7a2f7648", "level": "none", "message": {"text": "Commented-code block (6 lines) in src/contexts/MultiScenarioContext.tsx:145"}, "properties": {"repobilityId": "5b759004ac882433", "scanner": "scanner-primary", "fingerprint": "4cb4bbfb7a2f7648", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-dd0fab64971a0f40", "level": "none", "message": {"text": "Commented-code block (5 lines) in src/contexts/DataAssumptionsContext.tsx:238"}, "properties": {"repobilityId": "3cf642b1bba1c237", "scanner": "scanner-primary", "fingerprint": "dd0fab64971a0f40", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-f1085eb537f8d72c", "level": "none", "message": {"text": "Commented-code block (5 lines) in src/hooks/useSharedScenario.ts:106"}, "properties": {"repobilityId": "d3273add13e98c24", "scanner": "scanner-primary", "fingerprint": "f1085eb537f8d72c", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-b5039da7cdd863b4", "level": "none", "message": {"text": "Commented-code block (5 lines) in src/hooks/useClientSwitching.ts:18"}, "properties": {"repobilityId": "8655df06747b9c0e", "scanner": "scanner-primary", "fingerprint": "b5039da7cdd863b4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-2b4b07a6e9252ec6", "level": "none", "message": {"text": "Commented-code block (5 lines) in src/hooks/useAffordabilityCalculator.ts:846"}, "properties": {"repobilityId": "6b828f0cfeaf4a3a", "scanner": "scanner-primary", "fingerprint": "2b4b07a6e9252ec6", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-8383a548bd1db776", "level": "none", "message": {"text": "Commented-code block (7 lines) in src/hooks/useChatConversation.ts:114"}, "properties": {"repobilityId": "2e644eba6344491e", "scanner": "scanner-primary", "fingerprint": "8383a548bd1db776", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-cc002e54aa967c4b", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/portal/PortalPortfolio.tsx:102"}, "properties": {"repobilityId": "1da0deba22671f7d", "scanner": "scanner-primary", "fingerprint": "cc002e54aa967c4b", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-cbb4b5747cde92cb", "level": "none", "message": {"text": "Commented-code block (5 lines) in src/engine/planPreCheck.ts:553"}, "properties": {"repobilityId": "5dacc6c12a407c57", "scanner": "scanner-primary", "fingerprint": "cbb4b5747cde92cb", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-b334d875f2339fa1", "level": "note", "message": {"text": "5 env vars used in code but missing from .env.example"}, "properties": {"repobilityId": "faa38682016f5d53", "scanner": "scanner-primary", "fingerprint": "b334d875f2339fa1", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "config-drift"]}}, {"ruleId": "scanner-ab1a013c936a9236", "level": "warning", "message": {"text": "Frontend route `/reset-password` has no Link/navigate to it \u2014 src/AppRouter.tsx"}, "properties": {"repobilityId": "c2cd66a345552e44", "scanner": "scanner-primary", "fingerprint": "ab1a013c936a9236", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-111478dee77fa0c1", "level": "warning", "message": {"text": "Frontend route `/email-confirmed` has no Link/navigate to it \u2014 src/AppRouter.tsx"}, "properties": {"repobilityId": "ec891f89795003d8", "scanner": "scanner-primary", "fingerprint": "111478dee77fa0c1", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-eea58a0644314ac3", "level": "warning", "message": {"text": "Frontend route `/client-view` has no Link/navigate to it \u2014 src/AppRouter.tsx"}, "properties": {"repobilityId": "68acbe87d4d74975", "scanner": "scanner-primary", "fingerprint": "eea58a0644314ac3", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-7478ea05f5c8fc73", "level": "warning", "message": {"text": "Frontend route `/onboarding/:onboardingId` has no Link/navigate to it \u2014 src/AppRouter.tsx"}, "properties": {"repobilityId": "05334d55c5f48e3e", "scanner": "scanner-primary", "fingerprint": "7478ea05f5c8fc73", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-0213a6ea3b9b5ae3", "level": "warning", "message": {"text": "Frontend route `/retirement` has no Link/navigate to it \u2014 src/AppRouter.tsx"}, "properties": {"repobilityId": "0a866b001c12c383", "scanner": "scanner-primary", "fingerprint": "0213a6ea3b9b5ae3", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-a93dc77ba7b4ab9e", "level": "warning", "message": {"text": "Frontend route `/assumptions` has no Link/navigate to it \u2014 src/AppRouter.tsx"}, "properties": {"repobilityId": "56e2123c846c828a", "scanner": "scanner-primary", "fingerprint": "a93dc77ba7b4ab9e", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-b60624dfbd797a17", "level": "warning", "message": {"text": "Frontend route `/data` has no Link/navigate to it \u2014 src/AppRouter.tsx"}, "properties": {"repobilityId": "dca92d5313d2ecc6", "scanner": "scanner-primary", "fingerprint": "b60624dfbd797a17", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-fa35ae244d718d66", "level": "warning", "message": {"text": "Frontend route `profile` has no Link/navigate to it \u2014 src/AppRouter.tsx"}, "properties": {"repobilityId": "df9005ad2f08024d", "scanner": "scanner-primary", "fingerprint": "fa35ae244d718d66", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}]}]}