Session Overview

Autonomous daily run of the internal-link-opportunity scheduled task for Sam Aguiar Injury Lawyers (aguiarinjurylawyers.com, WordPress on Cloudways). Goal: add contextually-correct internal links from unlinked pillar-topic mentions in live published content, repair broken internal links, avoid overlap with the prior few days, and ship a structural improvement to the matcher. Last prior run was 2026-06-01 (no runs 06-02 or 06-03), so saturation had a 3-day gap to recover.

What Was Accomplished

Inserts by pillar: underinsured-motorist 9, tbi-cases 5, drunk-driving 3, distracted-driving 3, hit-and-run 2, spinal-cord 2, premises-liability 1, dram-shop 1, uber-accident 1, wrongful-death 1, uninsured-motorist 1, personal-injury 1. underinsured-motorist is now the dominant anchor (location pages mention it in prose but rarely hand-link it).

Key Improvement Shipped: Prose ALLOW-LIST

The standing fix direction recommended to Sam on 2026-06-01 is now implemented. Background: two runs in a row (05-31 results-widget labels, 06-01 form-dropdown labels) the matcher linked non-prose UI text because the old logic was a deny-list (SKIP_RE): link unless explicitly skipped. Each new non-prose template surface required a new deny rule and was only caught by post-run QA.

Fix in scan.py: find_unlinked_match now calls a new nearest_block_tag(content, pos) and only inserts when the match's nearest enclosing BLOCK element is in PROSE_TAGS = {p, li, td, summary, blockquote, dd}. Inline formatting tags (strong/em/span/a/label, set _INLINE_TAGS) are transparent, so an anchor inside a strong tag within a paragraph still qualifies. SKIP_RE kept as a cheap first filter (now belt-and-suspenders). The allow-list self-defends against future non-prose surfaces (tabs, accordions, nav) with no new deny rule. Unit-tested 10 cases pre-run (prose accept; option/select/widget-div/bare-div/h2 reject), all passed. First production run: 30/30 prose, 0 reverts.

Decisions Made

Files and Locations