<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Vlad Arbatov</title>
    <description>The latest articles on DEV Community by Vlad Arbatov (@vladarbatov).</description>
    <link>https://dev.to/vladarbatov</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3424401%2Fab0360db-20d0-439e-9f2f-3dc7ac5f4c0c.jpg</url>
      <title>DEV Community: Vlad Arbatov</title>
      <link>https://dev.to/vladarbatov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vladarbatov"/>
    <language>en</language>
    <item>
      <title>PullGuard: a GitHub Action that scores PR review risk for OSS maintainers</title>
      <dc:creator>Vlad Arbatov</dc:creator>
      <pubDate>Mon, 18 May 2026 16:20:54 +0000</pubDate>
      <link>https://dev.to/vladarbatov/pullguard-a-github-action-that-scores-pr-review-risk-for-oss-maintainers-2jcf</link>
      <guid>https://dev.to/vladarbatov/pullguard-a-github-action-that-scores-pr-review-risk-for-oss-maintainers-2jcf</guid>
      <description>&lt;p&gt;OSS maintainers spend reviewer hours on the same patterns over and over. Near-empty fixes, broad unrelated changes, refactors that drop tests, PR descriptions that don't match the diff. Some PRs are AI-generated, some are just careless. Either way they end up in the same triage queue.&lt;/p&gt;

&lt;p&gt;PullGuard is a GitHub Action that scores pull request review risk so maintainers can route their attention. BYOK (OpenAI or Anthropic). It can comment, label, or close a PR based on policy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.arbatov.dev/pullguard" rel="noopener noreferrer"&gt;LINK&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What it flags
&lt;/h2&gt;

&lt;p&gt;PullGuard does not try to detect whether a PR was written by an AI. That signal is too noisy and the question is the wrong one. Maintainers actually care about review cost. The rule set looks for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;missing or weakly extended tests&lt;/li&gt;
&lt;li&gt;broad unrelated changes in one PR&lt;/li&gt;
&lt;li&gt;risky refactors without obvious motivation&lt;/li&gt;
&lt;li&gt;duplicated logic across files&lt;/li&gt;
&lt;li&gt;weak or templated PR descriptions&lt;/li&gt;
&lt;li&gt;suspiciously shallow fixes (one-line patches to deep issues)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Output is a 0 to 100 score plus a short comment listing top findings, capped at four to keep noise down.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx pullguard init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That writes &lt;code&gt;.github/workflows/pullguard.yml&lt;/code&gt; and &lt;code&gt;.github/pullguard.yml&lt;/code&gt;, then prints exact next steps. Add &lt;code&gt;OPENAI_API_KEY&lt;/code&gt; or &lt;code&gt;ANTHROPIC_API_KEY&lt;/code&gt; as a repository secret.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openai&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gpt-5.4-mini-2026-03-17&lt;/span&gt;

&lt;span class="na"&gt;trigger&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;comment&lt;/span&gt;
  &lt;span class="na"&gt;comment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/pullguard&lt;/span&gt;
  &lt;span class="na"&gt;allowedCommentAuthorAssociations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;OWNER&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;MEMBER&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;COLLABORATOR&lt;/span&gt;

&lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;comment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;threshold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt;
        &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;needs-human-review&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;threshold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
        &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;high-risk-pr&lt;/span&gt;
  &lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Trigger modes
&lt;/h2&gt;

&lt;p&gt;Three options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;always&lt;/code&gt;: run on every configured PR event.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;label&lt;/code&gt;: run when a specific label is applied.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;comment&lt;/code&gt;: run when an allowed maintainer comments &lt;code&gt;/pullguard&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Default is &lt;code&gt;comment&lt;/code&gt;, restricted to maintainers via &lt;code&gt;allowedCommentAuthorAssociations&lt;/code&gt;. Random commenters cannot spend the repository's API credits.&lt;/p&gt;

&lt;p&gt;Maintainers can override a single run from the comment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/pullguard --depth codebase --close 95
/pullguard --provider anthropic --model claude-sonnet-4-20250514
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Three independent actions
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;comment&lt;/code&gt;, &lt;code&gt;labels&lt;/code&gt;, and &lt;code&gt;close&lt;/code&gt; are separate switches. Common combinations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Comment-only: post a short review summary, no labels, no closing.&lt;/li&gt;
&lt;li&gt;Label-only: route to humans by score threshold.&lt;/li&gt;
&lt;li&gt;Observe-only: compute the score for downstream workflow steps without touching the PR.&lt;/li&gt;
&lt;li&gt;All three: the full pipeline for projects buried in low-quality PRs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Closing is off by default. In public OSS the cost of an incorrect close is much higher than a missed PR.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why BYOK
&lt;/h2&gt;

&lt;p&gt;The action does not call any third-party service of mine. Provider key, model choice, and rate are under the maintainer's control. Token spend is bounded by &lt;code&gt;maxPatchCharsPerFile&lt;/code&gt;, &lt;code&gt;maxFiles&lt;/code&gt;, and &lt;code&gt;maxFindings&lt;/code&gt;, so a single run on a normal PR is cheap.&lt;/p&gt;

&lt;h2&gt;
  
  
  Disclaimer
&lt;/h2&gt;

&lt;p&gt;Early work. Score calibration is still being adjusted against real OSS PRs and the comment text needs polishing. Two useful things if you try it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Tell me when the score is obviously wrong in either direction.&lt;/li&gt;
&lt;li&gt;Tell me when the comment is confusing or unhelpful.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/vladzima/pullguard" rel="noopener noreferrer"&gt;https://github.com/vladzima/pullguard&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>github</category>
      <category>opensource</category>
      <category>devops</category>
    </item>
    <item>
      <title>Claude Code Internals</title>
      <dc:creator>Vlad Arbatov</dc:creator>
      <pubDate>Tue, 31 Mar 2026 10:40:28 +0000</pubDate>
      <link>https://dev.to/vladarbatov/claude-code-internals-24hk</link>
      <guid>https://dev.to/vladarbatov/claude-code-internals-24hk</guid>
      <description>&lt;p&gt;Since Claude Code full source leaked, i went ahead and created deep technical documentation of CC's architecture and internals, derived from analysis of 1,884 files and 512k lines of TypeScript. Should be useful to anyone touching CC as a tool in their pipeline.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.arbatov.dev/claude-code" rel="noopener noreferrer"&gt;HERE &amp;gt;&amp;gt;&amp;gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It has 8 sections:&lt;br&gt;
&lt;strong&gt;Architecture Overview&lt;/strong&gt;&lt;br&gt;
Entry points, data flow, module graph, config, process model, state&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Query Engine&lt;/strong&gt;&lt;br&gt;
Conversation loop, streaming, token management, error recovery, compaction&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tool System&lt;/strong&gt;&lt;br&gt;
Tool interface, registry, execution lifecycle, permissions, deferred tools&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Agent &amp;amp; Coordinator&lt;/strong&gt;&lt;br&gt;
Subagents, coordinator mode, isolation, fork protocol, task management&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MCP Integration&lt;/strong&gt;&lt;br&gt;
Server lifecycle, tool proxying, OAuth, resources, elicitation&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Context &amp;amp; System Prompts&lt;/strong&gt;&lt;br&gt;
Prompt assembly, CLAUDE.md, auto-memory, git context, compression&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hooks, Skills, Permissions&lt;/strong&gt;&lt;br&gt;
Hook events, skill format, permission modes, sandbox, denial tracking&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Server, Bridge, Remote&lt;/strong&gt;&lt;br&gt;
Server mode, bridge protocol, CCR, WebSocket, cron, state management&lt;/p&gt;

</description>
      <category>vibecoding</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
