<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xml:lang="en-US">
  <id>tag:github.com,2008:https://github.com/patchrail/patchrail/releases</id>
  <link type="text/html" rel="alternate" href="https://github.com/patchrail/patchrail/releases"/>
  <link type="application/atom+xml" rel="self" href="https://github.com/patchrail/patchrail/releases.atom"/>
  <title>Release notes from patchrail</title>
  <updated>2026-07-22T19:28:28Z</updated>
  <entry>
    <id>tag:github.com,2008:Repository/1257620736/v0.7.6</id>
    <updated>2026-07-22T19:28:57Z</updated>
    <link rel="alternate" type="text/html" href="https://github.com/patchrail/patchrail/releases/tag/v0.7.6"/>
    <title>v0.7.6</title>
    <content type="html">&lt;p&gt;When PatchRail cannot name the cause, it now shows you where the log ends.&lt;/p&gt;
&lt;p&gt;1,164 lines of apache/kafka run 29805964231 used to go in and this came out: &lt;code&gt;unknown&lt;/code&gt;, &lt;code&gt;0.15&lt;/code&gt;, &quot;No high-confidence local signal found.&quot; — not one line of the log. The cause was sitting one line above the runner&#39;s boilerplate exit-code annotation (&lt;code&gt;Could not find the PR that triggered this workflow request&lt;/code&gt;), three seconds of scrolling away. Declining to guess is the right call; answering with nothing is not.&lt;/p&gt;
&lt;h3&gt;Added&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;An &lt;code&gt;unknown&lt;/code&gt; verdict now hands back the last lines of the log that carried output, under a heading that says exactly what they are: raw log, not a diagnosis. The heuristic is positional, never lexical — it asks where the log stopped, a question with the same answer in every ecosystem, including the ones no rule covers. Optional &lt;code&gt;log_tail&lt;/code&gt; key in &lt;code&gt;ci-result.v1&lt;/code&gt; (max 5 lines, each capped at 300 characters and passed through &lt;code&gt;redact_ci_log&lt;/code&gt;). (&lt;a class=&quot;issue-link js-issue-link&quot; data-error-text=&quot;Failed to load title&quot; data-id=&quot;4952115071&quot; data-permission-text=&quot;Title is private&quot; data-url=&quot;https://github.com/patchrail/patchrail/issues/399&quot; data-hovercard-type=&quot;pull_request&quot; data-hovercard-url=&quot;/patchrail/patchrail/pull/399/hovercard&quot; href=&quot;https://github.com/patchrail/patchrail/pull/399&quot;&gt;#399&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;The same tail follows a verdict that is only a hint (under &lt;code&gt;LOW_CONFIDENCE_THRESHOLD&lt;/code&gt; = 0.35). rails/rails run 29648807728 is the case: three &lt;code&gt;bundle&lt;/code&gt; invocations carry &lt;code&gt;ruby_bundle_failure&lt;/code&gt; at 0.3, none of them failed, and the step that actually broke — &lt;code&gt;./bin/rails assets:precompile&lt;/code&gt; — sat in the last lines nobody was shown. Same extraction, same cap, same redaction; only the condition widened. (&lt;a class=&quot;issue-link js-issue-link&quot; data-error-text=&quot;Failed to load title&quot; data-id=&quot;4952270044&quot; data-permission-text=&quot;Title is private&quot; data-url=&quot;https://github.com/patchrail/patchrail/issues/400&quot; data-hovercard-type=&quot;pull_request&quot; data-hovercard-url=&quot;/patchrail/patchrail/pull/400/hovercard&quot; href=&quot;https://github.com/patchrail/patchrail/pull/400&quot;&gt;#400&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;failure_class&lt;/code&gt;, &lt;code&gt;confidence&lt;/code&gt;, &lt;code&gt;signals&lt;/code&gt; and exit codes are untouched, and a log that classifies produces byte-identical output to 0.7.5.&lt;/p&gt;
&lt;p&gt;Full changelog: &lt;a href=&quot;https://github.com/patchrail/patchrail/blob/main/CHANGELOG.md&quot;&gt;https://github.com/patchrail/patchrail/blob/main/CHANGELOG.md&lt;/a&gt;&lt;/p&gt;</content>
    <author>
      <name>PabloCodes7</name>
    </author>
    <media:thumbnail height="30" width="30" url="https://avatars.githubusercontent.com/u/284438953?s=60&amp;v=4"/>
  </entry>
  <entry>
    <id>tag:github.com,2008:Repository/1257620736/v0.7.5</id>
    <updated>2026-07-22T13:04:08Z</updated>
    <link rel="alternate" type="text/html" href="https://github.com/patchrail/patchrail/releases/tag/v0.7.5"/>
    <title>v0.7.5</title>
    <content type="html">&lt;p&gt;A low-confidence verdict now reads like one.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;0.7.4&lt;/code&gt; stopped a class carried by nothing but tool invocations from claiming diagnosis-level confidence, but it printed that capped verdict in exactly the same shape as a confident one — &lt;code&gt;Root cause: &amp;lt;class&amp;gt;&lt;/code&gt; / &lt;code&gt;Confidence: 0.3&lt;/code&gt; — so a maintainer still read &quot;root cause&quot; and went off to fix a file that was fine. The number dropped; the message didn&#39;t.&lt;/p&gt;
&lt;h3&gt;Fixed&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Both human-facing reports (&lt;code&gt;--format text&lt;/code&gt; and &lt;code&gt;--format markdown&lt;/code&gt;) now add an explicit caveat below a configurable threshold (&lt;code&gt;LOW_CONFIDENCE_THRESHOLD = 0.35&lt;/code&gt;): that the verdict is a hint rather than a proven cause, that the signals behind it only show a tool &lt;em&gt;ran&lt;/em&gt; and not that it failed, and that the next useful step is the raw log — plus the existing CI failure fixture issue template if the real cause turns out to be something PatchRail cannot classify yet. The guard keys on confidence alone, never on a class or ecosystem; &lt;code&gt;unknown&lt;/code&gt; keeps its own existing message instead of being told twice. (&lt;a class=&quot;issue-link js-issue-link&quot; data-error-text=&quot;Failed to load title&quot; data-id=&quot;4946687825&quot; data-permission-text=&quot;Title is private&quot; data-url=&quot;https://github.com/patchrail/patchrail/issues/397&quot; data-hovercard-type=&quot;pull_request&quot; data-hovercard-url=&quot;/patchrail/patchrail/pull/397/hovercard&quot; href=&quot;https://github.com/patchrail/patchrail/pull/397&quot;&gt;#397&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Presentation only: the class, the confidence, the exit code and the &lt;code&gt;--format json&lt;/code&gt; payload the GitHub Action consumes are unchanged, and a high-confidence report is byte-identical to 0.7.4.&lt;/p&gt;
&lt;p&gt;Full changelog: &lt;a href=&quot;https://github.com/patchrail/patchrail/blob/main/CHANGELOG.md&quot;&gt;https://github.com/patchrail/patchrail/blob/main/CHANGELOG.md&lt;/a&gt;&lt;/p&gt;</content>
    <author>
      <name>PabloCodes7</name>
    </author>
    <media:thumbnail height="30" width="30" url="https://avatars.githubusercontent.com/u/284438953?s=60&amp;v=4"/>
  </entry>
  <entry>
    <id>tag:github.com,2008:Repository/1257620736/v0.7.4</id>
    <updated>2026-07-21T23:01:09Z</updated>
    <link rel="alternate" type="text/html" href="https://github.com/patchrail/patchrail/releases/tag/v0.7.4"/>
    <title>v0.7.4</title>
    <content type="html">&lt;p&gt;Ten false positives removed. Each one is a verdict &lt;code&gt;0.7.3&lt;/code&gt; gets wrong on a real CI log — the classifier named a tool that was fine, or reported diagnosis-level confidence for a guess.&lt;/p&gt;
&lt;h3&gt;Fixed&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;A verdict carried by invocations alone now caps at &lt;strong&gt;0.3&lt;/strong&gt; confidence. An invocation proves a tool ran, never that it failed; rails/rails run 29648807728 dies on a Ruby &lt;code&gt;SyntaxError&lt;/code&gt; and three &lt;code&gt;bundle&lt;/code&gt; invocations were producing &lt;code&gt;ruby_bundle_failure&lt;/code&gt; at 0.89, sending a maintainer to debug a Gemfile that is fine. Legitimate last resorts (a bare &lt;code&gt;pytest&lt;/code&gt;) keep both class and confidence. (&lt;a class=&quot;issue-link js-issue-link&quot; data-error-text=&quot;Failed to load title&quot; data-id=&quot;4942432268&quot; data-permission-text=&quot;Title is private&quot; data-url=&quot;https://github.com/patchrail/patchrail/issues/395&quot; data-hovercard-type=&quot;pull_request&quot; data-hovercard-url=&quot;/patchrail/patchrail/pull/395/hovercard&quot; href=&quot;https://github.com/patchrail/patchrail/pull/395&quot;&gt;#395&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;A yarn install that finishes with warnings is no longer a broken dependency install, and a &lt;code&gt;git checkout&lt;/code&gt; that recovers is no longer a checkout failure. (&lt;a class=&quot;issue-link js-issue-link&quot; data-error-text=&quot;Failed to load title&quot; data-id=&quot;4936818079&quot; data-permission-text=&quot;Title is private&quot; data-url=&quot;https://github.com/patchrail/patchrail/issues/393&quot; data-hovercard-type=&quot;pull_request&quot; data-hovercard-url=&quot;/patchrail/patchrail/pull/393/hovercard&quot; href=&quot;https://github.com/patchrail/patchrail/pull/393&quot;&gt;#393&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;debconf: (TERM is not set, ...)&lt;/code&gt; and other unset terminal/locale variables no longer read as a missing repository secret. (&lt;a class=&quot;issue-link js-issue-link&quot; data-error-text=&quot;Failed to load title&quot; data-id=&quot;4936490332&quot; data-permission-text=&quot;Title is private&quot; data-url=&quot;https://github.com/patchrail/patchrail/issues/392&quot; data-hovercard-type=&quot;pull_request&quot; data-hovercard-url=&quot;/patchrail/patchrail/pull/392/hovercard&quot; href=&quot;https://github.com/patchrail/patchrail/pull/392&quot;&gt;#392&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;A parenthesized &lt;code&gt;Gateway Timeout (504)&lt;/code&gt; is &lt;code&gt;network_transient_failure&lt;/code&gt;, not &lt;code&gt;unknown&lt;/code&gt;. (&lt;a class=&quot;issue-link js-issue-link&quot; data-error-text=&quot;Failed to load title&quot; data-id=&quot;4932177186&quot; data-permission-text=&quot;Title is private&quot; data-url=&quot;https://github.com/patchrail/patchrail/issues/391&quot; data-hovercard-type=&quot;pull_request&quot; data-hovercard-url=&quot;/patchrail/patchrail/pull/391/hovercard&quot; href=&quot;https://github.com/patchrail/patchrail/pull/391&quot;&gt;#391&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;mypy listed in a pixi/conda dependency manifest is no longer a type-check failure. (&lt;a class=&quot;issue-link js-issue-link&quot; data-error-text=&quot;Failed to load title&quot; data-id=&quot;4932009201&quot; data-permission-text=&quot;Title is private&quot; data-url=&quot;https://github.com/patchrail/patchrail/issues/390&quot; data-hovercard-type=&quot;pull_request&quot; data-hovercard-url=&quot;/patchrail/patchrail/pull/390/hovercard&quot; href=&quot;https://github.com/patchrail/patchrail/pull/390&quot;&gt;#390&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;dune&#39;s &lt;code&gt;make test&lt;/code&gt; and a Crystal spec run are no longer read as C/C++ builds. (&lt;a class=&quot;issue-link js-issue-link&quot; data-error-text=&quot;Failed to load title&quot; data-id=&quot;4912653693&quot; data-permission-text=&quot;Title is private&quot; data-url=&quot;https://github.com/patchrail/patchrail/issues/384&quot; data-hovercard-type=&quot;pull_request&quot; data-hovercard-url=&quot;/patchrail/patchrail/pull/384/hovercard&quot; href=&quot;https://github.com/patchrail/patchrail/pull/384&quot;&gt;#384&lt;/a&gt;, &lt;a class=&quot;issue-link js-issue-link&quot; data-error-text=&quot;Failed to load title&quot; data-id=&quot;4912923129&quot; data-permission-text=&quot;Title is private&quot; data-url=&quot;https://github.com/patchrail/patchrail/issues/385&quot; data-hovercard-type=&quot;pull_request&quot; data-hovercard-url=&quot;/patchrail/patchrail/pull/385/hovercard&quot; href=&quot;https://github.com/patchrail/patchrail/pull/385&quot;&gt;#385&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Cabal&#39;s &lt;code&gt;Could not resolve dependencies:&lt;/code&gt; is no longer a Maven build failure. (&lt;a class=&quot;issue-link js-issue-link&quot; data-error-text=&quot;Failed to load title&quot; data-id=&quot;4912303532&quot; data-permission-text=&quot;Title is private&quot; data-url=&quot;https://github.com/patchrail/patchrail/issues/383&quot; data-hovercard-type=&quot;pull_request&quot; data-hovercard-url=&quot;/patchrail/patchrail/pull/383/hovercard&quot; href=&quot;https://github.com/patchrail/patchrail/pull/383&quot;&gt;#383&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Flutter&#39;s cached Gradle Wrapper is no longer a Gradle build failure. (&lt;a class=&quot;issue-link js-issue-link&quot; data-error-text=&quot;Failed to load title&quot; data-id=&quot;4911000047&quot; data-permission-text=&quot;Title is private&quot; data-url=&quot;https://github.com/patchrail/patchrail/issues/382&quot; data-hovercard-type=&quot;pull_request&quot; data-hovercard-url=&quot;/patchrail/patchrail/pull/382/hovercard&quot; href=&quot;https://github.com/patchrail/patchrail/pull/382&quot;&gt;#382&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;A passing test&#39;s title is no longer a secrets failure. (&lt;a class=&quot;issue-link js-issue-link&quot; data-error-text=&quot;Failed to load title&quot; data-id=&quot;4910533889&quot; data-permission-text=&quot;Title is private&quot; data-url=&quot;https://github.com/patchrail/patchrail/issues/380&quot; data-hovercard-type=&quot;pull_request&quot; data-hovercard-url=&quot;/patchrail/patchrail/pull/380/hovercard&quot; href=&quot;https://github.com/patchrail/patchrail/pull/380&quot;&gt;#380&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;A failing PHPUnit assertion is no longer a Composer failure. (&lt;a class=&quot;issue-link js-issue-link&quot; data-error-text=&quot;Failed to load title&quot; data-id=&quot;4910289684&quot; data-permission-text=&quot;Title is private&quot; data-url=&quot;https://github.com/patchrail/patchrail/issues/378&quot; data-hovercard-type=&quot;pull_request&quot; data-hovercard-url=&quot;/patchrail/patchrail/pull/378/hovercard&quot; href=&quot;https://github.com/patchrail/patchrail/pull/378&quot;&gt;#378&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;An installed &lt;code&gt;pytest&lt;/code&gt; is no longer reported as a failing test run. (&lt;a class=&quot;issue-link js-issue-link&quot; data-error-text=&quot;Failed to load title&quot; data-id=&quot;4909639614&quot; data-permission-text=&quot;Title is private&quot; data-url=&quot;https://github.com/patchrail/patchrail/issues/376&quot; data-hovercard-type=&quot;pull_request&quot; data-hovercard-url=&quot;/patchrail/patchrail/pull/376/hovercard&quot; href=&quot;https://github.com/patchrail/patchrail/pull/376&quot;&gt;#376&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--out&lt;/code&gt; writes only to the file, not also to stdout; &lt;code&gt;redact&lt;/code&gt; and &lt;code&gt;pilot-pack&lt;/code&gt; error on an empty log. (&lt;a class=&quot;issue-link js-issue-link&quot; data-error-text=&quot;Failed to load title&quot; data-id=&quot;4898823031&quot; data-permission-text=&quot;Title is private&quot; data-url=&quot;https://github.com/patchrail/patchrail/issues/370&quot; data-hovercard-type=&quot;pull_request&quot; data-hovercard-url=&quot;/patchrail/patchrail/pull/370/hovercard&quot; href=&quot;https://github.com/patchrail/patchrail/pull/370&quot;&gt;#370&lt;/a&gt;, &lt;a class=&quot;issue-link js-issue-link&quot; data-error-text=&quot;Failed to load title&quot; data-id=&quot;4898958666&quot; data-permission-text=&quot;Title is private&quot; data-url=&quot;https://github.com/patchrail/patchrail/issues/371&quot; data-hovercard-type=&quot;pull_request&quot; data-hovercard-url=&quot;/patchrail/patchrail/pull/371/hovercard&quot; href=&quot;https://github.com/patchrail/patchrail/pull/371&quot;&gt;#371&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Changed&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;patchrail --help&lt;/code&gt; now ends with a link to the project home.&lt;/li&gt;
&lt;li&gt;The CI triage job summary shows the local reproduction command, and no longer carries internal adoption telemetry. (&lt;a class=&quot;issue-link js-issue-link&quot; data-error-text=&quot;Failed to load title&quot; data-id=&quot;4899922280&quot; data-permission-text=&quot;Title is private&quot; data-url=&quot;https://github.com/patchrail/patchrail/issues/372&quot; data-hovercard-type=&quot;pull_request&quot; data-hovercard-url=&quot;/patchrail/patchrail/pull/372/hovercard&quot; href=&quot;https://github.com/patchrail/patchrail/pull/372&quot;&gt;#372&lt;/a&gt;, &lt;a class=&quot;issue-link js-issue-link&quot; data-error-text=&quot;Failed to load title&quot; data-id=&quot;4901649590&quot; data-permission-text=&quot;Title is private&quot; data-url=&quot;https://github.com/patchrail/patchrail/issues/373&quot; data-hovercard-type=&quot;pull_request&quot; data-hovercard-url=&quot;/patchrail/patchrail/pull/373/hovercard&quot; href=&quot;https://github.com/patchrail/patchrail/pull/373&quot;&gt;#373&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;PyPI &lt;code&gt;keywords&lt;/code&gt; and trove classifiers broadened to match how a CI-triage tool is actually searched for.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Two real mainstream CI logs (spring-boot, kafka) are now pinned as regression tests under &lt;code&gt;tests/data/realworld/&lt;/code&gt;, and &lt;code&gt;docs/real-world-benchmark.md&lt;/code&gt; covers twenty-one committed public logs.&lt;/p&gt;
&lt;p&gt;Full changelog: &lt;a href=&quot;https://github.com/patchrail/patchrail/blob/main/CHANGELOG.md&quot;&gt;https://github.com/patchrail/patchrail/blob/main/CHANGELOG.md&lt;/a&gt;&lt;/p&gt;</content>
    <author>
      <name>PabloCodes7</name>
    </author>
    <media:thumbnail height="30" width="30" url="https://avatars.githubusercontent.com/u/284438953?s=60&amp;v=4"/>
  </entry>
  <entry>
    <id>tag:github.com,2008:Repository/1257620736/v0.7.3</id>
    <updated>2026-07-16T02:34:18Z</updated>
    <link rel="alternate" type="text/html" href="https://github.com/patchrail/patchrail/releases/tag/v0.7.3"/>
    <title>v0.7.3</title>
    <content type="html">&lt;p&gt;Four new-user UX fixes merged since 0.7.2, now on PyPI.&lt;/p&gt;
&lt;h2&gt;Fixed&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Piping a non-UTF-8 CI log no longer crashes.&lt;/strong&gt; The headline one-liner &lt;code&gt;gh run view &amp;lt;run-id&amp;gt; --log-failed | patchrail ci explain&lt;/code&gt; feeds raw log bytes to stdin, and real CI logs often carry bytes that aren&#39;t clean UTF-8 (a latin-1 accent in a test name, stray ANSI/control bytes, a truncated multibyte sequence). &lt;code&gt;explain&lt;/code&gt;, &lt;code&gt;classify&lt;/code&gt;, &lt;code&gt;pilot-pack&lt;/code&gt; and &lt;code&gt;redact&lt;/code&gt; now read the stdin pipe as bytes and decode with &lt;code&gt;errors=&quot;replace&quot;&lt;/code&gt; — the same forgiveness the &lt;code&gt;--log &amp;lt;file&amp;gt;&lt;/code&gt; path already had — instead of raising an uncaught &lt;code&gt;UnicodeDecodeError&lt;/code&gt; on a first-timer (&lt;a class=&quot;issue-link js-issue-link&quot; data-error-text=&quot;Failed to load title&quot; data-id=&quot;4897687468&quot; data-permission-text=&quot;Title is private&quot; data-url=&quot;https://github.com/patchrail/patchrail/issues/368&quot; data-hovercard-type=&quot;pull_request&quot; data-hovercard-url=&quot;/patchrail/patchrail/pull/368/hovercard&quot; href=&quot;https://github.com/patchrail/patchrail/pull/368&quot;&gt;#368&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;ci explain&lt;/code&gt; with no &lt;code&gt;--log&lt;/code&gt; in a terminal no longer hangs.&lt;/strong&gt; Running &lt;code&gt;patchrail ci explain&lt;/code&gt; without piping anything in used to block forever on &lt;code&gt;stdin.read()&lt;/code&gt;, looking frozen. It now detects an interactive terminal and fails fast with a hint to pass &lt;code&gt;--log&lt;/code&gt; or pipe a log in, exit 2. A real pipe or file redirect is untouched (&lt;a class=&quot;issue-link js-issue-link&quot; data-error-text=&quot;Failed to load title&quot; data-id=&quot;4896312374&quot; data-permission-text=&quot;Title is private&quot; data-url=&quot;https://github.com/patchrail/patchrail/issues/366&quot; data-hovercard-type=&quot;pull_request&quot; data-hovercard-url=&quot;/patchrail/patchrail/pull/366/hovercard&quot; href=&quot;https://github.com/patchrail/patchrail/pull/366&quot;&gt;#366&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;--log&lt;/code&gt; at a directory or an unreadable file gives a clear message, not a traceback.&lt;/strong&gt; &lt;code&gt;patchrail ci explain --log logs/&lt;/code&gt; used to leak a raw &lt;code&gt;IsADirectoryError&lt;/code&gt;/&lt;code&gt;PermissionError&lt;/code&gt;. It now reports the problem on stderr and exits 2, the same clean contract as the missing-file case (&lt;a class=&quot;issue-link js-issue-link&quot; data-error-text=&quot;Failed to load title&quot; data-id=&quot;4895856815&quot; data-permission-text=&quot;Title is private&quot; data-url=&quot;https://github.com/patchrail/patchrail/issues/365&quot; data-hovercard-type=&quot;pull_request&quot; data-hovercard-url=&quot;/patchrail/patchrail/pull/365/hovercard&quot; href=&quot;https://github.com/patchrail/patchrail/pull/365&quot;&gt;#365&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A passing CI log is no longer reported as an unrecognized failure to file a fixture for.&lt;/strong&gt; A green log that matched no failure rule landed on &lt;code&gt;unknown&lt;/code&gt; (0.15) with &quot;Open a CI failure fixture issue&quot; — inviting non-failures into the tracker. PatchRail now recognizes a log that plainly announces success, flags &lt;code&gt;likely_successful_run&lt;/code&gt;, and replies &quot;No failure detected — point me at the failed run.&quot; Conservative: any failure tell vetoes it, so a genuinely unrecognized failure keeps its &lt;code&gt;unknown&lt;/code&gt; verdict (&lt;a class=&quot;issue-link js-issue-link&quot; data-error-text=&quot;Failed to load title&quot; data-id=&quot;4895618904&quot; data-permission-text=&quot;Title is private&quot; data-url=&quot;https://github.com/patchrail/patchrail/issues/364&quot; data-hovercard-type=&quot;pull_request&quot; data-hovercard-url=&quot;/patchrail/patchrail/pull/364/hovercard&quot; href=&quot;https://github.com/patchrail/patchrail/pull/364&quot;&gt;#364&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also includes a GitLab CI clang++ undefined-reference link fixture from &lt;a class=&quot;user-mention notranslate&quot; data-hovercard-type=&quot;user&quot; data-hovercard-url=&quot;/users/sahilmathur254/hovercard&quot; data-octo-click=&quot;hovercard-link-click&quot; data-octo-dimensions=&quot;link_type:self&quot; href=&quot;https://github.com/sahilmathur254&quot;&gt;@sahilmathur254&lt;/a&gt; (&lt;a class=&quot;issue-link js-issue-link&quot; data-error-text=&quot;Failed to load title&quot; data-id=&quot;4894784396&quot; data-permission-text=&quot;Title is private&quot; data-url=&quot;https://github.com/patchrail/patchrail/issues/363&quot; data-hovercard-type=&quot;pull_request&quot; data-hovercard-url=&quot;/patchrail/patchrail/pull/363/hovercard&quot; href=&quot;https://github.com/patchrail/patchrail/pull/363&quot;&gt;#363&lt;/a&gt;).&lt;/p&gt;</content>
    <author>
      <name>PabloCodes7</name>
    </author>
    <media:thumbnail height="30" width="30" url="https://avatars.githubusercontent.com/u/284438953?s=60&amp;v=4"/>
  </entry>
  <entry>
    <id>tag:github.com,2008:Repository/1257620736/v0.7.2</id>
    <updated>2026-07-15T08:03:13Z</updated>
    <link rel="alternate" type="text/html" href="https://github.com/patchrail/patchrail/releases/tag/v0.7.2"/>
    <title>v0.7.2</title>
    <content type="html">&lt;p&gt;Three fixes merged since 0.7.1, now on PyPI.&lt;/p&gt;
&lt;h2&gt;Fixed&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Flyway runtime migration failures are recognised.&lt;/strong&gt; A &lt;code&gt;flyway migrate&lt;/code&gt; step that fails against the database — &lt;code&gt;ERROR: Migration V2__add_users.sql failed&lt;/code&gt;, &lt;code&gt;SQL State : 42S01&lt;/code&gt; — used to fall through to &lt;code&gt;unknown&lt;/code&gt; (0.15). It now classifies as &lt;code&gt;database_migration_failure&lt;/code&gt; at 0.71 and points you at the SQL error to fix; the &lt;code&gt;SQL State : 00000&lt;/code&gt; success code is explicitly excluded so green runs are untouched. &lt;strong&gt;Thanks to &lt;a class=&quot;user-mention notranslate&quot; data-hovercard-type=&quot;user&quot; data-hovercard-url=&quot;/users/hkJerryLeung/hovercard&quot; data-octo-click=&quot;hovercard-link-click&quot; data-octo-dimensions=&quot;link_type:self&quot; href=&quot;https://github.com/hkJerryLeung&quot;&gt;@hkJerryLeung&lt;/a&gt;&lt;/strong&gt; for the fix (&lt;a class=&quot;issue-link js-issue-link&quot; data-error-text=&quot;Failed to load title&quot; data-id=&quot;4888169106&quot; data-permission-text=&quot;Title is private&quot; data-url=&quot;https://github.com/patchrail/patchrail/issues/361&quot; data-hovercard-type=&quot;pull_request&quot; data-hovercard-url=&quot;/patchrail/patchrail/pull/361/hovercard&quot; href=&quot;https://github.com/patchrail/patchrail/pull/361&quot;&gt;#361&lt;/a&gt;, closing &lt;a class=&quot;issue-link js-issue-link&quot; data-error-text=&quot;Failed to load title&quot; data-id=&quot;4839065006&quot; data-permission-text=&quot;Title is private&quot; data-url=&quot;https://github.com/patchrail/patchrail/issues/265&quot; data-hovercard-type=&quot;issue&quot; data-hovercard-url=&quot;/patchrail/patchrail/issues/265/hovercard&quot; href=&quot;https://github.com/patchrail/patchrail/issues/265&quot;&gt;#265&lt;/a&gt;) — PatchRail&#39;s first merged external contribution.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A failed &lt;code&gt;yarn run&lt;/code&gt; script is no longer reported as a dependency install.&lt;/strong&gt; yarn classic&#39;s docs footer was matched on the bare host, so a &lt;code&gt;yarn run prettier&lt;/code&gt; that failed on a diff got sent to reconcile a lockfile. The footer is now pinned to &lt;code&gt;install&lt;/code&gt;/&lt;code&gt;add&lt;/code&gt;; a real &lt;code&gt;yarn install&lt;/code&gt; failure is unaffected (&lt;a class=&quot;issue-link js-issue-link&quot; data-error-text=&quot;Failed to load title&quot; data-id=&quot;4887884638&quot; data-permission-text=&quot;Title is private&quot; data-url=&quot;https://github.com/patchrail/patchrail/issues/360&quot; data-hovercard-type=&quot;pull_request&quot; data-hovercard-url=&quot;/patchrail/patchrail/pull/360/hovercard&quot; href=&quot;https://github.com/patchrail/patchrail/pull/360&quot;&gt;#360&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A container OOM-killed under test is no longer reported as the &lt;em&gt;runner&lt;/em&gt; running out of memory.&lt;/strong&gt; &lt;code&gt;OOMKilled&lt;/code&gt; / exit 137 / &lt;code&gt;Out of memory&lt;/code&gt; from a container runtime&#39;s own tests now defer to the concrete cause the log recorded (here &lt;code&gt;go_test_failure&lt;/code&gt;). A real host exhaustion still trips a terminal signal and keeps its verdict (&lt;a class=&quot;issue-link js-issue-link&quot; data-error-text=&quot;Failed to load title&quot; data-id=&quot;4887694438&quot; data-permission-text=&quot;Title is private&quot; data-url=&quot;https://github.com/patchrail/patchrail/issues/358&quot; data-hovercard-type=&quot;pull_request&quot; data-hovercard-url=&quot;/patchrail/patchrail/pull/358/hovercard&quot; href=&quot;https://github.com/patchrail/patchrail/pull/358&quot;&gt;#358&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;pip install --upgrade patchrail&lt;/code&gt; · &lt;code&gt;patchrail --version&lt;/code&gt; → &lt;code&gt;patchrail 0.7.2&lt;/code&gt;&lt;/p&gt;</content>
    <author>
      <name>PabloCodes7</name>
    </author>
    <media:thumbnail height="30" width="30" url="https://avatars.githubusercontent.com/u/284438953?s=60&amp;v=4"/>
  </entry>
  <entry>
    <id>tag:github.com,2008:Repository/1257620736/v0.7.1</id>
    <updated>2026-07-14T22:05:54Z</updated>
    <link rel="alternate" type="text/html" href="https://github.com/patchrail/patchrail/releases/tag/v0.7.1"/>
    <title>v0.7.1</title>
    <content type="html">&lt;p&gt;Two misreadings, both the same shape: a line that merely &lt;em&gt;names&lt;/em&gt; a tool, read as proof that tool had &lt;em&gt;failed&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;Fixed&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;A job that declares &lt;code&gt;timeout-minutes&lt;/code&gt; is no longer reported as a job that timed out.&lt;/strong&gt; Actions echoes your step config into the log — &lt;code&gt;timeout-minutes: 180&lt;/code&gt; — on green runs and red ones alike, and PatchRail was reading that declaration as evidence the limit had been &lt;em&gt;hit&lt;/em&gt;. On envoyproxy/envoy&#39;s coverage run &lt;code&gt;29363920524&lt;/code&gt; the job never came near its 180-minute ceiling: one directory out of 430 had slipped three tenths of a point under its coverage threshold. That log now answers &lt;code&gt;code_coverage_threshold&lt;/code&gt;. A job that really did run long is unaffected — the runner says so in words (&lt;code&gt;has exceeded the maximum execution time of…&lt;/code&gt;, &lt;code&gt;The operation was canceled&lt;/code&gt;), and those still land as &lt;code&gt;ci_job_timeout&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;A Go job that fails to compile is no longer reported as a lint failure.&lt;/strong&gt; &lt;code&gt;golangci-lint-action&lt;/code&gt; names its tool five times just to &lt;em&gt;ship&lt;/em&gt; it — version lookup, cache hit, install, echoed command line, timing — and PatchRail was reading those install lines as proof the linter had failed. Any Go job that merely declared the action got a confident &lt;code&gt;go_lint&lt;/code&gt; verdict, whatever had actually broken. On grafana/grafana&#39;s &lt;code&gt;lint-go&lt;/code&gt; run &lt;code&gt;27635190952&lt;/code&gt; there was no lint finding at all: a function had grown a parameter and eight call sites in one test file had not. That log now answers &lt;code&gt;go_test_failure&lt;/code&gt; and reproduces with &lt;code&gt;go test ./...&lt;/code&gt;. A linter that really did report something (&lt;code&gt;(gofmt)&lt;/code&gt;, &lt;code&gt;(gci)&lt;/code&gt;, &lt;code&gt;(revive)&lt;/code&gt;) is still &lt;code&gt;go_lint&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Go call-site mismatches are recognised.&lt;/strong&gt; &lt;code&gt;not enough arguments in call to&lt;/code&gt; and &lt;code&gt;too many arguments in call to&lt;/code&gt; — the compiler&#39;s own words — no longer pass unread, alongside &lt;code&gt;undefined:&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Both fixes were measured against the real failing logs, which ship in the repo under &lt;code&gt;examples/real-world/&lt;/code&gt; so you can reproduce the before and after yourself.&lt;/p&gt;
&lt;div class=&quot;highlight highlight-source-shell notranslate position-relative overflow-auto&quot; data-snippet-clipboard-copy-content=&quot;pip install --upgrade patchrail
patchrail ci explain --log examples/real-world/envoy-29363920524-excerpt.log&quot;&gt;&lt;pre&gt;pip install --upgrade patchrail
patchrail ci explain --log examples/real-world/envoy-29363920524-excerpt.log&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Full changelog:&lt;/strong&gt; &lt;a href=&quot;https://github.com/patchrail/patchrail/blob/main/CHANGELOG.md&quot;&gt;https://github.com/patchrail/patchrail/blob/main/CHANGELOG.md&lt;/a&gt;&lt;/p&gt;</content>
    <author>
      <name>PabloCodes7</name>
    </author>
    <media:thumbnail height="30" width="30" url="https://avatars.githubusercontent.com/u/284438953?s=60&amp;v=4"/>
  </entry>
  <entry>
    <id>tag:github.com,2008:Repository/1257620736/v0.7.0</id>
    <updated>2026-07-14T20:33:47Z</updated>
    <link rel="alternate" type="text/html" href="https://github.com/patchrail/patchrail/releases/tag/v0.7.0"/>
    <title>v0.7.0 — nine fixes for one mistake</title>
    <content type="html">&lt;p&gt;Nine misreadings, all of one kind.&lt;/p&gt;
&lt;p&gt;Every fix in this release started as a real failing run at a real project — pandas, deno, svelte, istio, astro, ruff, prometheus, pytorch — where PatchRail answered confidently and answered &lt;strong&gt;wrong&lt;/strong&gt;. And every one of them was wrong in the same way: it mistook a line that merely &lt;strong&gt;named&lt;/strong&gt; a tool for a line proving that tool had &lt;strong&gt;failed&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;An install listing. A script echoed before it runs. A suppressible CMake warning. A cache cleaning up after a job that was already dead. A test quoting a compiler back at itself.&lt;/p&gt;
&lt;p&gt;A verdict that no signal ever witnessed failing now yields to what the runner actually flagged — and when nothing is left, the honest answer is &lt;code&gt;unknown&lt;/code&gt;, with the failing line handed back to you.&lt;/p&gt;
&lt;h2&gt;What stops being wrong&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;CMake policy&lt;/strong&gt; that &quot;is not set&quot; is no longer read as a repository &lt;strong&gt;secret&lt;/strong&gt; that is not set (&lt;code&gt;CMP0148&lt;/code&gt; is shaped exactly like an environment variable). pytorch&#39;s lint job died in &lt;code&gt;jq&lt;/code&gt;; we sent maintainers to audit their secrets.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;dependency Dependabot merely listed&lt;/strong&gt; in its job definition is no longer mistaken for a linter that ran and failed. svelte&#39;s maintainers were told &lt;code&gt;pnpm lint&lt;/code&gt; broke. No linter ran.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Output a test quotes back at you&lt;/strong&gt; is no longer read as the job&#39;s own diagnostic. deno&#39;s spec suite typechecks deliberately-broken programs on purpose; we told the maintainers of a TypeScript runtime that their TypeScript was broken, at 0.95 confidence.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;source of a step, echoed before it runs&lt;/strong&gt;, is no longer read as the step&#39;s output. ruff&#39;s Rust panic came out &lt;code&gt;python_test_failure&lt;/code&gt;, on an error branch for a download that had succeeded.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;cache that could not save&lt;/strong&gt;, and a tool the job merely &lt;strong&gt;installed&lt;/strong&gt;, no longer decide the verdict. pandas&#39; doc build sent a maintainer to debug a cache that was working perfectly.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;failed &lt;code&gt;npm audit&lt;/code&gt;&lt;/strong&gt; is reported as a failed scan, not a broken install — and npm&#39;s &lt;strong&gt;post-install audit tally&lt;/strong&gt; is not a failed scan at all.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;tie&lt;/strong&gt; between two failure classes goes to the rule that watched something &lt;em&gt;fail&lt;/em&gt;. prometheus — a Go repo, whose Go tests failed — came out &lt;code&gt;javascript_lint&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;proxy logging its own client disconnects&lt;/strong&gt; is not a network outage.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;New: the classifier, measured against real logs&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/patchrail/patchrail/blob/main/docs/real-world-benchmark.md&quot;&gt;&lt;code&gt;docs/real-world-benchmark.md&lt;/code&gt;&lt;/a&gt; runs PatchRail against seven real CI logs and shows what it said before, what it says now, and the command that reproduces each one. The logs are committed verbatim under &lt;code&gt;examples/real-world/&lt;/code&gt;, so you can check the numbers instead of trusting them.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The misses are in the table, not in a footnote.&lt;/strong&gt; pandas still lands on &lt;code&gt;python_test_failure&lt;/code&gt; at 0.53 rather than naming the crash. grafana calls a compile error &lt;code&gt;go_lint&lt;/code&gt;. Four of the seven verdicts are identical before and after — which is the point: these fixes are narrow, and a benchmark that only shows wins is not a benchmark.&lt;/p&gt;
&lt;div class=&quot;highlight highlight-source-shell notranslate position-relative overflow-auto&quot; data-snippet-clipboard-copy-content=&quot;pipx install patchrail
patchrail ci explain --log failed-ci.log&quot;&gt;&lt;pre&gt;pipx install patchrail
patchrail ci explain --log failed-ci.log&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Runs locally. No API keys, no log upload.&lt;/p&gt;</content>
    <author>
      <name>PabloCodes7</name>
    </author>
    <media:thumbnail height="30" width="30" url="https://avatars.githubusercontent.com/u/284438953?s=60&amp;v=4"/>
  </entry>
  <entry>
    <id>tag:github.com,2008:Repository/1257620736/v0.6.1</id>
    <updated>2026-07-14T13:24:41Z</updated>
    <link rel="alternate" type="text/html" href="https://github.com/patchrail/patchrail/releases/tag/v0.6.1"/>
    <title>v0.6.1</title>
    <content type="html">&lt;p&gt;Patch release: a success announced through the error channel is no longer reported as somewhere to &quot;start&quot;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;oven-sh/bun&lt;/code&gt;&#39;s failing run carries exactly one runner annotation in 4,709 lines, and the workflow emits a success through it — &lt;code&gt;##[error]✅ Autofix task started.&lt;/code&gt; The &lt;code&gt;unknown&lt;/code&gt; verdict handed that line back under &lt;em&gt;&quot;the CI runner did annotate these lines as errors — start there&quot;&lt;/em&gt;, pointing the maintainer at a line saying everything went fine.&lt;/p&gt;
&lt;p&gt;The verdict itself was, and stays, correct: &lt;code&gt;unknown&lt;/code&gt; is honest for that log. Only the evidence changes. An annotation is now dropped when it &lt;em&gt;opens&lt;/em&gt; with a success mark and names no failure anywhere in the line — a guard deliberately lopsided towards keeping, so &lt;code&gt;✅ 2 passed, ❌ 1 failed&lt;/code&gt; and &lt;code&gt;✔ image built, but the upload failed&lt;/code&gt; both survive.&lt;/p&gt;
&lt;p&gt;Users of the &lt;a href=&quot;https://github.com/patchrail/ci-triage-action&quot;&gt;CI Triage Action&lt;/a&gt; pick this up on their next run with no change on their side.&lt;/p&gt;
&lt;p&gt;Closes &lt;a class=&quot;issue-link js-issue-link&quot; data-error-text=&quot;Failed to load title&quot; data-id=&quot;4883101776&quot; data-permission-text=&quot;Title is private&quot; data-url=&quot;https://github.com/patchrail/patchrail/issues/329&quot; data-hovercard-type=&quot;issue&quot; data-hovercard-url=&quot;/patchrail/patchrail/issues/329/hovercard&quot; href=&quot;https://github.com/patchrail/patchrail/issues/329&quot;&gt;#329&lt;/a&gt;. Full notes in &lt;a href=&quot;https://github.com/patchrail/patchrail/blob/main/CHANGELOG.md&quot;&gt;CHANGELOG.md&lt;/a&gt;.&lt;/p&gt;</content>
    <author>
      <name>PabloCodes7</name>
    </author>
    <media:thumbnail height="30" width="30" url="https://avatars.githubusercontent.com/u/284438953?s=60&amp;v=4"/>
  </entry>
  <entry>
    <id>tag:github.com,2008:Repository/1257620736/v0.6.0</id>
    <updated>2026-07-14T12:34:42Z</updated>
    <link rel="alternate" type="text/html" href="https://github.com/patchrail/patchrail/releases/tag/v0.6.0"/>
    <title>v0.6.0 — an unknown log that explains itself, and no more invented diagnoses</title>
    <content type="html">&lt;p&gt;Three changes that landed after 0.5.0, all found the same way: piping &lt;strong&gt;real failing runs from public repositories&lt;/strong&gt; through the one-liner in the README, the way a first-time user meets this tool. Eight new ecosystems (deno, bun, istio, astro, airflow, envoy, ruff, pydantic) — three came back confidently wrong.&lt;/p&gt;
&lt;h3&gt;Fixed&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;A tool named inside a filename is no longer a diagnosis.&lt;/strong&gt; A CI log in a monorepo is mostly filenames, and a rule could be carried start to finish by a word that only ever appeared inside one. &lt;code&gt;oven-sh/bun&lt;/code&gt; — a Zig/JS runtime — was told its pnpm lockfile was out of date, on the evidence of prettier listing files it left &lt;code&gt;(unchanged)&lt;/code&gt;, two of which sat under a &lt;code&gt;lockfile/&lt;/code&gt; directory; in the same log, a regression test &lt;em&gt;named after&lt;/em&gt; an advisory (&lt;code&gt;GHSA-pfwx-36v6-832x.test.ts&lt;/code&gt;) was read as a failed security scan that never ran. &lt;code&gt;istio/istio&lt;/code&gt;, a Go repository, was diagnosed with both a Java build failure and a Node install failure, read out of a 2929-character single-line Dependabot JSON blob. &lt;code&gt;withastro/astro&lt;/code&gt; matched on &lt;code&gt;--no-frozen-lockfile&lt;/code&gt; — the flag that &lt;em&gt;permits&lt;/em&gt; the change it was complaining about. A signal must now match outside a path token to carry a verdict, and a bare tool name corroborates a failure without ever constituting one.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The runner&#39;s content-free annotations no longer dress an empty answer up as a finding.&lt;/strong&gt; &lt;code&gt;Process completed with exit code 1.&lt;/code&gt; appears in every failing run, whatever the cause; reported back under a heading it read as evidence, and — each exit code being a distinct string — a matrix build&#39;s worth of them would crowd out the annotation that actually names the failure.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Added&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;An &lt;code&gt;unknown&lt;/code&gt; verdict now hands back the line the runner itself flagged.&lt;/strong&gt; A log no rule matches usually still names its own failure: &lt;code&gt;psf/requests&lt;/code&gt; failed on a single, self-explanatory line — &lt;code&gt;##[error]&quot;github-token&quot; length must be less than or equal to 100 characters long&lt;/code&gt; — and PatchRail answered &lt;code&gt;unknown&lt;/code&gt;, no signals, nothing else. Those annotations are now reported in &lt;code&gt;runner_errors&lt;/code&gt; (JSON), under &quot;Errors the runner reported&quot; (Markdown), and as &lt;code&gt;Runner reported:&lt;/code&gt; (text), redacted and de-duplicated. They stay evidence and nothing more: an annotation says &lt;em&gt;where&lt;/em&gt; the job died, not &lt;em&gt;why&lt;/em&gt;, so the class stays &lt;code&gt;unknown&lt;/code&gt; and the confidence stays at 0.15. PatchRail still does not pretend to recognize a log it does not recognize.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Genuine failures are unaffected: real lockfile, security-scan and build failures score exactly as before, and no fixture changes classification or confidence (221 fixtures, top-1 1.0).&lt;/p&gt;
&lt;div class=&quot;highlight highlight-source-shell notranslate position-relative overflow-auto&quot; data-snippet-clipboard-copy-content=&quot;pip install --upgrade patchrail&quot;&gt;&lt;pre&gt;pip install --upgrade patchrail&lt;/pre&gt;&lt;/div&gt;</content>
    <author>
      <name>PabloCodes7</name>
    </author>
    <media:thumbnail height="30" width="30" url="https://avatars.githubusercontent.com/u/284438953?s=60&amp;v=4"/>
  </entry>
  <entry>
    <id>tag:github.com,2008:Repository/1257620736/v0.5.0</id>
    <updated>2026-07-14T10:32:28Z</updated>
    <link rel="alternate" type="text/html" href="https://github.com/patchrail/patchrail/releases/tag/v0.5.0"/>
    <title>v0.5.0 — real logs, real causes</title>
    <content type="html">&lt;p&gt;Five accuracy fixes that landed after 0.4.0, all found by running &lt;code&gt;ci explain&lt;/code&gt; over &lt;strong&gt;real failing runs from public repositories&lt;/strong&gt; rather than over the fixture zoo. The zoo&#39;s logs are clean; a real one is not, and every one of these bugs hid in the difference.&lt;/p&gt;
&lt;h3&gt;Fixed&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;A tool the job merely &lt;em&gt;named&lt;/em&gt; no longer outranks the one that failed.&lt;/strong&gt; &lt;code&gt;set -x&lt;/code&gt; echoes every command into the log whether it passes or not, and pip announces every dependency it resolves — so &lt;code&gt;Collecting mypy==1.17.1&lt;/code&gt; put mypy in the log of a job that never type-checked anything. Signals are now judged by the &lt;em&gt;line&lt;/em&gt; they land on. Caught 3 of 9 real Python runs (httpx, prefect, home-assistant) and 3 of 17 across Go/Rust/JVM/.NET/C++ (kafka, moby, opencv), where a &lt;code&gt;GRADLE_HOME=&lt;/code&gt; entry in a Windows environment table was enough to diagnose a Java build failure in a job that compiled nothing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ANSI colour codes no longer hide the failure.&lt;/strong&gt; CI keeps the colour on and the GitHub log API serves the escapes back, so the reset lands &lt;em&gt;inside&lt;/em&gt; the failure line (&lt;code&gt;^[[31mFAILED^[[0m tests/…&lt;/code&gt;) and &lt;code&gt;FAILED .*::&lt;/code&gt; silently stopped matching. A real airflow test failure was reported as an artifact error.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;python_test_failure&lt;/code&gt; now recognises pytest&#39;s own verdict&lt;/strong&gt; — &lt;code&gt;1 failed, 1416 passed in 18.37s&lt;/code&gt;, the short test summary, and collection errors, not just named tests.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Post-failure cleanup noise no longer outranks the real cause.&lt;/strong&gt; The &lt;code&gt;if: failure()&lt;/code&gt; step that uploads logs and finds nothing is the commonest shape in CI; it used to tie the real cause and win on declaration order.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The classifier no longer reads a command that merely &lt;em&gt;ran&lt;/em&gt; as the failure&lt;/strong&gt; — &lt;code&gt;\btsc\b&lt;/code&gt; matched the x86 time stamp counter in &lt;code&gt;/proc/cpuinfo&lt;/code&gt;, diagnosing a rust-lang/rust build failure as a TypeScript typecheck.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Genuine failures are unaffected: a real gradle, clippy, docker or dotnet failure scores exactly as before, and no fixture changes classification or confidence (221 fixtures, top-1 1.0).&lt;/p&gt;
&lt;h3&gt;Added&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;patchrail schema ci-classes&lt;/code&gt; publishes the schema for &lt;code&gt;ci classes --format json&lt;/code&gt;, with a conformance test that pins the emitted &lt;code&gt;schema_version&lt;/code&gt; to the schema you can fetch, so the contract cannot drift silently again.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docs/json-cookbook.md&lt;/code&gt; documents the &lt;code&gt;ci classes&lt;/code&gt; payload with a coverage recipe.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;highlight highlight-source-shell notranslate position-relative overflow-auto&quot; data-snippet-clipboard-copy-content=&quot;pip install --upgrade patchrail&quot;&gt;&lt;pre&gt;pip install --upgrade patchrail&lt;/pre&gt;&lt;/div&gt;</content>
    <author>
      <name>PabloCodes7</name>
    </author>
    <media:thumbnail height="30" width="30" url="https://avatars.githubusercontent.com/u/284438953?s=60&amp;v=4"/>
  </entry>
</feed>
