Skip to content

feat(workflow_audit): WF022 unanchored_heading_regex (#360)#410

Merged
hyperpolymath merged 1 commit into
mainfrom
claude/gracious-mendel-WIXFG
May 31, 2026
Merged

feat(workflow_audit): WF022 unanchored_heading_regex (#360)#410
hyperpolymath merged 1 commit into
mainfrom
claude/gracious-mendel-WIXFG

Conversation

@hyperpolymath
Copy link
Copy Markdown
Owner

What

Implements #360 (hypatia#333 cohort, pattern 1) — WorkflowAudit rule WF022 unanchored_heading_regex: flags 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. This was the multi-week silent failure of affinescript's governance / Language / package anti-pattern policy gate (standards#183 anchored it). HIGH severity — estate-wide and invisible in logs.

How

  • check_unanchored_heading_regex/1 (after WF021) threaded into audit/3 (call, findings concat, count field).
  • Finding %{rule: "WF022", type: :unanchored_heading_regex, file:, severity: :high, pattern:, reason:, fix_recipe: :anchor_heading_regex}.
  • Heuristic (conservative): gated on python3 presence; 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).
  • CHANGELOG md + adoc.

Dogfood-safe

WF022 auto-runs in the hypatia self-scan via audit/3. hypatia has no inline-python re.search/re.match in any workflow, so it produces zero self-findings (confirmed on the real compiled module).

Verified at source (local Elixir 1.14)

  • isolated elixirc → no new warnings
  • real compiled module → detection fixtures pass; 0 findings on hypatia's workflows
  • diff is a pure addition apart from one line: the audit/3 findings-concat last line, which gains ++ heading_regex_issues wrapped 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 long var = func() lines; the one concat edit follows 1.17's greedy-fill style as seen on main).

Closes #360


Generated by Claude Code

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
@hyperpolymath hyperpolymath marked this pull request as ready for review May 31, 2026 05:33
@hyperpolymath hyperpolymath merged commit b1782ca into main May 31, 2026
1 of 27 checks passed
@hyperpolymath hyperpolymath deleted the claude/gracious-mendel-WIXFG branch May 31, 2026 05:33
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.

hypatia: detect brittle regex matching of doc headings in inline-python workflow scripts (from #333 cohort, pattern 1)

2 participants