fix(render): close-side </div> tolerance + consolidate dj-root scanners (#1751)#1754
Conversation
…root scanners (#1751) Completes the #1749/#1750 dj-root-boundary fix class. - `_find_closing_div_pos` (the shared scanner, 6 call sites) hardcoded the close tag as `</div>`, missing `</div >` / `</div\n>`. That is the close-side twin of #1749's open-side under-count: a whitespace close over-counts depth so the close is never found. Now matches `</div\s*>` (`close_match.end()` consumes the full tag, so splice points stay correct). - Replaced `render_full_template`'s separate hand-rolled depth loop (its open side was patched in #1750) with a call to `_find_closing_div_pos`. The helper is multi-line-safe on the open side (`<div\b`) and now whitespace-tolerant on the close side; the rendered shell has no `{% %}` tags so the helper's if/else handling is inert. Removing the duplicate scanner closes the parallel-path-drift (#1646) that let the open-side bug exist in one copy only. Adds close-side gate-off test (reverting `</div\s*>`→`</div>` makes the whitespace test fail); existing multi-line + render-path suites stay green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Stage-7 Adversarial Review — PR #1754 (fix #1751)Verdict: APPROVE ✅ Close-side Mandatory gates
Empirical verification
Consolidation behavioral-equivalence determination
Minor
SummaryThe fix is correct, the consolidation is behaviorally equivalent on the inputs |
Retrospective — PR #1754 (#1751)Task: close-side Quality: 5/5Closed the bug class (not just an instance): both the close-side twin and the duplicate scanner that enabled the original drift. What went well
What could be improved / noted (non-blocking)
Verified
|
…1752) (#1755) nav-hooks-guard and playwright-tests duplicated ~9 setup steps (Python/uv/cache/ uv sync/maturin build/playwright install/migrate/start server/wait). #1753 had to patch the missing maturin step into nav-hooks-guard precisely because the copy had drifted. Extract the shared harness into .github/actions/djust-playwright-server (composite); both jobs now `uses:` it after checkout, then run their own test step + log upload + server stop. One definition can't drift a step out of one job (parallel-path-drift, #1646). Both jobs keep their identity: playwright-tests stays continue-on-error (optional), nav-hooks-guard stays blocking; test-summary wiring unchanged. Closes #1752. Item 1 (maturin) shipped in #1753; item 2 (blocking-soak) resolved by decision — keep nav-hooks-guard blocking (green across #1748/#1753/#1754); item 3 (this dedup). Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Closes #1751. Completes the #1749/#1750
dj-root-boundary fix class.Problem
Two issues in the
dj-rootregion boundary scan:_find_closing_div_pos(the shared scanner, 6 call sites) located the close asre.search("</div>")— missing</div >/</div\n>. That's the close-side twin of fix: render_full_template ejects page content outside dj-root for multi-line <div> tags (leaks across dj-navigate) #1749's open-side under-count: a whitespace close over-counts depth so the close is never found → caller falls back / mis-splices.render_full_templatehad its own hand-rolled depth loop (its open side was patched in fix(render): count multi-line <div> opening tags in dj-root boundary scan (#1749) #1750) separate from_find_closing_div_pos. Parallel-path drift (fix(auth): wrap per-event check_object_permission in sync_to_async (#1638) #1646) is exactly what let the open-side bug exist in one copy and not the other.Fix
_find_closing_div_pos:</div>→</div\s*>(benefits all 6 call sites;close_match.end()consumes the full tag so splice points stay correct).render_full_template's hand-rolled loop with a_find_closing_div_poscall. The helper is multi-line-safe on the open side (<div\b, subsumes fix(render): count multi-line <div> opening tags in dj-root boundary scan (#1749) #1750) and now whitespace-tolerant on close; the rendered shell carries no{% %}tags so the helper's if/else handling is inert there. One scanner now, not two.Verification
_find_closing_div_poswith gate-off: reverting</div\s*>→</div>makes the whitespace test fail (scanner returns(None, None)); control (plain</div>) stays green._find_closing_div_posand stays green (consolidation preserves behavior).🤖 Generated with Claude Code