<?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: Abdulaleem Zakariyah </title>
    <description>The latest articles on DEV Community by Abdulaleem Zakariyah  (@hay_43).</description>
    <link>https://dev.to/hay_43</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%2F1061051%2Fcf2ad412-017f-4964-8237-a731b342c67c.jpg</url>
      <title>DEV Community: Abdulaleem Zakariyah </title>
      <link>https://dev.to/hay_43</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hay_43"/>
    <language>en</language>
    <item>
      <title>Sloth Nap: two lines in the morning, instead of the chores you keep skipping</title>
      <dc:creator>Abdulaleem Zakariyah </dc:creator>
      <pubDate>Thu, 22 Oct 2026 20:54:59 +0000</pubDate>
      <link>https://dev.to/hay_43/sloth-nap-two-lines-in-the-morning-instead-of-the-chores-you-keep-skipping-2l92</link>
      <guid>https://dev.to/hay_43/sloth-nap-two-lines-in-the-morning-instead-of-the-chores-you-keep-skipping-2l92</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;Sloth Nap is for the evening you do not want to deal with the pile. You drop a chore table and a couple of notes into a folder. It ranks which tasks you are likely to skip again, finds the one sentence in the notes that actually has a date, looks up the question you were avoiding, and leaves two lines for the morning.&lt;/p&gt;

&lt;p&gt;On the sample pile, those lines are the receipts and a one-sentence reply to the landlord. Together they are about 55 minutes. The plants, the dentist, and the downloads folder can wait. Nothing is deleted. Copying the notes into an archive folder stays pending until a person approves it, and a second approval does not copy them again.&lt;/p&gt;

&lt;p&gt;The person who gets to be lazier is whoever keeps reopening the same three tasks and the same lease PDF. The nap does that pass once.&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;Do file the receipts and reply to the landlord. Those are the chores you keep skipping.&lt;/p&gt;

&lt;p&gt;The only sentence that matters: the lease renewal notice is due on November 2. Leave sort the downloads folder and book the dentist for later. Filing online is $30. Showing up in person is $45 and a morning.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm &lt;span class="nb"&gt;test
&lt;/span&gt;npm run nap
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;out/morning-brief.md&lt;/code&gt; is the result. &lt;code&gt;npm run nap -- --approve&lt;/code&gt; copies the notes once. &lt;code&gt;npm start&lt;/code&gt; serves those two lines on port 3000.&lt;/p&gt;
&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;MIT, on GitHub: &lt;a href="https://github.com/zakkycrypt01/sloth-nap" rel="noopener noreferrer"&gt;zakkycrypt01/sloth-nap&lt;/a&gt;&lt;/p&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/zakkycrypt01" rel="noopener noreferrer"&gt;
        zakkycrypt01
      &lt;/a&gt; / &lt;a href="https://github.com/zakkycrypt01/sloth-nap" rel="noopener noreferrer"&gt;
        sloth-nap
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &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;Sloth Nap&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;An overnight chore agent for the &lt;a href="https://dev.to/challenges/hacktoberfest-week3-2026-10-19" rel="nofollow"&gt;Hacktoberfest Week 3 challenge&lt;/a&gt;. You drop the tasks you keep avoiding into &lt;code&gt;inbox/&lt;/code&gt;. It ranks what you will skip, pulls the one date buried in the notes, looks up the question you did not want to search, and leaves two lines in &lt;code&gt;out/morning-brief.md&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On the sample inbox that is the receipts and the landlord reply: about 55 minutes. Archiving the notes waits until you approve it.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Run it&lt;/h2&gt;
&lt;/div&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm install
npm &lt;span class="pl-c1"&gt;test&lt;/span&gt;
npm run nap&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;code&gt;npm start&lt;/code&gt; serves the brief at &lt;code&gt;http://localhost:3000&lt;/code&gt;. Add &lt;code&gt;--approve&lt;/code&gt; to copy the notes into &lt;code&gt;out/archived&lt;/code&gt;. Add &lt;code&gt;--slow&lt;/code&gt; if you want a pause between steps.&lt;/p&gt;
&lt;p&gt;The sample run does not call a hosted model. If &lt;a href="https://ollama.com" rel="nofollow noopener noreferrer"&gt;Ollama&lt;/a&gt; is running with &lt;code&gt;gemma2:2b&lt;/code&gt;, the two lines come from Gemma. Otherwise a template writes them from the same facts, and the brief says &lt;code&gt;model: template&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;…
&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/zakkycrypt01/sloth-nap" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;The project is a new repo started during this challenge window. The commit on &lt;code&gt;master&lt;/code&gt; is &lt;code&gt;ddc4f5e&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;inbox/                  sample chores, lease note, question
src/mastra/             Mastra agent, forecast tool, LibSQL memory
src/nap/                brief, approval ledger, pile search, partner clients
src/temporal/           durable nap: activities, then a signal wait
python/tabpfn_forecast.py
python/tinker_eval.py
arduino/sloth_nap/      UNO Q sketch
render.yaml
deploy/digitalocean-app.yaml
.github/workflows/overnight-nap.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The archive path is the one I want a judge to look at. The intent is written as &lt;code&gt;submitted&lt;/code&gt; before the copy, then &lt;code&gt;confirmed&lt;/code&gt; after. A retry that finds &lt;code&gt;confirmed&lt;/code&gt; returns without copying. A retry that finds &lt;code&gt;submitted&lt;/code&gt; (the copy timed out) does not guess.&lt;/p&gt;

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

&lt;p&gt;The open piece at the center is &lt;a href="https://mastra.ai" rel="noopener noreferrer"&gt;Mastra&lt;/a&gt;, an open-source TypeScript agent harness. The agent is &lt;code&gt;sloth-nap&lt;/code&gt;. Its tool, &lt;code&gt;forecast-skips&lt;/code&gt;, fits a small logistic model on age, minutes, dread, and how many of the last four attempts were skipped. Memory is LibSQL. &lt;a href="https://dev.to/thegdsks/building-a-production-ai-agent-in-typescript-with-mastra-a-2026-step-by-step-37dc"&gt;GDS K S's Mastra walkthrough&lt;/a&gt; is the shape I used: an agent, a Zod tool, and memory.&lt;/p&gt;

&lt;p&gt;Gemma writes the two lines. The client posts to Ollama &lt;code&gt;/api/chat&lt;/code&gt; with &lt;code&gt;gemma2:2b&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Two other posts decided the approval design. &lt;a href="https://dev.to/obataka/building-fault-tolerant-ai-agent-workflows-with-temporal-and-crewai-3hmk"&gt;Takashi Obara's Temporal write-up&lt;/a&gt; is why the archive is a signal wait in &lt;code&gt;src/temporal/workflows.ts&lt;/code&gt; rather than a poll. &lt;a href="https://dev.to/cyclopt_dimitrisk/your-agents-retry-bug-isnt-an-ai-problem-its-a-distributed-systems-problem-with-an-llm-on-top-1i6k"&gt;The retry essay&lt;/a&gt; is why the idempotency key is stored before the copy. A commenter on that essay, &lt;a href="https://dev.to/abhinavs1920"&gt;Abhinav Sharma&lt;/a&gt;, points out that a key does nothing if the far side ignores it. Here the far side is this process, so the ledger is the far side.&lt;/p&gt;

&lt;p&gt;The workflow runs the nap, then waits on the approval signal. &lt;code&gt;python/tinker_eval.py&lt;/code&gt; trains the same kind of classifier: 0.85 on the holdout against a majority-class baseline of 0.80. &lt;code&gt;python/tabpfn_forecast.py&lt;/code&gt; is the TabPFN path for that same ranking.&lt;/p&gt;

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

&lt;p&gt;The notes in this project are a lease date and a dread score. The ranker and Gemma run on the machine, so the pile stays in the folder. Swapping the model is a name, not a new vendor. Mastra keeps the tool and the memory in an open harness.&lt;/p&gt;

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

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Chore&lt;/th&gt;
&lt;th&gt;Minutes&lt;/th&gt;
&lt;th&gt;What the nap did&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;File the receipts&lt;/td&gt;
&lt;td&gt;40&lt;/td&gt;
&lt;td&gt;Do this&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reply to the landlord&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;Do this, before November 2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sort the downloads folder&lt;/td&gt;
&lt;td&gt;25&lt;/td&gt;
&lt;td&gt;Leave it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Book the dentist&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;Leave it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Water the plants&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Leave it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Renew the library card&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;Leave it&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;About 55 minutes of the chores the model thinks you will skip. The other 48 minutes are the ones you already do. Filing the small claim online is $30. Showing up in person is $45 and a morning.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Best Use of Mastra.&lt;/strong&gt; The forecast tool, the agent, and LibSQL memory are what rank the chores. The tests construct the agent and the nap calls the tool.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>hacktoberfest</category>
      <category>ai</category>
    </item>
    <item>
      <title>Wow</title>
      <dc:creator>Abdulaleem Zakariyah </dc:creator>
      <pubDate>Sun, 04 Oct 2026 17:50:20 +0000</pubDate>
      <link>https://dev.to/hay_43/-58ek</link>
      <guid>https://dev.to/hay_43/-58ek</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/kayode96max/fixit-ai-an-open-weight-technical-troubleshooting-friend-powered-by-google-gemma-2b4h" class="crayons-story__hidden-navigation-link"&gt;FixIt AI: An Open-Weight Technical Troubleshooting Friend Powered by Google Gemma&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
      &lt;a href="https://dev.to/kayode96max/fixit-ai-an-open-weight-technical-troubleshooting-friend-powered-by-google-gemma-2b4h" class="crayons-article__context-note crayons-article__context-note__feed"&gt;&lt;p&gt;Hacktoberfest Weekend Challenge: Build for a Friend Submission 🤝&lt;/p&gt;

&lt;/a&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/kayode96max" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F3690691%2F52db3d24-ee7f-4821-846b-695bc8cb7e54.jpeg" alt="kayode96max profile" class="crayons-avatar__image" width="460" height="460"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/kayode96max" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Usman Abdullahi Olukayode
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Usman Abdullahi Olukayode
                
                
              
              &lt;div id="story-author-preview-content-4796888" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/kayode96max" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F3690691%2F52db3d24-ee7f-4821-846b-695bc8cb7e54.jpeg" class="crayons-avatar__image" alt="" width="460" height="460"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Usman Abdullahi Olukayode&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/kayode96max/fixit-ai-an-open-weight-technical-troubleshooting-friend-powered-by-google-gemma-2b4h" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Oct 4&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/kayode96max/fixit-ai-an-open-weight-technical-troubleshooting-friend-powered-by-google-gemma-2b4h" id="article-link-4796888"&gt;
          FixIt AI: An Open-Weight Technical Troubleshooting Friend Powered by Google Gemma
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/hf26challenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;hf26challenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/gemma"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;gemma&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/render"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;render&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/kayode96max/fixit-ai-an-open-weight-technical-troubleshooting-friend-powered-by-google-gemma-2b4h" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt;&amp;nbsp;reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/kayode96max/fixit-ai-an-open-weight-technical-troubleshooting-friend-powered-by-google-gemma-2b4h#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            3 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>ai</category>
      <category>llm</category>
      <category>opensource</category>
    </item>
    <item>
      <title>PyReviewer: A Production-Grade Python AST, Security &amp; Docker Reviewer for Large Codebases</title>
      <dc:creator>Abdulaleem Zakariyah </dc:creator>
      <pubDate>Sun, 04 Oct 2026 17:00:46 +0000</pubDate>
      <link>https://dev.to/hay_43/pyreviewer-a-production-grade-python-ast-security-docker-reviewer-for-large-codebases-4bn0</link>
      <guid>https://dev.to/hay_43/pyreviewer-a-production-grade-python-ast-security-docker-reviewer-for-large-codebases-4bn0</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-weekend-2026-10-01"&gt;Hacktoberfest Weekend Challenge: Build for a Friend&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;I built &lt;strong&gt;PyReviewer&lt;/strong&gt; for my close friend &lt;strong&gt;Dave&lt;/strong&gt;, a self-taught junior Python developer currently building multi-file FastAPI microservices and background data pipelines.&lt;/p&gt;

&lt;h3&gt;
  
  
  Who I Built It For: My Friend Dave
&lt;/h3&gt;

&lt;p&gt;Dave is a passionate developer, but like many juniors working across growing multi-file repositories, he continually runs into high-severity traps that are hard to catch without senior peer review:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Async Concurrency Freezes&lt;/strong&gt;: Accidentally placing synchronous blocking functions (&lt;code&gt;time.sleep()&lt;/code&gt;, &lt;code&gt;requests.get()&lt;/code&gt;) inside FastAPI &lt;code&gt;async def&lt;/code&gt; endpoints, locking Python's single-threaded event loop and stalling client requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mutable Default Leaks&lt;/strong&gt;: Using &lt;code&gt;def append_item(item, cache=[])&lt;/code&gt;, causing memory to leak and state to bleed across completely unrelated requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OWASP Security Vulnerabilities&lt;/strong&gt;: String-interpolated SQL queries (&lt;code&gt;f"SELECT * FROM users WHERE id = '{user_id}'"&lt;/code&gt;), shell command injections (&lt;code&gt;subprocess.run(..., shell=True)&lt;/code&gt;), and insecure deserialization (&lt;code&gt;pickle.loads()&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Codebase Review Fatigue&lt;/strong&gt;: Struggling to get a unified view of 30+ files across a repo, rank security hotspots, and write production-hardened Dockerfiles that don't run as root.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What PyReviewer Does For Him
&lt;/h3&gt;

&lt;p&gt;PyReviewer turns large, messy codebases into clean, production-ready systems in seconds:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Repository Scanner&lt;/strong&gt;: Dave pastes his public GitHub repository URL. PyReviewer executes a shallow clone, indexes every Python file into an interactive 3-column file tree explorer, and runs an AST security sweep.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic AST &amp;amp; Security Engine&lt;/strong&gt;: Inspects Python Abstract Syntax Trees via &lt;code&gt;ast.NodeVisitor&lt;/code&gt; for zero-day vulnerabilities, blocking async calls, and Python anti-patterns.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hotspot Ranking &amp;amp; Executive Audit Report&lt;/strong&gt;: Ranks files by risk concentration and compiles a comprehensive, downloadable Markdown audit report.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unified Refactor Diffs&lt;/strong&gt;: Generates Git-style unified diffs showing exact fixes with a 1-click "Apply Refactor" button.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Production Docker Packaging &amp;amp; Render Deployment&lt;/strong&gt;: Automatically generates a hardened multi-stage Dockerfile and a &lt;code&gt;render.yaml&lt;/code&gt; Blueprint for 1-click deployment on Render.&lt;/li&gt;
&lt;/ol&gt;




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

&lt;p&gt;PyReviewer is containerized with Docker and running live in production on Render:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🌐 &lt;strong&gt;Live Web Application&lt;/strong&gt;: &lt;a href="https://pyreviewer.onrender.com/" rel="noopener noreferrer"&gt;https://pyreviewer.onrender.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🩺 &lt;strong&gt;Production Healthcheck&lt;/strong&gt;: &lt;a href="https://pyreviewer.onrender.com/healthz" rel="noopener noreferrer"&gt;https://pyreviewer.onrender.com/healthz&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How It Works:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Paste any GitHub repository URL&lt;/strong&gt; (e.g. &lt;code&gt;https://github.com/psf/requests&lt;/code&gt; or click &lt;em&gt;"Load Demo Microservice Repo"&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;The 3-column workspace immediately opens the codebase tree, color-coded by vulnerability risk (Green = Safe, Amber = Warnings, Red = Critical Flaws).&lt;/li&gt;
&lt;li&gt;Select any file to inspect syntax-highlighted code with gutter line numbers and live diagnostic warning pills.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;"Review &amp;amp; Refactor"&lt;/strong&gt; to inspect unified diffs and one-click fixes.&lt;/li&gt;
&lt;li&gt;Switch to &lt;strong&gt;"Docker &amp;amp; Render"&lt;/strong&gt; to inspect the auto-generated multi-stage Dockerfile and one-click deploy to Render.&lt;/li&gt;
&lt;/ol&gt;




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

&lt;p&gt;PyReviewer is completely open source under the MIT License:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── Dockerfile                  # Hardened Docker container for Render (git + non-root user)
├── render.yaml                 # Render Blueprint specification
├── docker-compose.yml          # Local container orchestration
├── server.py                   # High-performance server with /healthz &amp;amp; /api/scan-repo
├── requirements.txt            # Optional production dependencies
├── .dockerignore               # Clean container exclusion rules
├── app/
│   ├── analyzer.py             # Pure Python AST NodeVisitor &amp;amp; Security Rules
│   └── repo_scanner.py         # Git shallow cloning &amp;amp; repository auditor
└── static/
    ├── index.html              # Clean 3-column repository explorer UI
    ├── style.css               # Slate/zinc high-density developer stylesheet
    └── app.js                  # File tree, diff viewer &amp;amp; report exporter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;PyReviewer is built around an open agentic harness and open-source local analysis tools:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Open-Source Agent Harness&lt;/strong&gt;: Developed collaboratively using the open Antigravity agentic harness with the DevRelay gateway, which tracked session milestones and verified architectural decisions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic AST Visitor Engine (&lt;code&gt;ast.NodeVisitor&lt;/code&gt;)&lt;/strong&gt;: Rather than relying on unreliable black-box LLMs that hallucinate syntax errors or leak source code, PyReviewer inspects the raw compiler syntax tree using Python's native &lt;code&gt;ast&lt;/code&gt; library:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;   &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PythonASTAnalyzer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NodeVisitor&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
       &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;visit_AsyncFunctionDef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AsyncFunctionDef&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
           &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;child&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;walk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
               &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Call&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                   &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_get_call_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;time.sleep&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sleep&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
                       &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                           &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;line&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lineno&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                           &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PERF-001&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                           &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Blocking Call in Async Function&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                           &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;severity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CRITICAL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                           &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Synchronous &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;()&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; blocks the event loop in &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                           &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;suggestion&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Use &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;await asyncio.sleep()&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; instead.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                       &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Multi-Stage Docker Packaging&lt;/strong&gt;:
Packaged inside a slim &lt;code&gt;python:3.12-slim&lt;/code&gt; container with &lt;code&gt;git&lt;/code&gt; and &lt;code&gt;ca-certificates&lt;/code&gt; installed so repository cloning works directly inside the container, running under non-root &lt;code&gt;appuser&lt;/code&gt; (UID 10001).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Render Infrastructure-as-Code (&lt;code&gt;render.yaml&lt;/code&gt;)&lt;/strong&gt;:
Uses a declarative Render Blueprint to configure the container web service, health checks, and port forwarding.&lt;/li&gt;
&lt;/ol&gt;


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

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Zero Intellectual Property &amp;amp; Code Leakage&lt;/strong&gt;: Dave and other developers should never have to paste proprietary codebases into closed third-party cloud LLMs where sensitive code can be retained or used for model retraining. PyReviewer runs AST analysis entirely locally on Dave's laptop or inside his own isolated Render container.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;100% Deterministic &amp;amp; Reproducible&lt;/strong&gt;: Closed AI models yield stochastic, inconsistent outputs between runs. Python's native AST engine produces identical, reproducible results every time, making it suitable for CI/CD gating and production standards.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero Inference Costs &amp;amp; Zero Latency&lt;/strong&gt;: No expensive API keys, no rate limits, and sub-20ms analysis times across dozens of files.&lt;/li&gt;
&lt;/ol&gt;


&lt;h2&gt;
  
  
  My Agent Session
&lt;/h2&gt;

&lt;p&gt;The complete end-to-end development session was captured and curated using DevRelay:&lt;/p&gt;


&lt;div class="ltag-agent-session"&gt;
  &lt;div class="agent-session-header"&gt;
    
    &lt;span class="agent-session-tool-icon-badge" title="Gemini CLI"&gt;
&lt;/span&gt;
    &lt;span class="agent-session-title"&gt;PyReviewer: Large Codebase GitHub Scanner &amp;amp; Executive Audit Reporter for Render&lt;/span&gt;
  &lt;/div&gt;

  &lt;div class="agent-session-scroll"&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Make it suitable for large codebase where the user can just paste in the GitHub URL, it populates the codebase, and scans and writes a detailed report.&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;We expanded PyReviewer into a full repository-scale code auditor. We added a shallow git cloning engine with ast.NodeVisitor traversal that maps entire GitHub codebases into an interactive file tree, ranks risk hotspots, and generates an audit-grade Markdown report with multi-stage Dockerfile and render.yaml blueprints.&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-scanrepository"&gt;scan_repository&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;https://github.com/bottlepy/bottle&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;https://github.com/bottlepy/bottle&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;Scanned 30 files, 7,492 LOC in under 5 seconds with zero cloud leakage.&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
  &lt;/div&gt;

  &lt;div class="agent-session-footer"&gt;
    &lt;span class="agent-session-meta"&gt;
        2 of 2 messages
    &lt;/span&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;&lt;em&gt;(View the complete transcript on &lt;a href="https://dev.to/agent_sessions/pyreviewer-large-codebase-github-scanner-executive-audit-reporter-for-render-rri07z"&gt;DevRelay Agent Session #470&lt;/a&gt;.)&lt;/em&gt;&lt;/p&gt;




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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Render ($200 Featured Category)&lt;/strong&gt;:
PyReviewer is deployed in production as a Docker web service on Render at &lt;a href="https://pyreviewer.onrender.com/" rel="noopener noreferrer"&gt;https://pyreviewer.onrender.com/&lt;/a&gt;. It features native &lt;code&gt;/healthz&lt;/code&gt; health check monitoring, a production Dockerfile with non-root security isolation, and a declarative &lt;code&gt;render.yaml&lt;/code&gt; Blueprint for 1-click zero-downtime deployment.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
      <category>hf26challenge</category>
      <category>render</category>
    </item>
  </channel>
</rss>
