Skip to content

fix(#980): route 16 more checkers in check_release_tree.py through the shared heredoc tracker - #988

Merged
fdaviddpt merged 2 commits into
mainfrom
fix/980
Oct 8, 2026
Merged

fdaviddpt merged 2 commits into
mainfrom
fix/980

Conversation

@fdaviddpt

Copy link
Copy Markdown
Contributor

Adjacent finding from #919's lane self-review (PR #978): #919 fixed one checker (_check_url_in_comment) that misread heredoc-body #-led lines as comments, but left every other checker in .github/scripts/check_release_tree.py using the same unguarded line.lstrip().startswith("#") pattern. The issue claimed "11 other checker functions" share it, explicitly reasoned rather than verified per site.

Recon (re-derived by grep rather than trusting the issue's count) found 17 raw call sites across 16 distinct functions (excluding the already-fixed one), one of which actually belongs to the shared _sh_lines helper feeding 8 further checkers -- so fixing _sh_lines once covers those 8. Net: 16 functions directly touched here, covering 24 effective call sites (16 direct + 8 via _sh_lines), out of 18 raw textual sites of the pattern in the file.

What changed

  • Added _iter_non_heredoc_lines(text, track_heredocs), mirroring the heredoc tracker _check_url_in_comment already carried, and routed 16 checkers through it (including a self-referential fix: _check_typed_heredoc itself didn't track heredoc bodies, so a body line shaped like a second <<WORD opener was misread as an independent one).
  • 2 of the 18 raw sites (_check_catch_all_in_loop, _check_single_line_delegate_positional) are deliberately left unfixed, each with an in-code docstring explaining why (one has its own multi-line state machine that would need interleaving rather than wrapping; the other filters an already-extracted string rather than the raw file).
  • tests/test_heredoc_comment_guard_980.py: 8 tests -- one must-not-fire-inside-heredoc case per class, each paired with a positive control proving the pattern still fires outside a heredoc, plus a regression test pinning that an unclosed heredoc still fails the release gate via the unchanged _check_url_in_comment.

Tests: red first (4 failed, 3 passed, the passes being positive controls), green after the fix (7 passed, then 8 passed after the follow-up regression test). Targeted/adjacent suite (-k "release_branch_check or release_branch_preflight or single_line_delegate or eval_of_substitution or strip_shell_comments or scanner_shapes_source or heredoc_comment_guard or url_host") ran clean before and after: 804 then 805 passed (new test added), 1 pre-existing unrelated skip, no regressions. Full test_command was not run locally, per this repo's own doctrine that CI (13 legs, 3 OSes, 4 interpreters) is the gate.

Self-review (Explore + oss:auditor, per agents/developer/review.md) found 2 issues on the first commit, both closed in a follow-up commit here:

  1. An unclosed heredoc leaves the new shared helper with no diagnostic of its own, unlike _check_url_in_comment's hand-rolled copy of the same tracker. Argued down from "the release gate goes silent" to mitigated-not-masked: check_tree always runs the unchanged _check_url_in_comment on every file with the identical scope, so a genuinely unclosed heredoc still fails in the same run -- now pinned by a regression test.
  2. The two deliberately-deferred functions had no documentation explaining the deferral -- fixed by adding an in-code docstring note to each.

Two supplementary observations from oss:auditor do not block this PR and are recorded here rather than fixed: _check_url_in_comment itself was not migrated onto the new shared helper and still carries its own duplicate inline copy of the identical state machine, so a future fix to one could silently drift from the other with nothing to catch it; and 8 of the 16 routed call sites got the identical code-shape change with no heredoc-specific test case of their own, reasoned-correct by the same logic as the tested siblings but not directly observed by a test.

Docs: README.md never mentions this internal validator script (grep -c returned 0) -- no change needed.

Closes #980.

[AI-generated]

fdaviddpt and others added 2 commits October 8, 2026 07:47
…py through a shared heredoc tracker

Adjacent finding from #919's lane self-review (PR #978): #978 fixed one
checker (_check_url_in_comment) that decided "is this a comment" with the
bare `.lstrip().startswith("#")` test, with no heredoc-boundary tracking, so
a heredoc body line could be misread as a comment. 16 other functions in
the same file shared the exact same unguarded pattern (18 raw call sites,
the two extra folding into `_check_dot_string` and `_sh_lines`).

Added `_iter_non_heredoc_lines`, generalizing the tracker
`_check_url_in_comment` already carries, and routed all 16 checkers through
it -- 8 of them share the existing `_sh_lines` helper, fixed once for all 8.
`_check_typed_heredoc` itself was a self-referential case: without tracking
the heredoc bodies it finds, a body line containing a second
"<<WORD"-shaped substring was misread as an independent second opener.

Added tests/test_heredoc_comment_guard_980.py: one must-not-fire case per
class of fix (shared _sh_lines helper, the self-referential heredoc
detector, check_tree's own unscoped eval/download REVIEW loop, and the
_SCRIPT_DIRS-scoped-not-.sh-restricted checkers), each paired with a
positive control proving the same pattern still fires outside a heredoc.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
… deferred functions

Self-review (Explore reviewer) on the preceding #980 commit found two real
gaps:

1. `_iter_non_heredoc_lines` has no "the heredoc opened here was never
   closed" diagnostic of its own, unlike `_check_url_in_comment`'s own
   hand-rolled copy of this same tracking loop. An unclosed/malformed
   `<<DELIM` silently blinds all 16 routed checkers to the rest of the
   file. Verified this is mitigated, not masked: `check_tree` always runs
   the unchanged `_check_url_in_comment` on every file too, with the exact
   same `track_heredocs` scope, so a genuinely unclosed heredoc in a
   reachable file still trips that function's own FAIL in the same run.
   Documented this coupling in the helper's docstring and added a
   regression test pinning the guarantee, rather than threading an extra
   parameter through 24 call sites to duplicate the diagnostic everywhere.

2. The two functions sharing the same unguarded comment pattern that were
   left out of the #980 fix (`_check_catch_all_in_loop`,
   `_check_single_line_delegate_positional`) had neither a fix nor
   in-code documentation of why -- #980 as scoped asked for one or the
   other for every checker sharing the pattern. Added a docstring note to
   each explaining why it needs a different approach (its own multi-line
   state machine; filtering an already-extracted function-body string
   rather than the raw file) and that it is deferred to a follow-up, not
   silently dropped.

Updated changelog.d/980.fixed.md to describe both outcomes accurately
(16 of 18 routed, not "every one"; the unclosed-heredoc mitigation).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
fdaviddpt added a commit that referenced this pull request Oct 8, 2026
@fdaviddpt
fdaviddpt merged commit a54cd80 into main Oct 8, 2026
19 checks passed
@fdaviddpt
fdaviddpt deleted the fix/980 branch October 8, 2026 06:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

check_release_tree.py: 11 more checker functions share the unguarded comment-detection pattern #919 fixed once

1 participant