跳到正文
DEV Community· Piyush Soni·· 4 小時前AI 評分56

LazyLead 以本地 Gemma 編寫工程經理晨間簡報,毋須開啟 GitHub

LazyLead: a morning brief for engineering managers, written overnight by a local Gemma, with no GitHub tab needed

AI 導讀

LazyLead 每晚 3 AM 在用戶自控的伺服器上讀取團隊的 GitHub 活動,並以本地 Gemma 4 生成工程經理晨間簡報。它只讀取 GitHub,不會留言、合併或修改內容;只有遇到逾期審核、無人負責的 PR 或未獲回覆的問題時,才可選擇向經理手機推送通知。

正文

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady

What I Built

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.

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.

LazyLead 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 Gemma 4 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.

The brief leads with a TL;DR, then a short list per person: you owe a review, someone asked you something, your PR has no reviewer. 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.

LazyLead only reads GitHub. It never comments, merges or changes anything.

Demo

Live sample brief: https://sonip98.github.io/lazylead/

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: sonip98 plays the manager and piyushsoni-wq plays the developer. So the brief is about LazyLead's own development. On that run it read 19 items (PRs, reviews, comments) and put 2 in front of people: one overdue review and one PR that nobody had picked up.

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

Code

GitHub logo sonip98 / lazylead

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.

🦥 LazyLead

A morning brief for engineering managers, written overnight by a local Gemma. No GitHub tab needed.

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.

The page has:

  • TL;DR – the most urgent thing first, then the counts
  • Needs someone – per person: reviews waiting on you, questions asked of you, your PRs that are approved or need changes
  • Yesterday – merged, opened, closed
  • Discussions – one line per active PR thread
  • Stuck &…

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

How I Built It

Model: gemma4:e4b-it-qat (6.1 GB, quantization-aware trained) on Ollama, on a 4-core ARM server with no GPU.

What only the model can do. Counting PRs is easy. Reading a thread is not. Code can see that a comment contains @piyushsoni-wq. 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 @piyushsoni-wq: Reply on #1: Should the per-person file list the author's own stuck PRs? 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:

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

What the model never does. 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 format), and the code checks it:

  • A question can only be routed to someone who is actually in the thread.
  • 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.
GitHub API ─► facts (code) ─┬─► Gemma: read threads, find open questions ─┐
                            ├─► Gemma: nudges for overdue reviews ────────┤
                            └─► Gemma: TL;DR ─► number check ─────────────┴─► brief + optional push

Quiet unless needed. The phone push is optional and uses ntfy, 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.

When the model is down, the brief still ships from the facts, with template nudges. If one model call fails, only that item falls back.

What went wrong

All of these came from reading real briefs, not from tests (tests came after: 19, offline, with a fake model):

  • The hallucination guard hallucinated. One TL;DR was thrown away, and I could not see why. So I made the brief show the rejected text. Gemma had written: "Review of 'Facts-only brief when the model is down' by @sonip98 is overdue. 4 merged, 2 opened…" Every count was right. My check had read @sonip98 as the number 98. Digits inside @logins and words are now ignored, and #N must be a real PR.
  • Ghost mentions. 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.
  • The first TL;DR was useless. It repeated the counts. Now it gets the urgent items by title, with no numbers, so the number check stays strict.
  • Gemma echoed my JSON keys ("1 reviewsWaiting, 1 stuckPrs"). I now give it the counts as words.

Then I pointed it at ollama/ollama

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

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 400 PRs "with no reviewer". A phone push saying "400 things need attention" helps nobody. After the fixes:

Before After
Collecting one day 450 s, 1,013 API calls 60 s, 537 API calls
Gemma work 29 calls, 412 s 17 calls, 306 s
"No reviewer" list 400 lines 10 shown, "…and 133 more", 258 abandoned PRs in one line
With a 4-person team set – "Read 518 items so you can read 19"

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.

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 start 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.

Why Does Open Innovation Matter?

Team discussions stay on your machine. 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: --from-snapshot rebuilds a brief from saved data with no network.

Slow is fine, so cheap hardware is fine. 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.

It costs nothing to run. 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.

I own the behaviour. 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.

Where a closed model would win: 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."

The Lazy Payoff

  • 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.
  • 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.
  • On the demo run: 19 items read, 2 needed a human. 5 model calls, 1,656 tokens, 41 seconds, $0.
  • 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.
  • PR #2 stayed in the overdue list, with a ready-to-send nudge, until sonip98 reviewed it.

Prize Categories

  • Best Use of Gemma

來源:DEV Community · dev.to