<?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: Piyush Soni</title>
    <description>The latest articles on DEV Community by Piyush Soni (@piyush_soni_74c459572e149).</description>
    <link>https://dev.to/piyush_soni_74c459572e149</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4189628%2F2c82958e-0528-4089-bc23-f26c36c86d0c.jpg</url>
      <title>DEV Community: Piyush Soni</title>
      <link>https://dev.to/piyush_soni_74c459572e149</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/piyush_soni_74c459572e149"/>
    <language>en</language>
    <item>
      <title>Managers don't read every PR. A local Gemma does, and speaks up only when it matters.</title>
      <dc:creator>Piyush Soni</dc:creator>
      <pubDate>Tue, 20 Oct 2026 19:35:06 +0000</pubDate>
      <link>https://dev.to/piyush_soni_74c459572e149/lazylead-a-morning-brief-for-engineering-managers-written-overnight-by-a-local-gemma-with-no-385b</link>
      <guid>https://dev.to/piyush_soni_74c459572e149/lazylead-a-morning-brief-for-engineering-managers-written-overnight-by-a-local-gemma-with-no-385b</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week3-2026-10-19"&gt;Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I'm a senior full-stack developer. Part of my job is reviewing other people's PRs before they merge, so I know how it looks from the reviewer's side: the PR list is long, GitHub sends a lot of notifications, and a review request can quietly sit for days.&lt;/p&gt;

&lt;p&gt;Engineering managers have it harder. They want to know how the team is doing, but opening GitHub every morning and reading through PRs takes time they don't have, and on most days nothing is wrong. So they tend to look only when something has already gone wrong: a release is late, or someone complains that their PR has been waiting for a week. A PR was opened on Friday and nobody was ever asked to review it. Someone asked "is 3 retries OK for the bank API?" in a thread and the person it was meant for never saw it. Things like that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LazyLead&lt;/strong&gt; is for that manager: a brief every morning, without going to GitHub. Every night at 3 AM it reads the team's GitHub activity on a server you control, and a local &lt;strong&gt;Gemma 4&lt;/strong&gt; turns it into a short brief of what happened yesterday and what is stuck. If something needs a human (an overdue review, a PR with no reviewer, an unanswered question), the manager's phone gets one push. If nothing does, it stays quiet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F34evro153q181a22qdk9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F34evro153q181a22qdk9.png" alt=" " width="800" height="1434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The brief leads with a TL;DR, then a short list per person: &lt;em&gt;you owe a review&lt;/em&gt;, &lt;em&gt;someone asked you something&lt;/em&gt;, &lt;em&gt;your PR has no reviewer&lt;/em&gt;. For each overdue review there is a friendly nudge, ready to copy. Everyone else on the team gets a file with only their own items.&lt;/p&gt;

&lt;p&gt;LazyLead only reads GitHub. It never comments, merges or changes anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Live sample brief:&lt;/strong&gt; &lt;a href="https://sonip98.github.io/lazylead/" rel="noopener noreferrer"&gt;https://sonip98.github.io/lazylead/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That page is a real brief from LazyLead's own repo. I'm a developer, not a manager, and I don't have a team to test on, so I built LazyLead through real pull requests between two of my own GitHub accounts: &lt;code&gt;sonip98&lt;/code&gt; plays the manager and &lt;code&gt;piyushsoni-wq&lt;/code&gt; plays the developer. So the brief is about LazyLead's own development. On that run it read &lt;strong&gt;19 items&lt;/strong&gt; (PRs, reviews, comments) and put &lt;strong&gt;2&lt;/strong&gt; in front of people: one overdue review and one PR that nobody had picked up.&lt;/p&gt;

&lt;p&gt;One honest note: real teams use &lt;code&gt;staleHours: 24&lt;/code&gt;. For the demo run I set it to 15 minutes so the overdue sections show up the same day. Same code, one config value.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/fisinSloRvc" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/sonip98" rel="noopener noreferrer"&gt;
        sonip98
      &lt;/a&gt; / &lt;a href="https://github.com/sonip98/lazylead" rel="noopener noreferrer"&gt;
        lazylead
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A morning brief for engineering managers, written overnight by a local Gemma. No GitHub tab needed. Pings only when a review is overdue or a PR is stuck.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;🦥 LazyLead&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;A morning brief for engineering managers, written overnight by a local Gemma. No GitHub tab needed.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A manager wants to know how the team is doing, but opening GitHub and reading through PRs every morning takes time they don't have, and most days nothing is wrong. So they usually look only when something has already gone wrong. LazyLead reads the team's GitHub every night on your own machine, writes one page, and (optionally) pushes to the manager's phone only when a review is overdue, a PR has no reviewer, or a question is still unanswered. Quiet nights stay quiet.&lt;/p&gt;
&lt;p&gt;The page has:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;TL;DR&lt;/strong&gt; – the most urgent thing first, then the counts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Needs someone&lt;/strong&gt; – per person: reviews waiting on you, questions asked of you, your PRs that are approved or need changes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Yesterday&lt;/strong&gt; – merged, opened, closed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Discussions&lt;/strong&gt; – one line per active PR thread&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stuck &amp;amp;&lt;/strong&gt;…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/sonip98/lazylead" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Worth a look: &lt;code&gt;src/brief.js&lt;/code&gt; (everything Gemma does, plus the checks around it), &lt;code&gt;src/facts.js&lt;/code&gt; (everything that must never be guessed), &lt;code&gt;src/notify.js&lt;/code&gt; (the quiet-unless-needed push).&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Model:&lt;/strong&gt; &lt;code&gt;gemma4:e4b-it-qat&lt;/code&gt; (6.1 GB, quantization-aware trained) on &lt;strong&gt;Ollama&lt;/strong&gt;, on a 4-core ARM server with no GPU.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What only the model can do.&lt;/strong&gt; Counting PRs is easy. Reading a thread is not. Code can see that a comment contains &lt;code&gt;@piyushsoni-wq&lt;/code&gt;. It cannot tell whether that is a question, what is being asked, or whether it is still open. In the first real run, sonip98 left a long comment on PR #1 that started with praise and ended with a question. Gemma turned it into one line under &lt;strong&gt;@piyushsoni-wq: Reply on #1: Should the per-person file list the author's own stuck PRs?&lt;/strong&gt; Once piyushsoni-wq replied, Gemma dropped the question from the next brief. (The plain @mention did not drop. That was my bug, see below.) Gemma does three jobs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Read each active PR thread&lt;/strong&gt; (map): a one-line summary, plus any question still waiting for a reply and &lt;em&gt;who&lt;/em&gt; has to answer it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write a nudge&lt;/strong&gt; for each overdue review: short, polite, no guilt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write the TL;DR&lt;/strong&gt; (reduce), most urgent thing first.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;What the model never does.&lt;/strong&gt; Counts, wait times, who was asked to review, @mentions and bot noise come from plain code and the GitHub API. Gemma's output is JSON with a schema (Ollama's &lt;code&gt;format&lt;/code&gt;), and the code checks it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A question can only be routed to someone who is actually in the thread.&lt;/li&gt;
&lt;li&gt;Every number in the TL;DR must exist in the facts. If Gemma invents one, its TL;DR is replaced by a plain one, and the brief shows what Gemma wrote, so you can see why.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GitHub API ─► facts (code) ─┬─► Gemma: read threads, find open questions ─┐
                            ├─► Gemma: nudges for overdue reviews ────────┤
                            └─► Gemma: TL;DR ─► number check ─────────────┴─► brief + optional push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Quiet unless needed.&lt;/strong&gt; The phone push is optional and uses &lt;a href="https://ntfy.sh" rel="noopener noreferrer"&gt;ntfy&lt;/a&gt;, an open-source push service you can self-host. It only fires for exceptions: overdue reviews, PRs with no reviewer, unanswered questions. A normal day sends nothing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When the model is down,&lt;/strong&gt; the brief still ships from the facts, with template nudges. If one model call fails, only that item falls back.&lt;/p&gt;

&lt;h3&gt;
  
  
  What went wrong
&lt;/h3&gt;

&lt;p&gt;All of these came from reading real briefs, not from tests (tests came after: 19, offline, with a fake model):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The hallucination guard hallucinated.&lt;/strong&gt; One TL;DR was thrown away, and I could not see why. So I made the brief show the rejected text. Gemma had written: &lt;em&gt;"Review of 'Facts-only brief when the model is down' by @sonip98 is overdue. 4 merged, 2 opened…"&lt;/em&gt; Every count was right. My check had read &lt;strong&gt;@sonip98 as the number 98&lt;/strong&gt;. Digits inside @logins and words are now ignored, and &lt;code&gt;#N&lt;/code&gt; must be a real PR.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ghost mentions.&lt;/strong&gt; The brief told @piyushsoni-wq that someone had mentioned them, after they had already replied. A mention is now dropped once the person comments or reviews.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The first TL;DR was useless.&lt;/strong&gt; It repeated the counts. Now it gets the urgent items by title, with no numbers, so the number check stays strict.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemma echoed my JSON keys&lt;/strong&gt; ("1 reviewsWaiting, 1 stuckPrs"). I now give it the counts as words.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Then I pointed it at ollama/ollama
&lt;/h3&gt;

&lt;p&gt;A two-person demo repo proves little, so I ran LazyLead against &lt;strong&gt;ollama/ollama&lt;/strong&gt; (500+ open PRs), on the same 4-core server that also serves three live websites, sampling the server every 5 seconds.&lt;/p&gt;

&lt;p&gt;The first run was humbling: 1,013 GitHub API calls and 7.5 minutes for one day of data, a silent stop at 500 PRs, and a brief listing &lt;strong&gt;400&lt;/strong&gt; PRs "with no reviewer". A phone push saying "400 things need attention" helps nobody. After the fixes:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Collecting one day&lt;/td&gt;
&lt;td&gt;450 s, 1,013 API calls&lt;/td&gt;
&lt;td&gt;60 s, 537 API calls&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemma work&lt;/td&gt;
&lt;td&gt;29 calls, 412 s&lt;/td&gt;
&lt;td&gt;17 calls, 306 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"No reviewer" list&lt;/td&gt;
&lt;td&gt;400 lines&lt;/td&gt;
&lt;td&gt;10 shown, "…and 133 more", 258 abandoned PRs in one line&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;With a 4-person team set&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;"Read 518 items so you can read 19"&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;While Gemma ran flat out, the other sites on the box got 5 to 12 ms slower at the median, with zero failed requests. Ollama is capped at 3 of 4 cores and runs at low priority, so the websites always keep a core.&lt;/p&gt;

&lt;p&gt;The load test also exposed a silent accuracy bug: a thread with hundreds of comments would overflow Gemma's 8k context, and Ollama quietly drops the &lt;em&gt;start&lt;/em&gt; of the prompt, which is where the instructions are. Each thread now gets a fixed budget, newest comments first, and Gemma is told how many older ones were left out. A 300-comment test thread became a 2,889-token prompt, and Gemma still sent the final question to the right person.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Team discussions stay on your machine.&lt;/strong&gt; PR threads are where people write "this is a hack," "the client wants X by Friday," "we are behind." Sending all of that to a third-party AI API every night is exactly what a security review says no to. Here, Gemma runs in Ollama on a server you control. The only outside call is to GitHub, which already has the data. The model step even works fully offline: &lt;code&gt;--from-snapshot&lt;/code&gt; rebuilds a brief from saved data with no network.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Slow is fine, so cheap hardware is fine.&lt;/strong&gt; On 4 ARM cores with no GPU, Gemma 4 E4B reads about 32 tokens per second and writes about 8. In a chat app that would feel broken. At 3 AM nobody is waiting. The demo run took 41 seconds of model time. A busy team with 30 active threads would take about 20 minutes, and still be done long before anyone wakes up. Slow and steady is the design.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It costs nothing to run.&lt;/strong&gt; The demo run used 1,656 tokens. A paid API would charge cents a day, but it never stops, and it is one more bill to watch for a tool whose whole point is to give someone less to watch. Here the cost is the power of a server that was already on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I own the behaviour.&lt;/strong&gt; Swapping to the 12B model, or anything else Ollama serves, is one config line. The prompts, schema and checks are mine to change. Nobody can deprecate the model or change how it answers overnight.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where a closed model would win:&lt;/strong&gt; wording. A frontier model would write nicer summaries and would need the number check less often. For a 3 AM brief about a team's private work, "correct and a bit plain" beats "beautiful, and on someone else's server."&lt;/p&gt;

&lt;h2&gt;
  
  
  The Lazy Payoff
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The manager doesn't have to open GitHub: they read one short page, or get a push only when something is stuck. Everyone else gets a file with only what waits on them.&lt;/li&gt;
&lt;li&gt;I haven't run it with a real manager yet. I built it as a developer, tested it on LazyLead's own repo and on ollama/ollama, and I'd like to hear from managers who try it.&lt;/li&gt;
&lt;li&gt;On the demo run: &lt;strong&gt;19 items read, 2 needed a human.&lt;/strong&gt; 5 model calls, 1,656 tokens, 41 seconds, $0.&lt;/li&gt;
&lt;li&gt;It caught real bugs in itself (the ghost mention, the @sonip98 = 98 check). Having the tool brief me on its own development was the best test I had.&lt;/li&gt;
&lt;li&gt;PR #2 stayed in the overdue list, with a ready-to-send nudge, until sonip98 reviewed it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Best Use of Gemma&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>gemma</category>
      <category>ai</category>
    </item>
    <item>
      <title>How I stopped babysitting late-night releases</title>
      <dc:creator>Piyush Soni</dc:creator>
      <pubDate>Fri, 16 Oct 2026 23:15:40 +0000</pubDate>
      <link>https://dev.to/piyush_soni_74c459572e149/how-i-stopped-babysitting-late-night-releases-4ko4</link>
      <guid>https://dev.to/piyush_soni_74c459572e149/how-i-stopped-babysitting-late-night-releases-4ko4</guid>
      <description>&lt;p&gt;For a long time my release process looked like this: build a feature, test it well on staging, and then be told it should go live after business hours. So I'd stay up, merge the pull request at the right time, watch the deploy, and be ready to roll it back.&lt;/p&gt;

&lt;p&gt;That's a boring job for a person. Here is what I automated, and the traps I found.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Merge the commit you approved, not whatever is on the branch
&lt;/h3&gt;

&lt;p&gt;If you schedule a merge for 11 pm and someone pushes at 10:50, a naive scheduler merges code nobody reviewed. The fix is to pin the PR's head commit when you schedule. At merge time, if the head changed, skip the release and say so.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Check again at merge time
&lt;/h3&gt;

&lt;p&gt;Required checks, conflicts and approvals can change in the hours between scheduling and merging. Run the prechecks twice: when you schedule, and right before you merge.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Watch the deploy, not just the merge
&lt;/h3&gt;

&lt;p&gt;A merge isn't done until the deploy is green. After merging, find the workflow run that the push triggered (&lt;code&gt;workflow_run&lt;/code&gt; webhooks make this reliable) and follow it to the end. Capture the failed job and step, plus a few lines around the error, so the email says why it failed.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Revert only if it's safe
&lt;/h3&gt;

&lt;p&gt;The riskiest part is the automatic revert. If the branch has moved on since your merge, reverting would also undo other people's work. So: revert automatically only when your merge is still the tip, open it as a normal revert pull request (no history rewriting), wait for the redeploy, and otherwise just tell a human.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Know what you can't undo
&lt;/h3&gt;

&lt;p&gt;Database migrations and infrastructure changes deployed outside the push workflow can't be rolled back by reverting a commit. Detect pull requests that touch those paths and warn before scheduling.&lt;/p&gt;

&lt;h3&gt;
  
  
  The tool
&lt;/h3&gt;

&lt;p&gt;I put this together as &lt;strong&gt;Merge Scheduler&lt;/strong&gt;, a GitHub App that does all of the above: &lt;a href="https://mergescheduler.gentlesoni.online/?utm_source=devto" rel="noopener noreferrer"&gt;mergescheduler.gentlesoni.online&lt;/a&gt;. There is a free plan with no time limit. It only touches the repositories you pick and doesn't keep your code (&lt;a href="https://mergescheduler.gentlesoni.online/security" rel="noopener noreferrer"&gt;what it asks for and why&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;If you handle after-hours releases differently, I'd like to hear how in the comments.&lt;/p&gt;

</description>
      <category>github</category>
      <category>devops</category>
      <category>cicd</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
