{"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: Ricou-IA/majordhome", "shortDescription": {"text": "Foundry mined unresolved feedback: Ricou-IA/majordhome"}, "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: Ricou-IA/majordhome\nThread: Ricou-IA/majordhome#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: Ricou-IA/majordhome\nThread: Ricou-IA/majordhome#1\nGraph gold label: needs_more_evidence\nThread graph evidence:\nGitHub issue/PR evidence subgraph\nThread: Ricou-IA/majordhome#1\nRepo: Ricou-IA/majordhome\nIssue/PR number: 1\nGraph consistency label: needs_more_evidence\nNodes: 54\nEdges: 94\nNode types: {'pr_file': 42, 'link_quality': 4, 'comment': 2, 'comment_chain': 2, 'thread': 1, 'repo': 1, 'issue_chain': 1, 'fix_outcome': 1}\nEdge types: {'thre"}, "properties": {"scanner": "foundry_dataset", "category": "practices", "severity": "medium", "confidence": 0.7, "cwe": "", "owasp": ""}}, {"id": "foundry_schema_ui_api_gap", "name": "Foundry mined schema ui api mismatch: Ricou-IA/majordhome", "shortDescription": {"text": "Foundry mined schema ui api mismatch: Ricou-IA/majordhome"}, "fullDescription": {"text": "Graph query export: Schema, UI, and API mismatch\nQuery id: schema_ui_api_mismatch\nQuery type: motif_query\nIntent: Assumption-check examples for data-path consistency across layers.\nMotif: schema_ui_api_mismatch\nTraining usage: assumption_check\nGraph gold label: needs_more_evidence\nRepo: Ricou-IA/majordhome\nThread: Ricou-IA/majordhome#1\nEvidence:\nGraph motif: Schema, UI, and API evidence do not line up\nMotif id: schema_ui_api_mismatch\nPolarity: bad\nTraining usage: assumption_check\nSeverity: high\nRepo: Ricou-IA/majordhome\nThread: Ricou-IA/majordhome#1\nGraph gold label: needs_more_evidence\nThread graph evidence:\nGitHub issue/PR evidence subgraph\nThread: Ricou-IA/majordhome#1\nRepo: Ricou-IA/majordhome\nIssue/PR number: 1\nGraph consistency label: needs_more_evidence\nNodes: 54\nEdges: 94\nNode types: {'pr_file': 42, 'link_quality': 4, 'comment': 2, 'comment_chain': 2, 'thread': 1, 'repo': 1, 'issue_chain': 1, 'fix_outcome': 1}\nEdge types: {'thread_touches_file': 42, 'comment_chain_touches_file'"}, "properties": {"scanner": "foundry_dataset", "category": "quality", "severity": "high", "confidence": 0.76, "cwe": "", "owasp": ""}}, {"id": "foundry_bad_chain", "name": "Foundry mined bad chains: Ricou-IA/majordhome", "shortDescription": {"text": "Foundry mined bad chains: Ricou-IA/majordhome"}, "fullDescription": {"text": "Comment chain pattern product: bad_chains\nRepo: Ricou-IA/majordhome\nThread: Ricou-IA/majordhome#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: Ricou-IA/majordhome#1\nRepo: Ricou-IA/majordhome\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: 42\nLabels: {'agent_instruction_gap': 1, 'deployment_env_gap': 1}\nPolarities: {'bad': 2}\nChanged file labels: {'schema_or_data': 2, 'dependency_or_build': 3, 'ui_or_frontend': 35, 'api_or_backend': 2}\nExamples:\n[\n  {\n    \"id\": \"github-feedback-comment-02bfcb5b5ef1cd92\",\n    \"kind\": \"pull_"}, "properties": {"scanner": "foundry_dataset", "category": "practices", "severity": "high", "confidence": 0.84, "cwe": "", "owasp": ""}}, {"id": "scanner-ff2d884d04c73a5f", "name": "Stray `console.log` in TS/JS \u2014 supabase/functions/resend-webhook/index.ts:215", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 supabase/functions/resend-webhook/index.ts:215"}, "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-31c3e5810f1a8d8f", "name": "Stray `console.log` in TS/JS \u2014 supabase/functions/invite-client/index.ts:230", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 supabase/functions/invite-client/index.ts:230"}, "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-6784efa6556f9446", "name": "Stray `console.log` in TS/JS \u2014 supabase/functions/voice-extract-fieldreport/index.ts:445", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 supabase/functions/voice-extract-fieldreport/index.ts:445"}, "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-37d840dbf210595e", "name": "Stray `console.log` in TS/JS \u2014 supabase/functions/pennylane-proxy/index.ts:92", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 supabase/functions/pennylane-proxy/index.ts:92"}, "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-93952a624ad690fa", "name": "Stray `console.log` in TS/JS \u2014 supabase/functions/mailing-send/index.ts:567", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 supabase/functions/mailing-send/index.ts:567"}, "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-f26bf0a411018da4", "name": "Stray `console.log` in TS/JS \u2014 supabase/functions/pennylane-sync-quote-status/index.ts:120", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 supabase/functions/pennylane-sync-quote-status/index.ts:120"}, "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-081efe108aa21671", "name": "Stray `console.log` in TS/JS \u2014 supabase/functions/client-change-password/index.ts:88", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 supabase/functions/client-change-password/index.ts:88"}, "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-9e3869b8242f5f90", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/solaire/pages/Simulateur.jsx:241", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/solaire/pages/Simulateur.jsx:241"}, "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-8de50ea04d0076ac", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/voice/components/ClientSearchPanel.jsx:78", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/voice/components/ClientSearchPanel.jsx:78"}, "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-6462be2fe9606742", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/voice/components/ContextSelector.jsx:173", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/voice/components/ContextSelector.jsx:173"}, "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-2b97f96d94091724", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/geogrid/BenchmarkResultTable.jsx:193", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/geogrid/BenchmarkResultTable.jsx:193"}, "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-153553a74db7780d", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/geogrid/ScanHistory.jsx:62", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/geogrid/ScanHistory.jsx:62"}, "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-8506c87c3e86a353", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/devis/DevisProductPicker.jsx:319", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/devis/DevisProductPicker.jsx:319"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-58adddd7e4e2c009", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/devis/DevisStepLines.jsx:52", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/devis/DevisStepLines.jsx:52"}, "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-a49700263dcea6f5", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/chantiers/LinkPennylaneQuoteModal.jsx:1", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/chantiers/LinkPennylaneQuoteModal.jsx:188"}, "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-cac033798b330831", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/chantiers/ChantierModal.jsx:284", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/chantiers/ChantierModal.jsx:284"}, "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-902db1dec08fa13f", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/chantiers/ChantierReceptionSection.jsx:", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/chantiers/ChantierReceptionSection.jsx:320"}, "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-ae4260dcb4d8442b", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/chantiers/ChantierInterventionSection.j", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/chantiers/ChantierInterventionSection.jsx:122"}, "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-5f16efa948680bb8", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/chantiers/ChantierCard.jsx:96", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/chantiers/ChantierCard.jsx: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-2e917dad2c9e3166", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/certificat/StepIndicator.jsx:50", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/certificat/StepIndicator.jsx:50"}, "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-b4973efc85bf6c53", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/shared/KanbanBoard.jsx:67", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/shared/KanbanBoard.jsx:67"}, "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-2027a6eefda30312", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/mailing/EditorTab.jsx:262", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/mailing/EditorTab.jsx:262"}, "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-a4776fb578c9e633", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/mailing/SegmentsTab.jsx:151", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/mailing/SegmentsTab.jsx:151"}, "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-8d71a0483186e251", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/entretiens/ContractCard.jsx:50", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/entretiens/ContractCard.jsx:50"}, "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-bd5e48fdac333879", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/entretiens/EntretienSAVModal.jsx:424", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/entretiens/EntretienSAVModal.jsx:424"}, "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-ab6e90e42965357f", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/entretiens/ContractModal.jsx:56", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/entretiens/ContractModal.jsx:56"}, "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-4798265aa0840b9f", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/entretiens/EntretiensDashboard.jsx:36", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/entretiens/EntretiensDashboard.jsx:36"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-e01e7cab60c8d933", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/entretiens/ContractStepClient.jsx:55", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/entretiens/ContractStepClient.jsx:55"}, "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-ed8e7c506d305023", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/entretiens/EntretienSAVCard.jsx:157", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/entretiens/EntretienSAVCard.jsx:157"}, "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-8474c01f214ff57c", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/entretiens/SectorGroupView.jsx:171", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/entretiens/SectorGroupView.jsx:171"}, "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-8c000e41b7558a23", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/entretiens/CertificatEquipmentRow.jsx:6", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/entretiens/CertificatEquipmentRow.jsx:62"}, "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-5cf7a4a0b841b98d", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/entretiens/ContractStepSummary.jsx:43", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/entretiens/ContractStepSummary.jsx:43"}, "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-bc5052bfc6313d73", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/clients/EquipmentList.jsx:252", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/clients/EquipmentList.jsx:252"}, "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-c196d1e94d917726", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/clients/ClientCard.jsx:58", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/clients/ClientCard.jsx: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-1527b6faee45eb7c", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/pipeline/LeadKanban.jsx:94", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/pipeline/LeadKanban.jsx:94"}, "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-470561d3e29a8739", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/pipeline/QuoteCandidatesModal.jsx:134", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/pipeline/QuoteCandidatesModal.jsx:134"}, "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-6207fabbe013151e", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/pipeline/LeadCard.jsx:249", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/pipeline/LeadCard.jsx:249"}, "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-e3a50156f6188f92", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/pipeline/LinkedQuotesPanel.jsx:52", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/pipeline/LinkedQuotesPanel.jsx:52"}, "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-8cd94fd791946783", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/pipeline/LeadFormSections.jsx:75", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/pipeline/LeadFormSections.jsx:75"}, "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-aeea4588b553f546", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/pipeline/FicheTechniqueModal.jsx:353", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/pipeline/FicheTechniqueModal.jsx:353"}, "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-0a2d9fcf8c9e9a5f", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/pipeline/longTerm/LongTermLeadDrawer.js", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/pipeline/longTerm/LongTermLeadDrawer.jsx:266"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-85cf555b13236439", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/pipeline/longTerm/LongTermTab.jsx:91", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/pipeline/longTerm/LongTermTab.jsx:91"}, "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-35869d416b758ee0", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/territoire/MapSearch.jsx:124", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/territoire/MapSearch.jsx:124"}, "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-918e42ba80e43bfb", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/territoire/MapPopup.jsx:82", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/territoire/MapPopup.jsx: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-794179c772f84e5c", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/planning/EventModal.jsx:816", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/planning/EventModal.jsx:816"}, "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-8cd262d88816794e", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/planning/EventFormSections.jsx:238", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/planning/EventFormSections.jsx:238"}, "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-af95275b8af9389a", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/planning/scheduling/DayResourceGrid.jsx", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/planning/scheduling/DayResourceGrid.jsx:364"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-c4e6bcb1a84375a7", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/meta-ads/MetaAdsCommercialFunnels.jsx:3", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/meta-ads/MetaAdsCommercialFunnels.jsx:37"}, "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-ad0afe5f8c8b7e76", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/PipelineContrats.jsx:174", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/PipelineContrats.jsx:174"}, "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-4e9447e07b69d02d", "name": "\"active\" state uses light bg in a dark theme \u2014 src/apps/artisan/pages/PipelineContrats.jsx:263", "shortDescription": {"text": "\"active\" state uses light bg in a dark theme \u2014 src/apps/artisan/pages/PipelineContrats.jsx:263"}, "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-feec312cbde14e55", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/InterventionDetail.jsx:366", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/InterventionDetail.jsx:366"}, "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-44c2f214d3f069f8", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/Planning.jsx:239", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/Planning.jsx:239"}, "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-8e9cb2842798b55a", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/Profile.jsx:86", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/Profile.jsx:86"}, "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-d6d789d5e85162cf", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/Dashboard.jsx:183", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/Dashboard.jsx:183"}, "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-e765333b7ecc609b", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/settings/SupplierManagement.jsx:910", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/settings/SupplierManagement.jsx:910"}, "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-af5e18bb2722e77d", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/settings/ProductDocumentsPanel.jsx:100", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/settings/ProductDocumentsPanel.jsx:100"}, "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-abc93986737e6b70", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/settings/ProductDetailDrawer.jsx:171", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/settings/ProductDetailDrawer.jsx:171"}, "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-bde775f81bdbdfa6", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/settings/product-detail/ProductCompatibility", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/settings/product-detail/ProductCompatibilitySection.jsx:229"}, "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-b0cecde16a8160ca", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/settings/organization/TerritoryTab.jsx:266", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/settings/organization/TerritoryTab.jsx:266"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-621b2c96ba4c15fd", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/client-detail/ContractPricingSection.jsx:275", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/client-detail/ContractPricingSection.jsx:275"}, "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-ca21997a7d6ef749", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/client-detail/TabInfo.jsx:31", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/client-detail/TabInfo.jsx:31"}, "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-f11e179ac1ee6fcb", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/client-detail/TabInterventions.jsx:64", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/client-detail/TabInterventions.jsx:64"}, "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-86ef8eb809cd1b67", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/client-detail/TabMailings.jsx:311", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/client-detail/TabMailings.jsx:311"}, "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-a35790a45e911b40", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/client-detail/TabContrat.jsx:630", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/client-detail/TabContrat.jsx:630"}, "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-6bc965f40bfb46e7", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/prospection/_shared/components/ProspectTable.jsx:129", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/prospection/_shared/components/ProspectTable.jsx:129"}, "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-ca299e6e2af49da7", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/prospection/_shared/components/SearchSireneModal.jsx:374", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/prospection/_shared/components/SearchSireneModal.jsx:374"}, "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-e902d25d40be7aca", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/prospection/_shared/components/ProspectDrawer.jsx:197", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/prospection/_shared/components/ProspectDrawer.jsx:197"}, "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-3069891bbcce6cbd", "name": "`truncate` class without `title=` for hover reveal \u2014 src/apps/prospection/_shared/components/NafSelector.jsx:304", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/prospection/_shared/components/NafSelector.jsx:304"}, "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-87d81d62967e7370", "name": "TODO/FIXME marker in shipping code \u2014 src/shared/services/clients.service.js:191", "shortDescription": {"text": "TODO/FIXME marker in shipping code \u2014 src/shared/services/clients.service.js:191"}, "fullDescription": {"text": "Track in /reviews or /issues, not as a code comment that rots.\n\nWhy: Drift control \u2014 shouldn't be the same as Quality TODO scanner.\nRule id: fq.todo-marker"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-3252e7552308185c", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/pipeline/dashboard/DashboardFilters.jsx:285", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/pipeline/dashboard/DashboardFilters.jsx:285"}, "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-40d098e8c9dbccaa", "name": "`truncate` class without `title=` for hover reveal \u2014 src/layouts/AppLayout.jsx:160", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/layouts/AppLayout.jsx:160"}, "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-8fd95a2c6aa07e26", "name": "Insecure pattern 'cors_wildcard' in supabase/functions/invite-client/index.ts:39", "shortDescription": {"text": "Insecure pattern 'cors_wildcard' in supabase/functions/invite-client/index.ts:39"}, "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-66d662ea7487d42f", "name": "Insecure pattern 'cors_wildcard' in supabase/functions/mailing-unsubscribe/index.ts:17", "shortDescription": {"text": "Insecure pattern 'cors_wildcard' in supabase/functions/mailing-unsubscribe/index.ts:17"}, "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-d62423ed8375126a", "name": "Insecure pattern 'cors_wildcard' in supabase/functions/contract-signed-notify/index.ts:35", "shortDescription": {"text": "Insecure pattern 'cors_wildcard' in supabase/functions/contract-signed-notify/index.ts:35"}, "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-a47ae3598e706ad1", "name": "Insecure pattern 'cors_wildcard' in supabase/functions/mailing-send/index.ts:47", "shortDescription": {"text": "Insecure pattern 'cors_wildcard' in supabase/functions/mailing-send/index.ts:47"}, "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-1e55b84d286fe4a1", "name": "Insecure pattern 'cors_wildcard' in supabase/functions/gsc-sync/index.ts:34", "shortDescription": {"text": "Insecure pattern 'cors_wildcard' in supabase/functions/gsc-sync/index.ts:34"}, "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-4fb30abcb30fb455", "name": "Insecure pattern 'cors_wildcard' in supabase/functions/client-change-password/index.ts:21", "shortDescription": {"text": "Insecure pattern 'cors_wildcard' in supabase/functions/client-change-password/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-c017265435a8811e", "name": "Insecure pattern 'cors_wildcard' in supabase/functions/gsc-oauth-init/index.ts:100", "shortDescription": {"text": "Insecure pattern 'cors_wildcard' in supabase/functions/gsc-oauth-init/index.ts:100"}, "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-e468b89b3d21a162", "name": "Possible secret in src/apps/artisan/pages/settings/TeamManagement.jsx", "shortDescription": {"text": "Possible secret in src/apps/artisan/pages/settings/TeamManagement.jsx"}, "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-cb639d9a10a47b23", "name": "package.json defines install-time lifecycle scripts", "shortDescription": {"text": "package.json defines install-time lifecycle scripts"}, "fullDescription": {"text": "preinstall/install/postinstall/prepare scripts execute during dependency installation. Review them carefully for network calls, obfuscation, shell execution, or credential access."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "low", "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-cac0764bfb0ec588", "name": "Very large file: src/apps/artisan/components/pipeline/LeadModal.jsx (1344 lines)", "shortDescription": {"text": "Very large file: src/apps/artisan/components/pipeline/LeadModal.jsx (1344 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-b25df49100eca541", "name": "Very large file: src/shared/services/pennylane.service.js (1794 lines)", "shortDescription": {"text": "Very large file: src/shared/services/pennylane.service.js (1794 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": "1 test file(s) for 413 source file(s) (ratio 0.00). 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-3ab5d313dda8e5f9", "name": "Debug logging residue appears in source files", "shortDescription": {"text": "Debug logging residue appears in source files"}, "fullDescription": {"text": "Found 110 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 379 placeholder/mock markers across 101 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. Opus verification showed these co-occurring gaps are a better readiness signal than reading each flag in isolation."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-749d4bc1bd66df5f", "name": "Agent instructions exist but release-hardening basics are missing", "shortDescription": {"text": "Agent instructions exist but release-hardening basics are missing"}, "fullDescription": {"text": "AI-coder instruction files were found, but the repo is missing license, ci. 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-f6441b8371f8deb5", "name": "Agent instruction/config may expose a secret: .claude/proposed-updates.md", "shortDescription": {"text": "Agent instruction/config may expose a secret: .claude/proposed-updates.md"}, "fullDescription": {"text": "Agent-facing files are routinely pasted into LLM/tool contexts. Move literal tokens, keys, and passwords into a secret manager or document them as placeholders only."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-505bc666a82f9849", "name": "Agent instruction/config may expose a secret: .claude/settings.local.json", "shortDescription": {"text": "Agent instruction/config may expose a secret: .claude/settings.local.json"}, "fullDescription": {"text": "Agent-facing files are routinely pasted into LLM/tool contexts. Move literal tokens, keys, and passwords into a secret manager or document them as placeholders only."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-a7b7f0e6e4683c13", "name": "Commented-code block (5 lines) in vite.config.js:14", "shortDescription": {"text": "Commented-code block (5 lines) in vite.config.js:14"}, "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-09f58c9d3f8725b2", "name": "Commented-code block (7 lines) in supabase/functions/resend-webhook/index.ts:8", "shortDescription": {"text": "Commented-code block (7 lines) in supabase/functions/resend-webhook/index.ts:8"}, "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-556930ac5d1b97c8", "name": "Commented-code block (5 lines) in supabase/functions/mailing-scheduler/index.ts:122", "shortDescription": {"text": "Commented-code block (5 lines) in supabase/functions/mailing-scheduler/index.ts:122"}, "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-9e14d68d95e8478a", "name": "`fetch()` without try/.catch or AbortSignal \u2014 supabase/functions/mailing-scheduler/index.ts:97", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 supabase/functions/mailing-scheduler/index.ts:97"}, "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-3cf20e49db78fdb7", "name": "Commented-code block (6 lines) in supabase/functions/voice-extract-fieldreport/index.ts:1", "shortDescription": {"text": "Commented-code block (6 lines) in supabase/functions/voice-extract-fieldreport/index.ts:1"}, "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-050f16b9e7392f0e", "name": "`fetch()` without try/.catch or AbortSignal \u2014 supabase/functions/voice-extract-fieldreport/index.ts:271", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 supabase/functions/voice-extract-fieldreport/index.ts:271"}, "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-8d915f369c3ec34a", "name": "Commented-code block (9 lines) in supabase/functions/pennylane-proxy/index.ts:13", "shortDescription": {"text": "Commented-code block (9 lines) in supabase/functions/pennylane-proxy/index.ts:13"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-ba39e04c32974739", "name": "`fetch()` without try/.catch or AbortSignal \u2014 supabase/functions/pennylane-proxy/index.ts:87", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 supabase/functions/pennylane-proxy/index.ts:87"}, "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-24ed41fb1bbcaf3a", "name": "Commented-code block (5 lines) in supabase/functions/pennylane-sync-cron/index.ts:12", "shortDescription": {"text": "Commented-code block (5 lines) in supabase/functions/pennylane-sync-cron/index.ts:12"}, "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-2116e9a0d6ab95cd", "name": "`fetch()` without try/.catch or AbortSignal \u2014 supabase/functions/pennylane-sync-cron/index.ts:46", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 supabase/functions/pennylane-sync-cron/index.ts:46"}, "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-2518d3bb4e320b50", "name": "Commented-code block (7 lines) in supabase/functions/mailing-unsubscribe/index.ts:1", "shortDescription": {"text": "Commented-code block (7 lines) in supabase/functions/mailing-unsubscribe/index.ts:1"}, "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-40d8ebd43afba2a8", "name": "Commented-code block (6 lines) in supabase/functions/resend-domain-onboard/index.ts:17", "shortDescription": {"text": "Commented-code block (6 lines) in supabase/functions/resend-domain-onboard/index.ts:17"}, "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-a2380d662366be98", "name": "Commented-code block (10 lines) in supabase/functions/contract-signed-notify/index.ts:10", "shortDescription": {"text": "Commented-code block (10 lines) in supabase/functions/contract-signed-notify/index.ts:10"}, "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-657ea66ce2092106", "name": "Commented-code block (19 lines) in supabase/functions/mailing-send/index.ts:1", "shortDescription": {"text": "Commented-code block (19 lines) in supabase/functions/mailing-send/index.ts:1"}, "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-6f736764bbbdd039", "name": "Commented-code block (5 lines) in supabase/functions/gsc-sync/index.ts:9", "shortDescription": {"text": "Commented-code block (5 lines) in supabase/functions/gsc-sync/index.ts:9"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-313b6b08b0a283b3", "name": "`fetch()` without try/.catch or AbortSignal \u2014 supabase/functions/gsc-sync/index.ts:134", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 supabase/functions/gsc-sync/index.ts:134"}, "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-bf7be311a8551f81", "name": "Commented-code block (6 lines) in supabase/functions/pennylane-sync-quote-status/index.ts:421", "shortDescription": {"text": "Commented-code block (6 lines) in supabase/functions/pennylane-sync-quote-status/index.ts:421"}, "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-6529061260bdc899", "name": "Commented-code block (5 lines) in supabase/functions/pennylane-backfill-quotes/index.ts:14", "shortDescription": {"text": "Commented-code block (5 lines) in supabase/functions/pennylane-backfill-quotes/index.ts:14"}, "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-fe97303cc33f1933", "name": "`fetch()` without try/.catch or AbortSignal \u2014 supabase/functions/pennylane-backfill-quotes/index.ts:43", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 supabase/functions/pennylane-backfill-quotes/index.ts:43"}, "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-2b71cafaab9790f4", "name": "Commented-code block (10 lines) in supabase/functions/gsc-oauth-callback/index.ts:13", "shortDescription": {"text": "Commented-code block (10 lines) in supabase/functions/gsc-oauth-callback/index.ts:13"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-e9bd9c69bdbcfe6d", "name": "`fetch()` without try/.catch or AbortSignal \u2014 supabase/functions/gsc-oauth-callback/index.ts:211", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 supabase/functions/gsc-oauth-callback/index.ts:211"}, "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-3f1a5a594a3c66ca", "name": "Commented-code block (5 lines) in supabase/functions/gsc-oauth-init/index.ts:9", "shortDescription": {"text": "Commented-code block (5 lines) in supabase/functions/gsc-oauth-init/index.ts:9"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-d2ee0896f462f2c4", "name": "Commented-code block (5 lines) in supabase/functions/_shared/auth.ts:9", "shortDescription": {"text": "Commented-code block (5 lines) in supabase/functions/_shared/auth.ts:9"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-fe495e8db9b07ece", "name": "Commented-code block (6 lines) in src/apps/solaire/components/MonthlyChart.jsx:1", "shortDescription": {"text": "Commented-code block (6 lines) in src/apps/solaire/components/MonthlyChart.jsx:1"}, "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-4125cf40130be680", "name": "Commented-code block (7 lines) in src/apps/solaire/components/FinancingModule.jsx:1", "shortDescription": {"text": "Commented-code block (7 lines) in src/apps/solaire/components/FinancingModule.jsx:1"}, "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-9a27490e88f5ba23", "name": "Commented-code block (5 lines) in src/apps/solaire/lib/etudeModel.js:1", "shortDescription": {"text": "Commented-code block (5 lines) in src/apps/solaire/lib/etudeModel.js:1"}, "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-72daaf68e5f323fa", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/apps/solaire/lib/etudeExport.js:33", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/apps/solaire/lib/etudeExport.js:33"}, "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-ff5d6f46043e41c5", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/apps/voice/services/voiceMemos.service.js:99", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/apps/voice/services/voiceMemos.service.js:99"}, "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-f2a5b7088316eb63", "name": "Commented-code block (16 lines) in src/apps/artisan/routes.jsx:118", "shortDescription": {"text": "Commented-code block (16 lines) in src/apps/artisan/routes.jsx:118"}, "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-2da224ea03cf8393", "name": "Legacy-named symbol `appointment_legacy` in src/apps/artisan/components/mailing/segmentBuilder.constants.js:37", "shortDescription": {"text": "Legacy-named symbol `appointment_legacy` in src/apps/artisan/components/mailing/segmentBuilder.constants.js:37"}, "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-f378af87a1ab61b9", "name": "Commented-code block (6 lines) in src/apps/artisan/components/mailing/SendTab.jsx:163", "shortDescription": {"text": "Commented-code block (6 lines) in src/apps/artisan/components/mailing/SendTab.jsx:163"}, "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-3b44db8d53e50e02", "name": "Commented-code block (5 lines) in src/apps/artisan/components/mailing/EditorTab.jsx:10", "shortDescription": {"text": "Commented-code block (5 lines) in src/apps/artisan/components/mailing/EditorTab.jsx:10"}, "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-d808605d57cc4bff", "name": "Commented-code block (5 lines) in src/apps/artisan/components/pipeline/LeadKanban.jsx:459", "shortDescription": {"text": "Commented-code block (5 lines) in src/apps/artisan/components/pipeline/LeadKanban.jsx:459"}, "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-bae36482172510e0", "name": "Legacy-named symbol `appointment_legacy` in src/apps/artisan/components/pipeline/LeadModal.jsx:865", "shortDescription": {"text": "Legacy-named symbol `appointment_legacy` in src/apps/artisan/components/pipeline/LeadModal.jsx:865"}, "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-6d90350aaf79ccb3", "name": "Commented-code block (6 lines) in src/apps/artisan/components/pipeline/LeadCard.jsx:151", "shortDescription": {"text": "Commented-code block (6 lines) in src/apps/artisan/components/pipeline/LeadCard.jsx:151"}, "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-64c03b2295a20cc2", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/apps/artisan/components/territoire/useMapZones.js:36", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/apps/artisan/components/territoire/useMapZones.js:36"}, "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-8e9fbb67b0f4aa5a", "name": "Commented-code block (7 lines) in src/apps/artisan/components/planning/EventModal.jsx:135", "shortDescription": {"text": "Commented-code block (7 lines) in src/apps/artisan/components/planning/EventModal.jsx:135"}, "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-5d036ac15cdc75a2", "name": "Commented-code block (5 lines) in src/apps/artisan/components/planning/scheduling/DayResourceGrid.jsx:130", "shortDescription": {"text": "Commented-code block (5 lines) in src/apps/artisan/components/planning/scheduling/DayResourceGrid.jsx:130"}, "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-8a4845af42917de2", "name": "Commented-code block (9 lines) in src/apps/artisan/components/planning/scheduling/SchedulingAssistant.jsx:101", "shortDescription": {"text": "Commented-code block (9 lines) in src/apps/artisan/components/planning/scheduling/SchedulingAssistant.jsx:101"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-3c35222046ea2675", "name": "Commented-code block (5 lines) in src/apps/artisan/pages/ContractSign.jsx:149", "shortDescription": {"text": "Commented-code block (5 lines) in src/apps/artisan/pages/ContractSign.jsx:149"}, "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-33da055c0be78c3c", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/apps/artisan/pages/ContractSign.jsx:107", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/apps/artisan/pages/ContractSign.jsx:107"}, "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-957397e4e4e198e5", "name": "Commented-code block (5 lines) in src/apps/artisan/pages/settings/SolaireSettings.jsx:1", "shortDescription": {"text": "Commented-code block (5 lines) in src/apps/artisan/pages/settings/SolaireSettings.jsx:1"}, "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-4431519c6f083f3b", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/apps/artisan/pages/settings/organization/TerritoryTab.jsx:133", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/apps/artisan/pages/settings/organization/TerritoryTab.jsx:133"}, "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-c2999c7fd77ea108", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/apps/artisan/pages/settings/organization/components/AddressSearch.jsx:", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/apps/artisan/pages/settings/organization/components/AddressSearch.jsx:45"}, "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-ab4276a513e5f94e", "name": "Commented-code block (5 lines) in src/apps/artisan/pages/client-detail/ContractPdfSection.jsx:103", "shortDescription": {"text": "Commented-code block (5 lines) in src/apps/artisan/pages/client-detail/ContractPdfSection.jsx:103"}, "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-dad53262e7c81563", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/apps/prospection/_shared/components/SearchSireneModal.jsx:93", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/apps/prospection/_shared/components/SearchSireneModal.jsx:93"}, "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-a809f47acb018519", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/apps/prospection/_shared/lib/sireneApi.js:83", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/apps/prospection/_shared/lib/sireneApi.js:83"}, "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-e3f1d2883d39ba37", "name": "Commented-code block (5 lines) in src/shared/hooks/usePennylane.js:551", "shortDescription": {"text": "Commented-code block (5 lines) in src/shared/hooks/usePennylane.js:551"}, "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-3923e5d9c1c5d308", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/shared/services/geocoding.service.js:47", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/shared/services/geocoding.service.js:47"}, "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-954444a09209b978", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/shared/services/gsc.service.js:23", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/shared/services/gsc.service.js:23"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-8c1c61479b3801d2", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/shared/services/googleCalendar.service.js:38", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/shared/services/googleCalendar.service.js:38"}, "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-ec457bafe3a8a750", "name": "Legacy-named symbol `appointment_legacy` in src/shared/services/clients.service.js:77", "shortDescription": {"text": "Legacy-named symbol `appointment_legacy` in src/shared/services/clients.service.js:77"}, "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-da1eb55205f409d5", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/shared/services/interventions.service.js:512", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/shared/services/interventions.service.js:512"}, "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-d9199e10c677d535", "name": "Commented-code block (5 lines) in src/shared/services/appointments.service.js:725", "shortDescription": {"text": "Commented-code block (5 lines) in src/shared/services/appointments.service.js:725"}, "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-7541c45a43d4af00", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/shared/services/geogrid.service.js:24", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/shared/services/geogrid.service.js:24"}, "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-ad370f51c64a3a38", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/shared/services/entretiens.service.js:812", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/shared/services/entretiens.service.js:812"}, "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-bd33ecd534deda48", "name": "Commented-code block (9 lines) in src/shared/services/pricing.service.js:419", "shortDescription": {"text": "Commented-code block (9 lines) in src/shared/services/pricing.service.js:419"}, "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-b92913ff24f1f084", "name": "Commented-code block (7 lines) in src/shared/services/pennylane.service.js:28", "shortDescription": {"text": "Commented-code block (7 lines) in src/shared/services/pennylane.service.js:28"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-8045390122552719", "name": "`fetch()` without try/.catch or AbortSignal \u2014 src/shared/services/pennylane.service.js:1131", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/shared/services/pennylane.service.js:1131"}, "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-270d662a1bc2d293", "name": "Commented-code block (7 lines) in src/components/ProtectedRoute.jsx:72", "shortDescription": {"text": "Commented-code block (7 lines) in src/components/ProtectedRoute.jsx:72"}, "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-53f2c35312623d86", "name": "Commented-code block (9 lines) in src/lib/permissionsRegistry.js:1", "shortDescription": {"text": "Commented-code block (9 lines) in src/lib/permissionsRegistry.js:1"}, "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-cc0f9d8e41b33b0e", "name": "11 env vars used in code but missing from .env.example", "shortDescription": {"text": "11 env vars used in code but missing from .env.example"}, "fullDescription": {"text": "Drift between code and config docs. The first few: `PROD`, `SUPABASE_ANON_KEY`, `SUPABASE_SERVICE_KEY`, `VITE_MAPBOX_TOKEN`, `VITE_N8N_WEBHOOK_CONTRACT_PDF`, `VITE_N8N_WEBHOOK_PDF`, `VITE_N8N_WEBHOOK_SIGNED`, `VITE_N8N_WEBHOOK_SMS_AVIS` + 3 more. Add them (with a placeholder/comment) to .env.example so onboarding doesn't break."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-5d3fdd84b07773f0", "name": "Frontend route `/reset-password` has no Link/navigate to it \u2014 src/App.jsx", "shortDescription": {"text": "Frontend route `/reset-password` has no Link/navigate to it \u2014 src/App.jsx"}, "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-5a8b49b88cc3081d", "name": "Frontend route `/auth/callback` has no Link/navigate to it \u2014 src/App.jsx", "shortDescription": {"text": "Frontend route `/auth/callback` has no Link/navigate to it \u2014 src/App.jsx"}, "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-21bbfe3ea5a9139e", "name": "Frontend route `/voice` has no Link/navigate to it \u2014 src/App.jsx", "shortDescription": {"text": "Frontend route `/voice` has no Link/navigate to it \u2014 src/App.jsx"}, "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/18146"}, "properties": {"repository": "Ricou-IA/majordhome", "repoUrl": "https://github.com/Ricou-IA/majordhome", "branch": "main"}, "results": [{"ruleId": "foundry_unresolved_feedback", "level": "warning", "message": {"text": "Foundry mined unresolved feedback: Ricou-IA/majordhome"}, "properties": {"repobilityId": 462801, "scanner": "foundry_dataset", "fingerprint": "d5f33d40824f88b9386f951c42621ebeaa877ca5ced98fd6f0151098ec5abe9d", "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": {"api_or_backend": 2, "schema_or_data": 2, "ui_or_frontend": 35, "deployment_env_gap": 1, "dependency_or_build": 3, "agent_instruction_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": 94, "edge_types": {"repo_has_thread": 1, "comment_has_chain": 2, "thread_has_comment": 2, "thread_touches_file": 42, "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": 54, "node_types": {"repo": 1, "thread": 1, "comment": 2, "pr_file": 42, "fix_outcome": 1, "issue_chain": 1, "link_quality": 4, "comment_chain": 2}, "query_type": "motif_query", "thread_key": "Ricou-IA/majordhome#1", "issue_number": "1", "quality_tiers": {"unresolved": 4}, "repo_full_name": "Ricou-IA/majordhome", "training_usage": "negative_or_unresolved", "source_motif_id": "graph-pattern-motif-thread-b8653bcc37f79969", "graph_gold_label": "needs_more_evidence", "changed_file_labels": {"api_or_backend": 10, "schema_or_data": 10, "ui_or_frontend": 175, "dependency_or_build": 15}}, "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: Ricou-IA/majordhome\nThread: Ricou-IA/majordhome#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: Ricou-IA/majordhome\nThread: Ricou-IA/majordhome#1\nGraph gold label: needs_more_evidence\nThread graph evidence:\nGitHub issue/PR evidence subgraph\nThread: Ricou-IA/majordhome#1\nRepo: Ricou-IA/majordhome\nIssue/PR number: 1\nGraph consistency label: needs_more_evidence\nNodes: 54\nEdges: 94\nNode types: {'pr_file': 42, 'link_quality': 4, 'comment': 2, 'comment_chain': 2, 'thread': 1, 'repo': 1, 'issue_chain': 1, 'fix_outcome': 1}\nEdge types: {'thread_touches_file': 42, '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': 35, 'not_resolved_or_not_observed': 4, 'dependency_or_build': 3, 'schema_or_data': 2, 'api_or_backend': 2, 'human_reported_issue_no_linked_fix': 2, 'thread_has_human_issue_without_fix_context': 2, 'issue_or_pull_request_thread': 1, 'agent_instruction_gap': 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/Ricou-IA/majordhome", "source_id": "graph-query-motif_query-8bbde442396aee16", "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": "Ricou-IA/majordhome", "source_dataset": "graph_queries/unresolved_feedback", "training_usage": "negative_or_unresolved"}}}, {"ruleId": "foundry_schema_ui_api_gap", "level": "error", "message": {"text": "Foundry mined schema ui api mismatch: Ricou-IA/majordhome"}, "properties": {"repobilityId": 452726, "scanner": "foundry_dataset", "fingerprint": "c7f0fed91df57e99f0500d0e4039f8a2db74ccc77002200f15ab9e34f44ad7fb", "category": "quality", "severity": "high", "confidence": 0.76, "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": "Schema, UI, and API mismatch", "intent": "Assumption-check examples for data-path consistency across layers.", "labels": {"api_or_backend": 2, "schema_or_data": 2, "ui_or_frontend": 35, "deployment_env_gap": 1, "dependency_or_build": 3, "agent_instruction_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": "schema_ui_api_mismatch", "outcomes": {"not_resolved_or_not_observed": 8}, "polarity": "bad", "query_id": "schema_ui_api_mismatch", "severity": "high", "ci_labels": {}, "synthetic": false, "edge_count": 94, "edge_types": {"repo_has_thread": 1, "comment_has_chain": 2, "thread_has_comment": 2, "thread_touches_file": 42, "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": 54, "node_types": {"repo": 1, "thread": 1, "comment": 2, "pr_file": 42, "fix_outcome": 1, "issue_chain": 1, "link_quality": 4, "comment_chain": 2}, "query_type": "motif_query", "thread_key": "Ricou-IA/majordhome#1", "issue_number": "1", "quality_tiers": {"unresolved": 4}, "repo_full_name": "Ricou-IA/majordhome", "training_usage": "assumption_check", "source_motif_id": "graph-pattern-motif-thread-f4319e495258a757", "graph_gold_label": "needs_more_evidence", "changed_file_labels": {"api_or_backend": 10, "schema_or_data": 10, "ui_or_frontend": 175, "dependency_or_build": 15}}, "text": "Graph query export: Schema, UI, and API mismatch\nQuery id: schema_ui_api_mismatch\nQuery type: motif_query\nIntent: Assumption-check examples for data-path consistency across layers.\nMotif: schema_ui_api_mismatch\nTraining usage: assumption_check\nGraph gold label: needs_more_evidence\nRepo: Ricou-IA/majordhome\nThread: Ricou-IA/majordhome#1\nEvidence:\nGraph motif: Schema, UI, and API evidence do not line up\nMotif id: schema_ui_api_mismatch\nPolarity: bad\nTraining usage: assumption_check\nSeverity: high\nRepo: Ricou-IA/majordhome\nThread: Ricou-IA/majordhome#1\nGraph gold label: needs_more_evidence\nThread graph evidence:\nGitHub issue/PR evidence subgraph\nThread: Ricou-IA/majordhome#1\nRepo: Ricou-IA/majordhome\nIssue/PR number: 1\nGraph consistency label: needs_more_evidence\nNodes: 54\nEdges: 94\nNode types: {'pr_file': 42, 'link_quality': 4, 'comment': 2, 'comment_chain': 2, 'thread': 1, 'repo': 1, 'issue_chain': 1, 'fix_outcome': 1}\nEdge types: {'thread_touches_file': 42, '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': 35, 'not_resolved_or_not_observed': 4, 'dependency_or_build': 3, 'schema_or_data': 2, 'api_or_backend': 2, 'human_reported_issue_no_linked_fix': 2, 'thread_has_human_issue_without_fix_context': 2, 'issue_or_pull_request_thread': 1, 'agent_instruction_gap': 1, 'deployment_env_gap': 1}\nOutcomes: {'not_resolved_or_not_observed': 8}\nQuality tiers: {'unresolved': 4}\nCI labels: {}\nCurriculum targets:\n- Create schema-to-API-to-UI consistency tasks with migrations and tests.\n- Teach models to verify persistence, route contracts, and UI state together.\nAssumption checks:\n- Do schema changes have matching API and UI handling?\n- Are migrations and tests present for the data path?", "source": "foundry_mined_dataset", "repo_url": "https://github.com/Ricou-IA/majordhome", "source_id": "graph-query-motif_query-1ccfd7991c8a8483", "synthetic": false, "gold_label": "", "graph_label": "", "source_path": "/data/distillate/foundry_data/graph_queries/schema_ui_api_mismatch/shard-0.jsonl", "bundle_label": "", "priority_band": "", "priority_score": 0, "repo_full_name": "Ricou-IA/majordhome", "source_dataset": "graph_queries/schema_ui_api_mismatch", "training_usage": "assumption_check"}}}, {"ruleId": "foundry_bad_chain", "level": "error", "message": {"text": "Foundry mined bad chains: Ricou-IA/majordhome"}, "properties": {"repobilityId": 441565, "scanner": "foundry_dataset", "fingerprint": "5f1a6562acd42acaa21415b9cc3daa2202cd3868c47e25933ef86e9ae467b0c9", "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": "Ricou-IA/majordhome#1", "human_labels": ["agent_instruction_gap", "api_or_backend", "dependency_or_build", "deployment_env_gap", "schema_or_data", "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": "Ricou-IA/majordhome", "training_usage": "negative_or_unresolved", "confidence_tier": "unresolved", "source_chain_id": "evidence-chain-issue_chain-3b25b2d82515f6f7", "helicopter_views": {"schemas": 2}, "artifact_families": {"ci": 1}, "source_chain_kind": "issue_chain", "changed_file_count": 42, "source_graph_label": "source_backed_multi_signal_graph", "changed_file_labels": {"api_or_backend": 2, "schema_or_data": 2, "ui_or_frontend": 35, "dependency_or_build": 3}, "linked_commit_count": 0, "helicopter_view_count": 2, "source_artifact_count": 1, "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: Ricou-IA/majordhome\nThread: Ricou-IA/majordhome#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: Ricou-IA/majordhome#1\nRepo: Ricou-IA/majordhome\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: 42\nLabels: {'agent_instruction_gap': 1, 'deployment_env_gap': 1}\nPolarities: {'bad': 2}\nChanged file labels: {'schema_or_data': 2, 'dependency_or_build': 3, 'ui_or_frontend': 35, 'api_or_backend': 2}\nExamples:\n[\n  {\n    \"id\": \"github-feedback-comment-02bfcb5b5ef1cd92\",\n    \"kind\": \"pull_request_body\",\n    \"label\": \"agent_instruction_gap\",\n    \"polarity\": \"bad\",\n    \"url\": \"https://github.com/Ricou-IA/majordhome/pull/1\",\n    \"text\": \"GitHub feedback: agent_instruction_gap\\nPolarity: bad\\nKind: pull_request_body\\nRepo: Ricou-IA/majordhome\\nAuthor: Ricou-IA (User)\\nURL: https://github.com/Ricou-IA/majordhome/pull/1\\nTitle: Claude/fix startup loop m gjbr\\nBody:\\n\"\n  },\n  {\n    \"id\": \"github-feedback-comment-5dd3a03604da3926\",\n    \"kind\": \"issue_comment\",\n    \"label\": \"deployment_env_gap\",\n    \"polarity\": \"bad\",\n    \"url\": \"https://github.com/Ricou-IA/majordhome/pull/1#issuecomment-3772323548\",\n    \"text\": \"GitHub feedback: deployment_env_gap\\nPolarity: bad\\nKind: issue_comment\\nRepo: Ricou-IA/majordhome\\nAuthor: vercel[bot] (Bot)\\nURL: https://github.com/Ricou-IA/majordhome/pull/1#issuecomment-3772323548\\nTitle: \\nBody:\\n[vc]: #SyYojJb8Hg5PTnoYRoikXICCL8WQZELseIL9wXEivnM=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJtYWpvcmRob21lIiwibGl2ZUZlZWRiYWNrIjp7InJlc29sdmVkIjowLCJ1bnJlc29sdmVkIjowLCJ0b3RhbCI6MCwibGluayI6Im1ham9yZGhvbWUtZ2l0LWNsYXVkZS1maXgtc3RhcnR1cC05YzVkMzMtZXJpYy1wdWRlYmF0cy1wcm9qZWN0cy52ZXJjZWwuYXBwIn0sImluc3BlY3RvclVybCI6Imh0dHBzOi8vdmVyY2VsLmNvbS9lcmljLXB1ZGViYXRzLXByb2plY3RzL21ham9yZGhvbWUvNDJhOUtjTE1iMmRzOWJaZ1FDTWczVkNVRDVNTiIsInByZXZpZXdVcmwiOiJtYWpvcmRob21lLWdpdC1jbGF1ZGUtZml4LXN0YXJ0dXAtOWM1ZDMzLWVyaWMtcHVkZWJhdHMtcHJvamVjdHMudmVyY2VsLmFwcCIsIm5leHRDb21taXRTdGF0dXMiOiJERVBMT1lFRCJ9XX0=\\nThe latest updates on your projects. Learn more about [Vercel for GitHub](https://vercel.link/github-learn-more).\\n\\n| Project | Deployment | Review | Updated (UTC) |\\n| :--- | :----- | :------ | :------ |\\n| [majordhome](https://vercel.com/eric-pudebats-projects/majordhome) | ![Ready](https://vercel.com/static/status/ready.svg) [Ready](https://vercel.com/eric-pudeb\"\n  }\n]\nChanged files:\n[\n  {\n    \"id\": \"github-pr-file-file-fb006da0e3dcdbde\",\n    \"filename\": \"SUPABASE_TABLES_REFERENCE.md\",\n[truncated by importer]", "source": "foundry_mined_dataset", "repo_url": "https://github.com/Ricou-IA/majordhome", "source_id": "comment-chain-pattern-bad_chains-d7eb9a5c8ebfa75c", "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": "Ricou-IA/majordhome", "source_dataset": "comment_chain_patterns/bad_chains", "training_usage": "negative_or_unresolved"}}}, {"ruleId": "scanner-ff2d884d04c73a5f", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 supabase/functions/resend-webhook/index.ts:215"}, "properties": {"repobilityId": "5b2040e110e825ea", "scanner": "scanner-primary", "fingerprint": "ff2d884d04c73a5f", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-31c3e5810f1a8d8f", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 supabase/functions/invite-client/index.ts:230"}, "properties": {"repobilityId": "56e1523c0d181336", "scanner": "scanner-primary", "fingerprint": "31c3e5810f1a8d8f", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-6784efa6556f9446", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 supabase/functions/voice-extract-fieldreport/index.ts:445"}, "properties": {"repobilityId": "08817089a2e2921d", "scanner": "scanner-primary", "fingerprint": "6784efa6556f9446", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-37d840dbf210595e", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 supabase/functions/pennylane-proxy/index.ts:92"}, "properties": {"repobilityId": "5ecd5f899f21d9e7", "scanner": "scanner-primary", "fingerprint": "37d840dbf210595e", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-93952a624ad690fa", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 supabase/functions/mailing-send/index.ts:567"}, "properties": {"repobilityId": "335d7bfd46d70bf3", "scanner": "scanner-primary", "fingerprint": "93952a624ad690fa", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-f26bf0a411018da4", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 supabase/functions/pennylane-sync-quote-status/index.ts:120"}, "properties": {"repobilityId": "764d105307416045", "scanner": "scanner-primary", "fingerprint": "f26bf0a411018da4", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-081efe108aa21671", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 supabase/functions/client-change-password/index.ts:88"}, "properties": {"repobilityId": "9d585633e1d73f6a", "scanner": "scanner-primary", "fingerprint": "081efe108aa21671", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-9e3869b8242f5f90", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/solaire/pages/Simulateur.jsx:241"}, "properties": {"repobilityId": "5dd88c2b8df6e169", "scanner": "scanner-primary", "fingerprint": "9e3869b8242f5f90", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-8de50ea04d0076ac", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/voice/components/ClientSearchPanel.jsx:78"}, "properties": {"repobilityId": "6a441ce95961e0bf", "scanner": "scanner-primary", "fingerprint": "8de50ea04d0076ac", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-6462be2fe9606742", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/voice/components/ContextSelector.jsx:173"}, "properties": {"repobilityId": "664279b595d4a10a", "scanner": "scanner-primary", "fingerprint": "6462be2fe9606742", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-2b97f96d94091724", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/geogrid/BenchmarkResultTable.jsx:193"}, "properties": {"repobilityId": "a2cdad3981f98303", "scanner": "scanner-primary", "fingerprint": "2b97f96d94091724", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-153553a74db7780d", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/geogrid/ScanHistory.jsx:62"}, "properties": {"repobilityId": "b87adf6475f0c0ec", "scanner": "scanner-primary", "fingerprint": "153553a74db7780d", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-8506c87c3e86a353", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/devis/DevisProductPicker.jsx:319"}, "properties": {"repobilityId": "b7902fd23168f851", "scanner": "scanner-primary", "fingerprint": "8506c87c3e86a353", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-58adddd7e4e2c009", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/devis/DevisStepLines.jsx:52"}, "properties": {"repobilityId": "58be712099dcdae5", "scanner": "scanner-primary", "fingerprint": "58adddd7e4e2c009", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-a49700263dcea6f5", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/chantiers/LinkPennylaneQuoteModal.jsx:188"}, "properties": {"repobilityId": "370286c8dac7b032", "scanner": "scanner-primary", "fingerprint": "a49700263dcea6f5", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-cac033798b330831", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/chantiers/ChantierModal.jsx:284"}, "properties": {"repobilityId": "c80fd7572e6e3db7", "scanner": "scanner-primary", "fingerprint": "cac033798b330831", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-902db1dec08fa13f", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/chantiers/ChantierReceptionSection.jsx:320"}, "properties": {"repobilityId": "f0fcf0a2babcecd9", "scanner": "scanner-primary", "fingerprint": "902db1dec08fa13f", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-ae4260dcb4d8442b", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/chantiers/ChantierInterventionSection.jsx:122"}, "properties": {"repobilityId": "4f07eecb2bf1ade1", "scanner": "scanner-primary", "fingerprint": "ae4260dcb4d8442b", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-5f16efa948680bb8", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/chantiers/ChantierCard.jsx:96"}, "properties": {"repobilityId": "4a7cefbacdef4f52", "scanner": "scanner-primary", "fingerprint": "5f16efa948680bb8", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-2e917dad2c9e3166", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/certificat/StepIndicator.jsx:50"}, "properties": {"repobilityId": "a1a2bbc0dc169700", "scanner": "scanner-primary", "fingerprint": "2e917dad2c9e3166", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-b4973efc85bf6c53", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/shared/KanbanBoard.jsx:67"}, "properties": {"repobilityId": "9ea09327a60149f5", "scanner": "scanner-primary", "fingerprint": "b4973efc85bf6c53", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-2027a6eefda30312", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/mailing/EditorTab.jsx:262"}, "properties": {"repobilityId": "83b369425c42fe9d", "scanner": "scanner-primary", "fingerprint": "2027a6eefda30312", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-a4776fb578c9e633", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/mailing/SegmentsTab.jsx:151"}, "properties": {"repobilityId": "86798d10325b6dd5", "scanner": "scanner-primary", "fingerprint": "a4776fb578c9e633", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-8d71a0483186e251", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/entretiens/ContractCard.jsx:50"}, "properties": {"repobilityId": "4e70a747bdbb784f", "scanner": "scanner-primary", "fingerprint": "8d71a0483186e251", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-bd5e48fdac333879", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/entretiens/EntretienSAVModal.jsx:424"}, "properties": {"repobilityId": "f370cbb7d30792bd", "scanner": "scanner-primary", "fingerprint": "bd5e48fdac333879", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-ab6e90e42965357f", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/entretiens/ContractModal.jsx:56"}, "properties": {"repobilityId": "ed80429e51d5e8a2", "scanner": "scanner-primary", "fingerprint": "ab6e90e42965357f", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-4798265aa0840b9f", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/entretiens/EntretiensDashboard.jsx:36"}, "properties": {"repobilityId": "4e09dd05e3253649", "scanner": "scanner-primary", "fingerprint": "4798265aa0840b9f", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-e01e7cab60c8d933", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/entretiens/ContractStepClient.jsx:55"}, "properties": {"repobilityId": "0efbbae6ef16ac96", "scanner": "scanner-primary", "fingerprint": "e01e7cab60c8d933", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-ed8e7c506d305023", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/entretiens/EntretienSAVCard.jsx:157"}, "properties": {"repobilityId": "23dba13194de5cf1", "scanner": "scanner-primary", "fingerprint": "ed8e7c506d305023", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-8474c01f214ff57c", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/entretiens/SectorGroupView.jsx:171"}, "properties": {"repobilityId": "69cd23a501dd470f", "scanner": "scanner-primary", "fingerprint": "8474c01f214ff57c", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-8c000e41b7558a23", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/entretiens/CertificatEquipmentRow.jsx:62"}, "properties": {"repobilityId": "b2e26879f168ec62", "scanner": "scanner-primary", "fingerprint": "8c000e41b7558a23", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-5cf7a4a0b841b98d", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/entretiens/ContractStepSummary.jsx:43"}, "properties": {"repobilityId": "338c702d382b96bf", "scanner": "scanner-primary", "fingerprint": "5cf7a4a0b841b98d", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-bc5052bfc6313d73", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/clients/EquipmentList.jsx:252"}, "properties": {"repobilityId": "a86933668c0e2580", "scanner": "scanner-primary", "fingerprint": "bc5052bfc6313d73", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-c196d1e94d917726", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/clients/ClientCard.jsx:58"}, "properties": {"repobilityId": "23f00ebfb5298fcc", "scanner": "scanner-primary", "fingerprint": "c196d1e94d917726", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-1527b6faee45eb7c", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/pipeline/LeadKanban.jsx:94"}, "properties": {"repobilityId": "ccecd72dece050c5", "scanner": "scanner-primary", "fingerprint": "1527b6faee45eb7c", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-470561d3e29a8739", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/pipeline/QuoteCandidatesModal.jsx:134"}, "properties": {"repobilityId": "2c7e0a0a63cdf21d", "scanner": "scanner-primary", "fingerprint": "470561d3e29a8739", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-6207fabbe013151e", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/pipeline/LeadCard.jsx:249"}, "properties": {"repobilityId": "28228fdfa4c177e0", "scanner": "scanner-primary", "fingerprint": "6207fabbe013151e", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-e3a50156f6188f92", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/pipeline/LinkedQuotesPanel.jsx:52"}, "properties": {"repobilityId": "3216ac75eb459335", "scanner": "scanner-primary", "fingerprint": "e3a50156f6188f92", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-8cd94fd791946783", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/pipeline/LeadFormSections.jsx:75"}, "properties": {"repobilityId": "04d418665d66697b", "scanner": "scanner-primary", "fingerprint": "8cd94fd791946783", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-aeea4588b553f546", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/pipeline/FicheTechniqueModal.jsx:353"}, "properties": {"repobilityId": "7e6b37d62a8155ff", "scanner": "scanner-primary", "fingerprint": "aeea4588b553f546", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-0a2d9fcf8c9e9a5f", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/pipeline/longTerm/LongTermLeadDrawer.jsx:266"}, "properties": {"repobilityId": "bc80ba3f399bef79", "scanner": "scanner-primary", "fingerprint": "0a2d9fcf8c9e9a5f", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-85cf555b13236439", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/pipeline/longTerm/LongTermTab.jsx:91"}, "properties": {"repobilityId": "9b5b8132a20197c1", "scanner": "scanner-primary", "fingerprint": "85cf555b13236439", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-35869d416b758ee0", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/territoire/MapSearch.jsx:124"}, "properties": {"repobilityId": "47374da0712d5248", "scanner": "scanner-primary", "fingerprint": "35869d416b758ee0", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-918e42ba80e43bfb", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/territoire/MapPopup.jsx:82"}, "properties": {"repobilityId": "9ad3c9ac57a9173e", "scanner": "scanner-primary", "fingerprint": "918e42ba80e43bfb", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-794179c772f84e5c", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/planning/EventModal.jsx:816"}, "properties": {"repobilityId": "7df121ac3ccb2c9f", "scanner": "scanner-primary", "fingerprint": "794179c772f84e5c", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-8cd262d88816794e", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/planning/EventFormSections.jsx:238"}, "properties": {"repobilityId": "14f18bb4dc292e1c", "scanner": "scanner-primary", "fingerprint": "8cd262d88816794e", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-af95275b8af9389a", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/planning/scheduling/DayResourceGrid.jsx:364"}, "properties": {"repobilityId": "c13f078684e00f25", "scanner": "scanner-primary", "fingerprint": "af95275b8af9389a", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-c4e6bcb1a84375a7", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/components/meta-ads/MetaAdsCommercialFunnels.jsx:37"}, "properties": {"repobilityId": "3b17786c787b34d7", "scanner": "scanner-primary", "fingerprint": "c4e6bcb1a84375a7", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-ad0afe5f8c8b7e76", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/PipelineContrats.jsx:174"}, "properties": {"repobilityId": "d72e72b393f69f8e", "scanner": "scanner-primary", "fingerprint": "ad0afe5f8c8b7e76", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-4e9447e07b69d02d", "level": "note", "message": {"text": "\"active\" state uses light bg in a dark theme \u2014 src/apps/artisan/pages/PipelineContrats.jsx:263"}, "properties": {"repobilityId": "6ec0c0f710a6397d", "scanner": "scanner-primary", "fingerprint": "4e9447e07b69d02d", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.active-light-bg"]}}, {"ruleId": "scanner-feec312cbde14e55", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/InterventionDetail.jsx:366"}, "properties": {"repobilityId": "cf740b13159ccb84", "scanner": "scanner-primary", "fingerprint": "feec312cbde14e55", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-44c2f214d3f069f8", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/Planning.jsx:239"}, "properties": {"repobilityId": "a6541afcd638a051", "scanner": "scanner-primary", "fingerprint": "44c2f214d3f069f8", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-8e9cb2842798b55a", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/Profile.jsx:86"}, "properties": {"repobilityId": "f81d1bb29a95d506", "scanner": "scanner-primary", "fingerprint": "8e9cb2842798b55a", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-d6d789d5e85162cf", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/Dashboard.jsx:183"}, "properties": {"repobilityId": "9e3fb190d777272a", "scanner": "scanner-primary", "fingerprint": "d6d789d5e85162cf", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-e765333b7ecc609b", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/settings/SupplierManagement.jsx:910"}, "properties": {"repobilityId": "ac8eb354445f5758", "scanner": "scanner-primary", "fingerprint": "e765333b7ecc609b", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-af5e18bb2722e77d", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/settings/ProductDocumentsPanel.jsx:100"}, "properties": {"repobilityId": "f161decc2d64b9ec", "scanner": "scanner-primary", "fingerprint": "af5e18bb2722e77d", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-abc93986737e6b70", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/settings/ProductDetailDrawer.jsx:171"}, "properties": {"repobilityId": "493cf06a56378a55", "scanner": "scanner-primary", "fingerprint": "abc93986737e6b70", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-bde775f81bdbdfa6", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/settings/product-detail/ProductCompatibilitySection.jsx:229"}, "properties": {"repobilityId": "1c2024f9c6c0726d", "scanner": "scanner-primary", "fingerprint": "bde775f81bdbdfa6", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-b0cecde16a8160ca", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/settings/organization/TerritoryTab.jsx:266"}, "properties": {"repobilityId": "4b311b159f4f1895", "scanner": "scanner-primary", "fingerprint": "b0cecde16a8160ca", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-621b2c96ba4c15fd", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/client-detail/ContractPricingSection.jsx:275"}, "properties": {"repobilityId": "89578fb88c54a463", "scanner": "scanner-primary", "fingerprint": "621b2c96ba4c15fd", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-ca21997a7d6ef749", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/client-detail/TabInfo.jsx:31"}, "properties": {"repobilityId": "49789912f4f160df", "scanner": "scanner-primary", "fingerprint": "ca21997a7d6ef749", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-f11e179ac1ee6fcb", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/client-detail/TabInterventions.jsx:64"}, "properties": {"repobilityId": "aae6c5ec7cac8638", "scanner": "scanner-primary", "fingerprint": "f11e179ac1ee6fcb", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-86ef8eb809cd1b67", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/client-detail/TabMailings.jsx:311"}, "properties": {"repobilityId": "f756b76c691f5955", "scanner": "scanner-primary", "fingerprint": "86ef8eb809cd1b67", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-a35790a45e911b40", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/artisan/pages/client-detail/TabContrat.jsx:630"}, "properties": {"repobilityId": "6aeef85ec16f6a9d", "scanner": "scanner-primary", "fingerprint": "a35790a45e911b40", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-6bc965f40bfb46e7", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/prospection/_shared/components/ProspectTable.jsx:129"}, "properties": {"repobilityId": "1ed61e0b37b0c5a7", "scanner": "scanner-primary", "fingerprint": "6bc965f40bfb46e7", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-ca299e6e2af49da7", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/prospection/_shared/components/SearchSireneModal.jsx:374"}, "properties": {"repobilityId": "a375847d9db8720b", "scanner": "scanner-primary", "fingerprint": "ca299e6e2af49da7", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-e902d25d40be7aca", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/prospection/_shared/components/ProspectDrawer.jsx:197"}, "properties": {"repobilityId": "a2c38f3da0acf5b8", "scanner": "scanner-primary", "fingerprint": "e902d25d40be7aca", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-3069891bbcce6cbd", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/apps/prospection/_shared/components/NafSelector.jsx:304"}, "properties": {"repobilityId": "4c20429406f751e7", "scanner": "scanner-primary", "fingerprint": "3069891bbcce6cbd", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-87d81d62967e7370", "level": "none", "message": {"text": "TODO/FIXME marker in shipping code \u2014 src/shared/services/clients.service.js:191"}, "properties": {"repobilityId": "132d30d266712833", "scanner": "scanner-primary", "fingerprint": "87d81d62967e7370", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.todo-marker"]}}, {"ruleId": "scanner-3252e7552308185c", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/pipeline/dashboard/DashboardFilters.jsx:285"}, "properties": {"repobilityId": "e36d14ebc64f9d23", "scanner": "scanner-primary", "fingerprint": "3252e7552308185c", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-40d098e8c9dbccaa", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/layouts/AppLayout.jsx:160"}, "properties": {"repobilityId": "2fa1d666019bd689", "scanner": "scanner-primary", "fingerprint": "40d098e8c9dbccaa", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-8fd95a2c6aa07e26", "level": "warning", "message": {"text": "Insecure pattern 'cors_wildcard' in supabase/functions/invite-client/index.ts:39"}, "properties": {"repobilityId": "0c2d7a29b2dd7967", "scanner": "scanner-primary", "fingerprint": "8fd95a2c6aa07e26", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "cors_wildcard"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "supabase/functions/invite-client/index.ts"}, "region": {"startLine": 39}}}]}, {"ruleId": "scanner-66d662ea7487d42f", "level": "warning", "message": {"text": "Insecure pattern 'cors_wildcard' in supabase/functions/mailing-unsubscribe/index.ts:17"}, "properties": {"repobilityId": "a7e2b85cb9ca7066", "scanner": "scanner-primary", "fingerprint": "66d662ea7487d42f", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "cors_wildcard"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "supabase/functions/mailing-unsubscribe/index.ts"}, "region": {"startLine": 17}}}]}, {"ruleId": "scanner-d62423ed8375126a", "level": "warning", "message": {"text": "Insecure pattern 'cors_wildcard' in supabase/functions/contract-signed-notify/index.ts:35"}, "properties": {"repobilityId": "6875fc224d68ed17", "scanner": "scanner-primary", "fingerprint": "d62423ed8375126a", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "cors_wildcard"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "supabase/functions/contract-signed-notify/index.ts"}, "region": {"startLine": 35}}}]}, {"ruleId": "scanner-a47ae3598e706ad1", "level": "warning", "message": {"text": "Insecure pattern 'cors_wildcard' in supabase/functions/mailing-send/index.ts:47"}, "properties": {"repobilityId": "f9416ea0244b3cd4", "scanner": "scanner-primary", "fingerprint": "a47ae3598e706ad1", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "cors_wildcard"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "supabase/functions/mailing-send/index.ts"}, "region": {"startLine": 47}}}]}, {"ruleId": "scanner-1e55b84d286fe4a1", "level": "warning", "message": {"text": "Insecure pattern 'cors_wildcard' in supabase/functions/gsc-sync/index.ts:34"}, "properties": {"repobilityId": "89f2c1b27cc3090c", "scanner": "scanner-primary", "fingerprint": "1e55b84d286fe4a1", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "cors_wildcard"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "supabase/functions/gsc-sync/index.ts"}, "region": {"startLine": 34}}}]}, {"ruleId": "scanner-4fb30abcb30fb455", "level": "warning", "message": {"text": "Insecure pattern 'cors_wildcard' in supabase/functions/client-change-password/index.ts:21"}, "properties": {"repobilityId": "efbc0bb8093ccc43", "scanner": "scanner-primary", "fingerprint": "4fb30abcb30fb455", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "cors_wildcard"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "supabase/functions/client-change-password/index.ts"}, "region": {"startLine": 21}}}]}, {"ruleId": "scanner-c017265435a8811e", "level": "warning", "message": {"text": "Insecure pattern 'cors_wildcard' in supabase/functions/gsc-oauth-init/index.ts:100"}, "properties": {"repobilityId": "0bc99e57f88cf27e", "scanner": "scanner-primary", "fingerprint": "c017265435a8811e", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "cors_wildcard"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "supabase/functions/gsc-oauth-init/index.ts"}, "region": {"startLine": 100}}}]}, {"ruleId": "scanner-e468b89b3d21a162", "level": "error", "message": {"text": "Possible secret in src/apps/artisan/pages/settings/TeamManagement.jsx"}, "properties": {"repobilityId": "597b1a2ab4b24931", "scanner": "scanner-primary", "fingerprint": "e468b89b3d21a162", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/apps/artisan/pages/settings/TeamManagement.jsx"}, "region": {"startLine": 93}}}]}, {"ruleId": "scanner-e468b89b3d21a162", "level": "error", "message": {"text": "Possible secret in src/apps/artisan/pages/settings/TeamManagement.jsx"}, "properties": {"repobilityId": "597b1a2ab4b24931", "scanner": "scanner-primary", "fingerprint": "e468b89b3d21a162", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/apps/artisan/pages/settings/TeamManagement.jsx"}, "region": {"startLine": 95}}}]}, {"ruleId": "scanner-cb639d9a10a47b23", "level": "note", "message": {"text": "package.json defines install-time lifecycle scripts"}, "properties": {"repobilityId": "b86179956da3a4a8", "scanner": "scanner-primary", "fingerprint": "cb639d9a10a47b23", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "npm", "install-scripts"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "package.json"}, "region": {"startLine": 1}}}]}, {"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-cac0764bfb0ec588", "level": "note", "message": {"text": "Very large file: src/apps/artisan/components/pipeline/LeadModal.jsx (1344 lines)"}, "properties": {"repobilityId": "761232d9a3fd06b6", "scanner": "scanner-primary", "fingerprint": "cac0764bfb0ec588", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-b25df49100eca541", "level": "note", "message": {"text": "Very large file: src/shared/services/pennylane.service.js (1794 lines)"}, "properties": {"repobilityId": "67abc2ec462279db", "scanner": "scanner-primary", "fingerprint": "b25df49100eca541", "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": "682450a28d4238e3", "scanner": "scanner-primary", "fingerprint": "141b30a41e03817b", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["license", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-3ab5d313dda8e5f9", "level": "note", "message": {"text": "Debug logging residue appears in source files"}, "properties": {"repobilityId": "caa7456386823784", "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": "a5ab860181bff2ed", "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": "4badfe51e3e860b2", "scanner": "scanner-primary", "fingerprint": "2d0c7b7ab8f8aacf", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "mock-data", "critical-flow", "generated-repo-pattern"]}}, {"ruleId": "scanner-b9088664ace7f748", "level": "note", "message": {"text": "Composite production-readiness gap"}, "properties": {"repobilityId": "6b5058f3ec73d91f", "scanner": "scanner-primary", "fingerprint": "b9088664ace7f748", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["production-readiness", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-749d4bc1bd66df5f", "level": "warning", "message": {"text": "Agent instructions exist but release-hardening basics are missing"}, "properties": {"repobilityId": "3d20477df0f50498", "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": "e388e94d7cd2e23c", "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": "90f6aa4b84fe4be9", "scanner": "scanner-primary", "fingerprint": "8424db9c75e04ba4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["provenance", "git-history", "generated-repo-pattern"]}}, {"ruleId": "scanner-f6441b8371f8deb5", "level": "error", "message": {"text": "Agent instruction/config may expose a secret: .claude/proposed-updates.md"}, "properties": {"repobilityId": "ef94298cec9c6c94", "scanner": "scanner-primary", "fingerprint": "f6441b8371f8deb5", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["agent-instructions", "secrets", "claude_instruction"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".claude/proposed-updates.md"}, "region": {"startLine": 375}}}]}, {"ruleId": "scanner-505bc666a82f9849", "level": "error", "message": {"text": "Agent instruction/config may expose a secret: .claude/settings.local.json"}, "properties": {"repobilityId": "777970b0fce0a93b", "scanner": "scanner-primary", "fingerprint": "505bc666a82f9849", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["agent-instructions", "secrets", "claude_instruction"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".claude/settings.local.json"}, "region": {"startLine": 91}}}]}, {"ruleId": "scanner-a7b7f0e6e4683c13", "level": "none", "message": {"text": "Commented-code block (5 lines) in vite.config.js:14"}, "properties": {"repobilityId": "80f01d9d12f825d3", "scanner": "scanner-primary", "fingerprint": "a7b7f0e6e4683c13", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-09f58c9d3f8725b2", "level": "none", "message": {"text": "Commented-code block (7 lines) in supabase/functions/resend-webhook/index.ts:8"}, "properties": {"repobilityId": "9fdbc4c573cfbcc5", "scanner": "scanner-primary", "fingerprint": "09f58c9d3f8725b2", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-556930ac5d1b97c8", "level": "none", "message": {"text": "Commented-code block (5 lines) in supabase/functions/mailing-scheduler/index.ts:122"}, "properties": {"repobilityId": "99049115c6d4e075", "scanner": "scanner-primary", "fingerprint": "556930ac5d1b97c8", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-9e14d68d95e8478a", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 supabase/functions/mailing-scheduler/index.ts:97"}, "properties": {"repobilityId": "e93d592a567b2293", "scanner": "scanner-primary", "fingerprint": "9e14d68d95e8478a", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-3cf20e49db78fdb7", "level": "none", "message": {"text": "Commented-code block (6 lines) in supabase/functions/voice-extract-fieldreport/index.ts:1"}, "properties": {"repobilityId": "4d70aaba6cd84145", "scanner": "scanner-primary", "fingerprint": "3cf20e49db78fdb7", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-050f16b9e7392f0e", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 supabase/functions/voice-extract-fieldreport/index.ts:271"}, "properties": {"repobilityId": "b4b2e4561de39ed2", "scanner": "scanner-primary", "fingerprint": "050f16b9e7392f0e", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-8d915f369c3ec34a", "level": "none", "message": {"text": "Commented-code block (9 lines) in supabase/functions/pennylane-proxy/index.ts:13"}, "properties": {"repobilityId": "573223cdf8090ee5", "scanner": "scanner-primary", "fingerprint": "8d915f369c3ec34a", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-ba39e04c32974739", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 supabase/functions/pennylane-proxy/index.ts:87"}, "properties": {"repobilityId": "6360bef988b1ac60", "scanner": "scanner-primary", "fingerprint": "ba39e04c32974739", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-24ed41fb1bbcaf3a", "level": "none", "message": {"text": "Commented-code block (5 lines) in supabase/functions/pennylane-sync-cron/index.ts:12"}, "properties": {"repobilityId": "3c90206f5038e323", "scanner": "scanner-primary", "fingerprint": "24ed41fb1bbcaf3a", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-2116e9a0d6ab95cd", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 supabase/functions/pennylane-sync-cron/index.ts:46"}, "properties": {"repobilityId": "396937f49c74202c", "scanner": "scanner-primary", "fingerprint": "2116e9a0d6ab95cd", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-2518d3bb4e320b50", "level": "none", "message": {"text": "Commented-code block (7 lines) in supabase/functions/mailing-unsubscribe/index.ts:1"}, "properties": {"repobilityId": "95f1a35523c740be", "scanner": "scanner-primary", "fingerprint": "2518d3bb4e320b50", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-40d8ebd43afba2a8", "level": "none", "message": {"text": "Commented-code block (6 lines) in supabase/functions/resend-domain-onboard/index.ts:17"}, "properties": {"repobilityId": "5d564c4495f86a38", "scanner": "scanner-primary", "fingerprint": "40d8ebd43afba2a8", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-a2380d662366be98", "level": "none", "message": {"text": "Commented-code block (10 lines) in supabase/functions/contract-signed-notify/index.ts:10"}, "properties": {"repobilityId": "75d88500e81ec23c", "scanner": "scanner-primary", "fingerprint": "a2380d662366be98", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-657ea66ce2092106", "level": "none", "message": {"text": "Commented-code block (19 lines) in supabase/functions/mailing-send/index.ts:1"}, "properties": {"repobilityId": "9a029cc4c66c3fae", "scanner": "scanner-primary", "fingerprint": "657ea66ce2092106", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-6f736764bbbdd039", "level": "none", "message": {"text": "Commented-code block (5 lines) in supabase/functions/gsc-sync/index.ts:9"}, "properties": {"repobilityId": "317670468641dba9", "scanner": "scanner-primary", "fingerprint": "6f736764bbbdd039", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-313b6b08b0a283b3", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 supabase/functions/gsc-sync/index.ts:134"}, "properties": {"repobilityId": "a194679c39b0fcc6", "scanner": "scanner-primary", "fingerprint": "313b6b08b0a283b3", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-bf7be311a8551f81", "level": "none", "message": {"text": "Commented-code block (6 lines) in supabase/functions/pennylane-sync-quote-status/index.ts:421"}, "properties": {"repobilityId": "f45278dfe365f861", "scanner": "scanner-primary", "fingerprint": "bf7be311a8551f81", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-6529061260bdc899", "level": "none", "message": {"text": "Commented-code block (5 lines) in supabase/functions/pennylane-backfill-quotes/index.ts:14"}, "properties": {"repobilityId": "d5d8a346410d44a7", "scanner": "scanner-primary", "fingerprint": "6529061260bdc899", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-fe97303cc33f1933", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 supabase/functions/pennylane-backfill-quotes/index.ts:43"}, "properties": {"repobilityId": "eaa740b284da6b30", "scanner": "scanner-primary", "fingerprint": "fe97303cc33f1933", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-2b71cafaab9790f4", "level": "none", "message": {"text": "Commented-code block (10 lines) in supabase/functions/gsc-oauth-callback/index.ts:13"}, "properties": {"repobilityId": "87f511dae82aecfb", "scanner": "scanner-primary", "fingerprint": "2b71cafaab9790f4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-e9bd9c69bdbcfe6d", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 supabase/functions/gsc-oauth-callback/index.ts:211"}, "properties": {"repobilityId": "9d2334c863034c36", "scanner": "scanner-primary", "fingerprint": "e9bd9c69bdbcfe6d", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-3f1a5a594a3c66ca", "level": "none", "message": {"text": "Commented-code block (5 lines) in supabase/functions/gsc-oauth-init/index.ts:9"}, "properties": {"repobilityId": "0a8ff254105f5860", "scanner": "scanner-primary", "fingerprint": "3f1a5a594a3c66ca", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-d2ee0896f462f2c4", "level": "none", "message": {"text": "Commented-code block (5 lines) in supabase/functions/_shared/auth.ts:9"}, "properties": {"repobilityId": "1bc9b20a738f63e9", "scanner": "scanner-primary", "fingerprint": "d2ee0896f462f2c4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-fe495e8db9b07ece", "level": "none", "message": {"text": "Commented-code block (6 lines) in src/apps/solaire/components/MonthlyChart.jsx:1"}, "properties": {"repobilityId": "7f29c88cc94ea268", "scanner": "scanner-primary", "fingerprint": "fe495e8db9b07ece", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-4125cf40130be680", "level": "none", "message": {"text": "Commented-code block (7 lines) in src/apps/solaire/components/FinancingModule.jsx:1"}, "properties": {"repobilityId": "240cfb5533bddaad", "scanner": "scanner-primary", "fingerprint": "4125cf40130be680", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-9a27490e88f5ba23", "level": "none", "message": {"text": "Commented-code block (5 lines) in src/apps/solaire/lib/etudeModel.js:1"}, "properties": {"repobilityId": "60ceb26270fa8666", "scanner": "scanner-primary", "fingerprint": "9a27490e88f5ba23", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-72daaf68e5f323fa", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/apps/solaire/lib/etudeExport.js:33"}, "properties": {"repobilityId": "d05916a40419c02c", "scanner": "scanner-primary", "fingerprint": "72daaf68e5f323fa", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-ff5d6f46043e41c5", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/apps/voice/services/voiceMemos.service.js:99"}, "properties": {"repobilityId": "133dcc6c4b886025", "scanner": "scanner-primary", "fingerprint": "ff5d6f46043e41c5", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-f2a5b7088316eb63", "level": "none", "message": {"text": "Commented-code block (16 lines) in src/apps/artisan/routes.jsx:118"}, "properties": {"repobilityId": "15a4e94f1c178a37", "scanner": "scanner-primary", "fingerprint": "f2a5b7088316eb63", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-2da224ea03cf8393", "level": "note", "message": {"text": "Legacy-named symbol `appointment_legacy` in src/apps/artisan/components/mailing/segmentBuilder.constants.js:37"}, "properties": {"repobilityId": "9828b9c0b03d2932", "scanner": "scanner-primary", "fingerprint": "2da224ea03cf8393", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-f378af87a1ab61b9", "level": "none", "message": {"text": "Commented-code block (6 lines) in src/apps/artisan/components/mailing/SendTab.jsx:163"}, "properties": {"repobilityId": "b0766b2931bd9803", "scanner": "scanner-primary", "fingerprint": "f378af87a1ab61b9", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-3b44db8d53e50e02", "level": "none", "message": {"text": "Commented-code block (5 lines) in src/apps/artisan/components/mailing/EditorTab.jsx:10"}, "properties": {"repobilityId": "14a76f299d9d396a", "scanner": "scanner-primary", "fingerprint": "3b44db8d53e50e02", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-d808605d57cc4bff", "level": "none", "message": {"text": "Commented-code block (5 lines) in src/apps/artisan/components/pipeline/LeadKanban.jsx:459"}, "properties": {"repobilityId": "2e99095106e2b413", "scanner": "scanner-primary", "fingerprint": "d808605d57cc4bff", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-bae36482172510e0", "level": "note", "message": {"text": "Legacy-named symbol `appointment_legacy` in src/apps/artisan/components/pipeline/LeadModal.jsx:865"}, "properties": {"repobilityId": "21aff19c4778e8bc", "scanner": "scanner-primary", "fingerprint": "bae36482172510e0", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-6d90350aaf79ccb3", "level": "none", "message": {"text": "Commented-code block (6 lines) in src/apps/artisan/components/pipeline/LeadCard.jsx:151"}, "properties": {"repobilityId": "6dc55876303ba0be", "scanner": "scanner-primary", "fingerprint": "6d90350aaf79ccb3", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-64c03b2295a20cc2", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/apps/artisan/components/territoire/useMapZones.js:36"}, "properties": {"repobilityId": "eb94f1a76000ef0e", "scanner": "scanner-primary", "fingerprint": "64c03b2295a20cc2", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-8e9fbb67b0f4aa5a", "level": "none", "message": {"text": "Commented-code block (7 lines) in src/apps/artisan/components/planning/EventModal.jsx:135"}, "properties": {"repobilityId": "49087e5e6a3e6f04", "scanner": "scanner-primary", "fingerprint": "8e9fbb67b0f4aa5a", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-5d036ac15cdc75a2", "level": "none", "message": {"text": "Commented-code block (5 lines) in src/apps/artisan/components/planning/scheduling/DayResourceGrid.jsx:130"}, "properties": {"repobilityId": "688ec4a177e5553e", "scanner": "scanner-primary", "fingerprint": "5d036ac15cdc75a2", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-8a4845af42917de2", "level": "none", "message": {"text": "Commented-code block (9 lines) in src/apps/artisan/components/planning/scheduling/SchedulingAssistant.jsx:101"}, "properties": {"repobilityId": "f87440ef6031b49e", "scanner": "scanner-primary", "fingerprint": "8a4845af42917de2", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-3c35222046ea2675", "level": "none", "message": {"text": "Commented-code block (5 lines) in src/apps/artisan/pages/ContractSign.jsx:149"}, "properties": {"repobilityId": "ae9bef1483fc0f41", "scanner": "scanner-primary", "fingerprint": "3c35222046ea2675", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-33da055c0be78c3c", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/apps/artisan/pages/ContractSign.jsx:107"}, "properties": {"repobilityId": "b84c26d3243bac26", "scanner": "scanner-primary", "fingerprint": "33da055c0be78c3c", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-957397e4e4e198e5", "level": "none", "message": {"text": "Commented-code block (5 lines) in src/apps/artisan/pages/settings/SolaireSettings.jsx:1"}, "properties": {"repobilityId": "16c0badc76496f29", "scanner": "scanner-primary", "fingerprint": "957397e4e4e198e5", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-4431519c6f083f3b", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/apps/artisan/pages/settings/organization/TerritoryTab.jsx:133"}, "properties": {"repobilityId": "06f0504c229ad197", "scanner": "scanner-primary", "fingerprint": "4431519c6f083f3b", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-c2999c7fd77ea108", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/apps/artisan/pages/settings/organization/components/AddressSearch.jsx:45"}, "properties": {"repobilityId": "984f78baef53e26c", "scanner": "scanner-primary", "fingerprint": "c2999c7fd77ea108", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-ab4276a513e5f94e", "level": "none", "message": {"text": "Commented-code block (5 lines) in src/apps/artisan/pages/client-detail/ContractPdfSection.jsx:103"}, "properties": {"repobilityId": "2182a1ce7aca5c69", "scanner": "scanner-primary", "fingerprint": "ab4276a513e5f94e", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-dad53262e7c81563", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/apps/prospection/_shared/components/SearchSireneModal.jsx:93"}, "properties": {"repobilityId": "5e193ef02bdf61d6", "scanner": "scanner-primary", "fingerprint": "dad53262e7c81563", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-a809f47acb018519", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/apps/prospection/_shared/lib/sireneApi.js:83"}, "properties": {"repobilityId": "b1b6d407bd8a9eeb", "scanner": "scanner-primary", "fingerprint": "a809f47acb018519", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-e3f1d2883d39ba37", "level": "none", "message": {"text": "Commented-code block (5 lines) in src/shared/hooks/usePennylane.js:551"}, "properties": {"repobilityId": "28a97afa705e2ec3", "scanner": "scanner-primary", "fingerprint": "e3f1d2883d39ba37", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-3923e5d9c1c5d308", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/shared/services/geocoding.service.js:47"}, "properties": {"repobilityId": "ab7ccf6295787869", "scanner": "scanner-primary", "fingerprint": "3923e5d9c1c5d308", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-954444a09209b978", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/shared/services/gsc.service.js:23"}, "properties": {"repobilityId": "45df082235e2e3a0", "scanner": "scanner-primary", "fingerprint": "954444a09209b978", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-8c1c61479b3801d2", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/shared/services/googleCalendar.service.js:38"}, "properties": {"repobilityId": "7ced89a17fc1fc20", "scanner": "scanner-primary", "fingerprint": "8c1c61479b3801d2", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-ec457bafe3a8a750", "level": "note", "message": {"text": "Legacy-named symbol `appointment_legacy` in src/shared/services/clients.service.js:77"}, "properties": {"repobilityId": "61564ff8a966176b", "scanner": "scanner-primary", "fingerprint": "ec457bafe3a8a750", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-da1eb55205f409d5", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/shared/services/interventions.service.js:512"}, "properties": {"repobilityId": "50ee7156d206319e", "scanner": "scanner-primary", "fingerprint": "da1eb55205f409d5", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-d9199e10c677d535", "level": "none", "message": {"text": "Commented-code block (5 lines) in src/shared/services/appointments.service.js:725"}, "properties": {"repobilityId": "d231c1e80315120f", "scanner": "scanner-primary", "fingerprint": "d9199e10c677d535", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-7541c45a43d4af00", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/shared/services/geogrid.service.js:24"}, "properties": {"repobilityId": "04c1e53177fbd3ff", "scanner": "scanner-primary", "fingerprint": "7541c45a43d4af00", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-ad370f51c64a3a38", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/shared/services/entretiens.service.js:812"}, "properties": {"repobilityId": "3d4e61119b91bb12", "scanner": "scanner-primary", "fingerprint": "ad370f51c64a3a38", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-bd33ecd534deda48", "level": "none", "message": {"text": "Commented-code block (9 lines) in src/shared/services/pricing.service.js:419"}, "properties": {"repobilityId": "2e9cc8dc8cd1fda9", "scanner": "scanner-primary", "fingerprint": "bd33ecd534deda48", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-b92913ff24f1f084", "level": "none", "message": {"text": "Commented-code block (7 lines) in src/shared/services/pennylane.service.js:28"}, "properties": {"repobilityId": "b92e5f22c1c65baf", "scanner": "scanner-primary", "fingerprint": "b92913ff24f1f084", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-8045390122552719", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 src/shared/services/pennylane.service.js:1131"}, "properties": {"repobilityId": "deef169342112d41", "scanner": "scanner-primary", "fingerprint": "8045390122552719", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-270d662a1bc2d293", "level": "none", "message": {"text": "Commented-code block (7 lines) in src/components/ProtectedRoute.jsx:72"}, "properties": {"repobilityId": "21e81d48eeb77dc5", "scanner": "scanner-primary", "fingerprint": "270d662a1bc2d293", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-53f2c35312623d86", "level": "none", "message": {"text": "Commented-code block (9 lines) in src/lib/permissionsRegistry.js:1"}, "properties": {"repobilityId": "0dc9d8338c5f4213", "scanner": "scanner-primary", "fingerprint": "53f2c35312623d86", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-cc0f9d8e41b33b0e", "level": "note", "message": {"text": "11 env vars used in code but missing from .env.example"}, "properties": {"repobilityId": "c82cd8cd626c3599", "scanner": "scanner-primary", "fingerprint": "cc0f9d8e41b33b0e", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "config-drift"]}}, {"ruleId": "scanner-5d3fdd84b07773f0", "level": "warning", "message": {"text": "Frontend route `/reset-password` has no Link/navigate to it \u2014 src/App.jsx"}, "properties": {"repobilityId": "948b633d8b4e5ac3", "scanner": "scanner-primary", "fingerprint": "5d3fdd84b07773f0", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-5a8b49b88cc3081d", "level": "warning", "message": {"text": "Frontend route `/auth/callback` has no Link/navigate to it \u2014 src/App.jsx"}, "properties": {"repobilityId": "53ab22a71eac19bd", "scanner": "scanner-primary", "fingerprint": "5a8b49b88cc3081d", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-21bbfe3ea5a9139e", "level": "warning", "message": {"text": "Frontend route `/voice` has no Link/navigate to it \u2014 src/App.jsx"}, "properties": {"repobilityId": "46373097d0fe0007", "scanner": "scanner-primary", "fingerprint": "21bbfe3ea5a9139e", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}]}]}