feat(workflow_audit): WF022 unanchored_heading_regex (#360)#410
Merged
Conversation
Detect a markdown-heading-detection regex used unanchored inside inline Python in a workflow run: block (e.g. re.search(r'TypeScript [Ee]xemptions', line) with no ^# anchor). Such a regex also matches prose mentions of the phrase, so the parser silently walks the wrong section — the multi-week silent governance-gate failure on affinescript (standards#183 anchored it). HIGH severity. Heuristic: gated on python3 presence, a Title-Case heading shape, and absence of ^# anchoring; single-word matches and anchored patterns are ignored. Threaded into audit/3. - check_unanchored_heading_regex/1 + audit/3 wiring (call, findings, count) - test/workflow_audit_test.exs: positive + anchored/non-heading/no-python - CHANGELOG md + adoc Verified locally (Elixir 1.14): isolated compile (no new warnings), real compiled module passes the detection fixtures, and ZERO findings on hypatia's own workflows (no inline-python re.search in any workflow). Closes #360 https://claude.ai/code/session_01J8oLNn6MjKDRRUF65e2jLf
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Implements #360 (hypatia#333 cohort, pattern 1) —
WorkflowAuditrule WF022unanchored_heading_regex: flags a markdown-heading-detection regex used unanchored inside inline Python in a workflowrun:block, e.g.re.search(r'TypeScript [Ee]xemptions', line)with no^#anchor.Such a regex also matches prose mentions of the phrase, so the parser silently walks the wrong section. This was the multi-week silent failure of affinescript's
governance / Language / package anti-pattern policygate (standards#183anchored it). HIGH severity — estate-wide and invisible in logs.How
check_unanchored_heading_regex/1(after WF021) threaded intoaudit/3(call, findings concat, count field).%{rule: "WF022", type: :unanchored_heading_regex, file:, severity: :high, pattern:, reason:, fix_recipe: :anchor_heading_regex}.python3presence; the regex literal must have a Title-Case heading shape ([A-Z][a-z]+followed by another Title-Case word or a[Xx]-style char class) and not start with^#. Single-word matches (Error: (.+)) and already-anchored patterns are ignored.test/workflow_audit_test.exs— positive + 3 negatives (anchored, non-heading, no-python).Dogfood-safe
WF022 auto-runs in the hypatia self-scan via
audit/3. hypatia has no inline-pythonre.search/re.matchin any workflow, so it produces zero self-findings (confirmed on the real compiled module).Verified at source (local Elixir 1.14)
elixirc→ no new warningsaudit/3findings-concat last line, which gains++ heading_regex_issueswrapped to a new continuation. All other pre-existing lines are byte-identical to main (I avoided whole-file formatting because Elixir 1.14's formatter diverges from CI's 1.17 on++-chain packing and longvar = func()lines; the one concat edit follows 1.17's greedy-fill style as seen on main).Closes #360
Generated by Claude Code