<?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: Praveen Kumar</title>
    <description>The latest articles on DEV Community by Praveen Kumar (@praveen_kumar_50c9892727f).</description>
    <link>https://dev.to/praveen_kumar_50c9892727f</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%2F4165988%2Fc0c1ea10-a1a6-4d6e-994e-56d04d66c5f7.png</url>
      <title>DEV Community: Praveen Kumar</title>
      <link>https://dev.to/praveen_kumar_50c9892727f</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/praveen_kumar_50c9892727f"/>
    <language>en</language>
    <item>
      <title>PixelBreak: I Built a Local-First Tool That Blocks Bad Commits Before They Break Your Frontend</title>
      <dc:creator>Praveen Kumar</dc:creator>
      <pubDate>Fri, 23 Oct 2026 15:03:52 +0000</pubDate>
      <link>https://dev.to/praveen_kumar_50c9892727f/pixelbreak-i-built-a-local-first-tool-that-blocks-bad-commits-before-they-break-your-frontend-569m</link>
      <guid>https://dev.to/praveen_kumar_50c9892727f/pixelbreak-i-built-a-local-first-tool-that-blocks-bad-commits-before-they-break-your-frontend-569m</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;&lt;strong&gt;PixelBreak&lt;/strong&gt; is a pre-commit hook + CLI tool that automatically catches responsive layout failures and visual regressions before they land in your repo — without any manual steps, subscriptions, or cloud services.&lt;/p&gt;

&lt;p&gt;Every time you &lt;code&gt;git commit&lt;/code&gt;, PixelBreak:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Scans your running app at every configured viewport width (375px → 1920px) using a real Chromium browser&lt;/li&gt;
&lt;li&gt;Detects horizontal overflow and element clipping with deterministic pixel measurements&lt;/li&gt;
&lt;li&gt;Compares screenshots against the previous committed version automatically — no manual baseline setup&lt;/li&gt;
&lt;li&gt;Blocks the commit if anything breaks and opens a localhost dashboard showing exactly what changed&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Who gets to be lazier:&lt;/strong&gt; frontend developers who used to manually resize their browser at 5+ widths after every CSS change, or pay for Percy/Chromatic subscriptions. With PixelBreak, you just commit. The tool does the rest.&lt;/p&gt;




&lt;h2&gt;
  
  
  Demo
&lt;/h2&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%2Fl440mbnbpwoflw9vuwsz.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%2Fl440mbnbpwoflw9vuwsz.png" alt="PixelBreak Dashboard — BLOCKED with 6 findings across 6 viewports" width="800" height="500"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;PixelBreak Dashboard — 6 findings blocked across 375px, 768px, 1024px, 1280px, 1440px, 1920px&lt;/em&gt;&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%2Fusv8f83r2uz35o586tmh.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%2Fusv8f83r2uz35o586tmh.png" alt="PixelBreak visual diff — Baseline vs Current vs Diff overlay" width="800" height="500"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Visual regression finding — Baseline (before), Current (after your change), Diff (changed pixels highlighted)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Since PixelBreak is a local-first tool, here's what a real terminal run looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Developer changes a CSS variable and tries to commit&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"style: update primary color"&lt;/span&gt;

&lt;span class="c"&gt;# PixelBreak fires automatically&lt;/span&gt;
🔍 &lt;span class="o"&gt;[&lt;/span&gt;PixelBreak] Running pre-commit checks...
🚀 Starting scan &lt;span class="k"&gt;for &lt;/span&gt;project &lt;span class="s1"&gt;'my-app'&lt;/span&gt;...
   Base URL: http://localhost:4173
   Profile:  responsive
   Widths:   &lt;span class="o"&gt;[&lt;/span&gt;375, 768, 1024, 1280, 1440, 1920]px
   Git baseline: 1 staged file&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; detected — comparing against HEAD automatically.

📊 Scan Complete: 6 viewports, 8 findings

  🚨 BLOCKED &lt;span class="o"&gt;[&lt;/span&gt;HIGH] horizontal-overflow @ 375px
     Element: &lt;span class="c"&gt;#metrics-card overflows viewport by 857px&lt;/span&gt;

  🚨 BLOCKED &lt;span class="o"&gt;[&lt;/span&gt;HIGH] horizontal-overflow @ 768px
     Element: &lt;span class="c"&gt;#metrics-card overflows viewport by 464px&lt;/span&gt;

  🚨 BLOCKED &lt;span class="o"&gt;[&lt;/span&gt;MODERATE] visual-regression @ 1024px
     0.09% pixel diff — 787 pixels changed

❌ Commit Gate: BLOCKED
   Dashboard: http://localhost:3847
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Clone and try it yourself:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/praveen-pravi6B/pixelbreak
&lt;span class="nb"&gt;cd &lt;/span&gt;pixelbreak &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pnpm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pnpm build
pnpm demo
node apps/runner/dist/cli.js init
node apps/runner/dist/cli.js baseline update
&lt;span class="c"&gt;# Change fixtures/broken-demo/src/style.css and commit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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/praveen-pravi6B" rel="noopener noreferrer"&gt;
        praveen-pravi6B
      &lt;/a&gt; / &lt;a href="https://github.com/praveen-pravi6B/pixelbreak" rel="noopener noreferrer"&gt;
        pixelbreak
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Local-first frontend regression testing — responsive breakpoint detection, visual diffs, and local AI explanations. Blocks bad commits before they ship.
    &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;PixelBreak&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Local-first responsive breakpoint detection and visual regression testing — no cloud, no account, no drama.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;PixelBreak checks your frontend before every Git commit. It tests only the viewport widths you configure, detects layout failures and visual regressions, shows evidence in a localhost dashboard, and uses a local LLM to explain issues and suggest CSS fixes — without sending your source code or screenshots to any cloud service.&lt;/p&gt;




&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why PixelBreak?&lt;/h2&gt;
&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Find where it breaks.&lt;/strong&gt; Deterministic horizontal-overflow and layout-clipping detection at exactly the breakpoints your app supports.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;See what changed.&lt;/strong&gt; Pixel-level screenshot diffs with bounding-box evidence and diff overlays.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Understand the cause.&lt;/strong&gt; A local LLM explains findings and proposes CSS patches — all on your machine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Block bad commits.&lt;/strong&gt; A severity-gated pre-commit hook stops high and critical regressions before they land.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stay private.&lt;/strong&gt; Zero telemetry. Zero cloud calls. No API key required.&lt;/li&gt;
&lt;/ul&gt;




&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Core Modules&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;&lt;div class="table-wrapper-paragraph"&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;table&gt;

&lt;thead&gt;

&lt;tr&gt;

&lt;th&gt;Module&lt;/th&gt;

&lt;th&gt;What it does&lt;/th&gt;

&lt;/tr&gt;

&lt;/thead&gt;

&lt;tbody&gt;

&lt;tr&gt;

&lt;td&gt;&lt;strong&gt;Breakpoint Detective&lt;/strong&gt;&lt;/td&gt;

&lt;td&gt;Configured&lt;/td&gt;

&lt;/tr&gt;

&lt;/tbody&gt;

&lt;/table&gt;&lt;/div&gt;…&lt;p&gt;&lt;/p&gt;&lt;/div&gt;
&lt;br&gt;
  &lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/praveen-pravi6B/pixelbreak" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;





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

&lt;p&gt;&lt;strong&gt;Open-source AI:&lt;/strong&gt; &lt;a href="https://github.com/ggml-org/llama.cpp" rel="noopener noreferrer"&gt;llama.cpp&lt;/a&gt; running &lt;strong&gt;Qwen2.5-Coder-Instruct&lt;/strong&gt; (GGUF, Q4_K_M quantization) locally on port 8080. No API key, no cloud, no bundled weights.&lt;/p&gt;

&lt;p&gt;The AI is the explanation layer — not the detection layer. Detection is fully deterministic:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Detection (no AI involved):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;@pixelbreak/layout-analyzer&lt;/code&gt; — injects JavaScript into Playwright pages to measure &lt;code&gt;scrollWidth &amp;gt; clientWidth&lt;/code&gt; and element clipping geometry&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@pixelbreak/visual-diff&lt;/code&gt; — uses &lt;code&gt;pixelmatch&lt;/code&gt; to compare screenshots pixel-by-pixel and generate diff PNGs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;AI layer (llama.cpp + Qwen2.5-Coder):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;After deterministic detection blocks a commit, the AI receives: finding summary, measured pixel geometry, relevant computed CSS&lt;/li&gt;
&lt;li&gt;Returns structured JSON: summary, likely cause, supporting evidence, and a CSS patch proposal&lt;/li&gt;
&lt;li&gt;All responses are validated with a Zod schema — malformed output is rejected, never silently accepted&lt;/li&gt;
&lt;li&gt;The model &lt;strong&gt;cannot&lt;/strong&gt; change severity, waive findings, or apply patches. &lt;code&gt;severity: finding.severity&lt;/code&gt; is copied from the finding object, never from the AI response.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Git-aware automatic baselines:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The most important UX decision: instead of requiring &lt;code&gt;pixelbreak baseline update&lt;/code&gt; before every scan, PixelBreak uses &lt;code&gt;git show HEAD:&amp;lt;file&amp;gt;&lt;/code&gt; to automatically get the previous version of staged files as the baseline. You just commit — no manual setup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stack:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;pnpm workspaces monorepo (TypeScript, ESM throughout)&lt;/li&gt;
&lt;li&gt;Playwright for Chromium automation&lt;/li&gt;
&lt;li&gt;pixelmatch for pixel comparison&lt;/li&gt;
&lt;li&gt;Zod for all schema validation&lt;/li&gt;
&lt;li&gt;Commander.js for CLI&lt;/li&gt;
&lt;li&gt;React + Vite for the localhost dashboard&lt;/li&gt;
&lt;li&gt;Node.js built-in &lt;code&gt;http&lt;/code&gt; for the dashboard server (no Express)&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;I could have built this on Percy, Chromatic, or the Applitools API. But every hosted visual regression tool:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sends your screenshots to their servers — a non-starter for internal dashboards, confidential UIs, or enterprise apps&lt;/li&gt;
&lt;li&gt;Requires a subscription — free tiers run out, pricing changes, vendor disappears&lt;/li&gt;
&lt;li&gt;Locks you into their severity rules — you file a ticket if you disagree&lt;/li&gt;
&lt;li&gt;Breaks when you're offline or behind a corporate firewall&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Open innovation made this possible in four concrete ways:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The AI runs on your hardware.&lt;/strong&gt; Qwen2.5-Coder-Instruct via llama.cpp — download once, run forever, cost $0. No API key. No data leaving your machine. A team building a hospital admin panel can use PixelBreak without worrying about screenshots of patient data touching a third-party server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. You own the severity rules.&lt;/strong&gt; The policy engine is a configurable YAML file. If your team disagrees with how a 0.08% pixel diff is classified, you change &lt;code&gt;.pixelbreak.yml&lt;/code&gt;. No support ticket.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. You can audit everything.&lt;/strong&gt; When a security review found 9 vulnerabilities in my own code (command injection, path traversal, prototype pollution via YAML), I could read the exact lines, understand the attack vectors, fix them, and write tests that prove they're fixed. That's not possible with a black-box SaaS.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. No lock-in by design.&lt;/strong&gt; The AI adapter speaks the OpenAI-compatible &lt;code&gt;/v1/chat/completions&lt;/code&gt; API. Swap llama.cpp for Ollama, LM Studio, or any future local inference server — zero code changes.&lt;/p&gt;




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

&lt;p&gt;Built with Claude Code across two sessions — foundation phases on a personal machine, AI engine + dashboard + security hardening in this session:&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="Claude Code"&gt;
&lt;/span&gt;
    &lt;span class="agent-session-title"&gt;PixelBreak: Building a Local-First Frontend Regression Tool for Hacktoberfest 2026&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;Clone praveen-pravi6B/pixelbreak, add README, check CONTRIBUTORS.md, LICENSE already exists. Check planner file and implementation summary, then plan and execute. Switch to personal GitHub profile first.&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-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;gh auth switch --user praveen-pravi6B&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 agent-session-terminal"&gt;&lt;code&gt;$ gh auth switch --user praveen-pravi6B&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;Switched active account to praveen-pravi6B&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&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-read"&gt;Read&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;IMPLEMENTATION_STATUS.md&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 highlight markdown"&gt;&lt;code&gt;IMPLEMENTATION_STATUS.md&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 highlight markdown"&gt;&lt;code&gt;Phase A-D complete. Phase E (Local AI), F (Dashboard), G (Release Readiness) pending. 25 tests passing.&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Switched to personal profile. Repo has Phases A-D complete (Foundation, Breakpoint Detective, PixelTruth, Policy Engine). Missing: README, CONTRIBUTING, CONTRIBUTORS, THIRD_PARTY_NOTICES, ai-engine package, dashboard app.&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&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;Switch to plan mode — full check then tell me.&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;Explored the full monorepo with 3 parallel agents.&lt;/p&gt;

&lt;p&gt;Missing files: README.md, CONTRIBUTING.md, CONTRIBUTORS.md, THIRD_PARTY_NOTICES.md&lt;br&gt;
Missing packages: packages/ai-engine/, apps/dashboard/&lt;br&gt;
Phases A-D complete: 6 packages, 1 CLI app, 25 tests&lt;/p&gt;

&lt;p&gt;Hacktoberfest Week 3 deadline: October 25 2026. Theme: Slow and Steady — open-source AI that rewards laziness/automates tedious tasks.&lt;/p&gt;

&lt;p&gt;4-day plan:&lt;br&gt;
- Day 1: Documentation files&lt;br&gt;
- Day 2: Phase E — packages/ai-engine/ (llama.cpp adapter)&lt;br&gt;
- Day 3: Phase F — apps/dashboard/ (React + Vite)&lt;br&gt;
- Day 4: Phase G — docs, verification, DEV post&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&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;Plan approved — execute.&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-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;README.md — 11.5KB comprehensive guide&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 highlight markdown"&gt;&lt;code&gt;README.md — 11.5KB comprehensive guide&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 highlight markdown"&gt;&lt;code&gt;Created: product overview, CLI reference, severity policy, local AI setup, waiver system, privacy section&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&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-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;CONTRIBUTING.md, CONTRIBUTORS.md, THIRD_PARTY_NOTICES.md&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;CONTRIBUTING.md, CONTRIBUTORS.md, THIRD_PARTY_NOTICES.md&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;All created with correct content&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Day 1 complete. Starting Phase E — Local AI Engine.&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&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;Start Phase E.&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;Building packages/ai-engine/ — llama.cpp HTTP adapter.&lt;/p&gt;

&lt;p&gt;Key design constraints:&lt;br&gt;
- Connects ONLY to local llama.cpp endpoint (&lt;a href="http://localhost:8080" rel="noopener noreferrer"&gt;http://localhost:8080&lt;/a&gt;)&lt;br&gt;
- AI CANNOT change severity, waive findings, update baselines, or apply patches&lt;br&gt;
- All output tagged isHypothesis: true&lt;br&gt;
- Patch proposals are previews — never auto-applied&lt;br&gt;
- If model unavailable: clear error, no silent pass&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-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;packages/ai-engine/src/types.ts&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 highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;packages&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&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 highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;AiExplanation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PatchProposal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;AiStatus&lt;/span&gt; &lt;span class="nx"&gt;types&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="nx"&gt;isHypothesis&lt;/span&gt; &lt;span class="nx"&gt;always&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&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-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;packages/ai-engine/src/prompts.ts&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 highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;packages&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;prompts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&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 highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;SYSTEM_PROMPT&lt;/span&gt; &lt;span class="nx"&gt;enforcing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cannot&lt;/span&gt; &lt;span class="nx"&gt;change&lt;/span&gt; &lt;span class="nx"&gt;severity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cannot&lt;/span&gt; &lt;span class="nx"&gt;waive&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cannot&lt;/span&gt; &lt;span class="nx"&gt;auto&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;apply&lt;/span&gt; &lt;span class="nx"&gt;patches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nf"&gt;buildExplanationPrompt&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;sends&lt;/span&gt; &lt;span class="nx"&gt;minimum&lt;/span&gt; &lt;span class="nx"&gt;evidence&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&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-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;packages/ai-engine/src/validator.ts&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 highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;packages&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&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 highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Zod&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt; &lt;span class="nx"&gt;AiExplanationResponseSchema&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="nx"&gt;rejects&lt;/span&gt; &lt;span class="nx"&gt;malformed&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;missing&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;empty&lt;/span&gt; &lt;span class="nx"&gt;strings&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&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-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;packages/ai-engine/src/adapter.ts&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 highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;packages&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;adapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&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 highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;LlamaCppAdapter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;checkStatus&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;explainFinding&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt; &lt;span class="nx"&gt;Uses&lt;/span&gt; &lt;span class="nx"&gt;execFileSync&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt; &lt;span class="nf"&gt;args &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;no&lt;/span&gt; &lt;span class="nx"&gt;shell&lt;/span&gt; &lt;span class="nx"&gt;injection&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt; &lt;span class="nx"&gt;AiUnavailableError&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;AiResponseError&lt;/span&gt; &lt;span class="nx"&gt;custom&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="nx"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&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-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;packages/ai-engine/test/ai-engine.test.ts&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 highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;packages&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&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 highlight typescript"&gt;&lt;code&gt;&lt;span class="mi"&gt;14&lt;/span&gt; &lt;span class="nx"&gt;unit&lt;/span&gt; &lt;span class="nx"&gt;tests&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;valid&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="nx"&gt;parsing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="nx"&gt;patch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;non&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt; &lt;span class="nx"&gt;rejection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt; &lt;span class="nx"&gt;validation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;AiUnavailableError&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt; &lt;span class="nx"&gt;ECONNREFUSED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;severity&lt;/span&gt; &lt;span class="nx"&gt;immutability&lt;/span&gt; &lt;span class="nx"&gt;verified&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;empty&lt;/span&gt; &lt;span class="nx"&gt;choices&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HTTP&lt;/span&gt; &lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&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-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;pnpm test&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 agent-session-terminal"&gt;&lt;code&gt;$ pnpm test&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;44/44 tests passing&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&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;Start Phase F.&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;Building apps/dashboard/ (React + Vite) + report persistence + HTTP server.&lt;/p&gt;

&lt;p&gt;Architecture:&lt;br&gt;
- report-store.ts: saves ScanReport JSON to .pixelbreak/reports/&lt;br&gt;
- dashboard-server.ts: Node.js http module server port 3847 (no Express)&lt;br&gt;
- React app fetches /api/reports/latest on load&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-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;apps/dashboard/src/components/ScanSummary.tsx&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 highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;apps&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;dashboard&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;ScanSummary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tsx&lt;/span&gt;&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 highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;PASS&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;BLOCK&lt;/span&gt; &lt;span class="nx"&gt;banner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Blocked&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;Waived&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;Allowed&lt;/span&gt; &lt;span class="nx"&gt;counts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;severity&lt;/span&gt; &lt;span class="nx"&gt;pips&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&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-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;apps/dashboard/src/components/FindingDetail.tsx&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 highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;apps&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;dashboard&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;FindingDetail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tsx&lt;/span&gt;&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 highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;Baseline&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;Current&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;Diff&lt;/span&gt; &lt;span class="nx"&gt;screenshots&lt;/span&gt; &lt;span class="nx"&gt;side&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;by&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;side&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;evidence&lt;/span&gt; &lt;span class="nx"&gt;geometry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;computed&lt;/span&gt; &lt;span class="nx"&gt;CSS&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&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-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;apps/dashboard/src/components/AiPanel.tsx&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 highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;apps&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;dashboard&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;AiPanel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tsx&lt;/span&gt;&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 highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;HYPOTHESIS&lt;/span&gt; &lt;span class="nx"&gt;NOT&lt;/span&gt; &lt;span class="nx"&gt;VERIFIED&lt;/span&gt; &lt;span class="nx"&gt;banner&lt;/span&gt; &lt;span class="nx"&gt;always&lt;/span&gt; &lt;span class="nx"&gt;shown&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;Summary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cause&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;evidence&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;limitations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&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-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;apps/dashboard/src/components/PatchReview.tsx&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 highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;apps&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;dashboard&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;PatchReview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tsx&lt;/span&gt;&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 highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;Diff&lt;/span&gt; &lt;span class="nx"&gt;syntax&lt;/span&gt; &lt;span class="nx"&gt;highlighting&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;copy&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;clipboard&lt;/span&gt; &lt;span class="nx"&gt;only&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="nx"&gt;never&lt;/span&gt; &lt;span class="nx"&gt;writes&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&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-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;apps/dashboard/src/components/WaiverFlow.tsx&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 highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;apps&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;dashboard&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;WaiverFlow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tsx&lt;/span&gt;&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 highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;Generates&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pixelbreak&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;waivers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yml&lt;/span&gt; &lt;span class="nx"&gt;YAML&lt;/span&gt; &lt;span class="nx"&gt;snippet&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="nx"&gt;copies&lt;/span&gt; &lt;span class="nx"&gt;manually&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dashboard&lt;/span&gt; &lt;span class="nx"&gt;never&lt;/span&gt; &lt;span class="nx"&gt;writes&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&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-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;pnpm build &amp;amp;&amp;amp; pnpm test&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 agent-session-terminal"&gt;&lt;code&gt;$ pnpm build &amp;amp;&amp;amp; pnpm test&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;All 10 packages built. 44/44 tests pass.&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&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;Start Phase G.&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-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;docs/local-model-setup.md&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 highlight markdown"&gt;&lt;code&gt;docs/local-model-setup.md&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 highlight markdown"&gt;&lt;code&gt;llama.cpp install, Qwen2.5-Coder GGUF download, server startup, hardware requirements, troubleshooting&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&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-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;docs/configuration.md&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 highlight markdown"&gt;&lt;code&gt;docs/configuration.md&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 highlight markdown"&gt;&lt;code&gt;Full .pixelbreak.yml field reference&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&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-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;docs/severity-policy.md&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 highlight markdown"&gt;&lt;code&gt;docs/severity-policy.md&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 highlight markdown"&gt;&lt;code&gt;Severity thresholds, commit gate logic, waiver rules, AI constraints table&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&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-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;docs/privacy.md&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 highlight markdown"&gt;&lt;code&gt;docs/privacy.md&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 highlight markdown"&gt;&lt;code&gt;What stays local, what is never transmitted, local AI data flow&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&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-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;pnpm build &amp;amp;&amp;amp; pnpm test&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 agent-session-terminal"&gt;&lt;code&gt;$ pnpm build &amp;amp;&amp;amp; pnpm test&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;Test Files 10 passed. Tests 44 passed. Duration 20.96s&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&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;Try test cases: multiple cases and execute them.&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&gt;
                  &lt;div class="agent-session-text agent-session-text-collapse"&gt;
                    &lt;p&gt;Running 5 test cases:&lt;/p&gt;

&lt;p&gt;Case 1: JS comment change — git baseline detects no visual impact → BLOCKED by pre-existing overflow only (no visual regression reported)&lt;/p&gt;

&lt;p&gt;Case 2: CSS color change #6366f1 → #e11d48 — 8 findings: HIGH overflow at 375/768/1024px + MODERATE visual-regression at 5 viewports → BLOCKED&lt;/p&gt;

&lt;p&gt;Case 3: Fix overflow (flex-wrap: wrap) — overflow fixed but visual regression HIGH (layout shifted &amp;gt;3%) → still BLOCKED&lt;/p&gt;

&lt;p&gt;Case 4: Full fix + intentional layout approval → BYPASS commit, then:&lt;/p&gt;

&lt;p&gt;Case 5: Non-visual JS change on fixed app — 0 findings → PASS ✅&lt;/p&gt;

&lt;p&gt;Key insight: git-aware baseline correctly distinguishes JS-only changes from CSS/visual changes without any manual baseline update step.&lt;/p&gt;

                  &lt;/div&gt;
                  Show more
                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&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;Security review — I want this safe before publishing as a package.&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;Full security audit found 9 vulnerabilities. Fixed all:&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-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;apps/runner/src/git-baseline.ts&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 highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;apps&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;runner&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;git&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;baseline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&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 highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;CRITICAL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;execSync&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="nx"&gt;interpolation&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="nx"&gt;execFileSync&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt; &lt;span class="nf"&gt;args &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;command&lt;/span&gt; &lt;span class="nx"&gt;injection&lt;/span&gt; &lt;span class="nx"&gt;prevention&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt; &lt;span class="nx"&gt;CRITICAL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;per&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="nx"&gt;restoration&lt;/span&gt; &lt;span class="nx"&gt;guarantee&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;withHeadVersions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;HIGH&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;skip&lt;/span&gt; &lt;span class="nx"&gt;symlinks&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="nx"&gt;MB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&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-edit"&gt;Edit&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;apps/runner/src/dashboard-server.ts&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 highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;apps&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;runner&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;dashboard&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&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 highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;CRITICAL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="nx"&gt;traversal&lt;/span&gt; &lt;span class="nx"&gt;fix&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="nx"&gt;relative&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;outputDir&lt;/span&gt; &lt;span class="nx"&gt;not&lt;/span&gt; &lt;span class="nx"&gt;CWD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;Reject&lt;/span&gt; &lt;span class="nx"&gt;symlinks&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;artifact&lt;/span&gt; &lt;span class="nx"&gt;serving&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&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-edit"&gt;Edit&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;apps/runner/src/cli.ts&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 highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;apps&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;runner&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;cli&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&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 highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;HIGH&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;exec &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shell&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="nx"&gt;execFile&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;openBrowser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;Init&lt;/span&gt; &lt;span class="nx"&gt;command&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="nx"&gt;auto&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;adds&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pixelbreak&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gitignore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&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-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;packages/policy-engine/src/waivers.ts&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 highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;packages&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;waivers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&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 highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;HIGH&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Zod&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strict&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt; &lt;span class="nx"&gt;rejects&lt;/span&gt; &lt;span class="nx"&gt;__proto__&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt; &lt;span class="nf"&gt;keys &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt; &lt;span class="nx"&gt;pollution&lt;/span&gt; &lt;span class="nx"&gt;prevention&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&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-edit"&gt;Edit&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;packages/config/src/loader.ts&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 highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;packages&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&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 highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;HIGH&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="nx"&gt;validated&lt;/span&gt; &lt;span class="nx"&gt;within&lt;/span&gt; &lt;span class="nx"&gt;project&lt;/span&gt; &lt;span class="nf"&gt;directory &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="nx"&gt;traversal&lt;/span&gt; &lt;span class="nx"&gt;prevention&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&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-edit"&gt;Edit&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;apps/runner/src/scanner.ts&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 highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;apps&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;runner&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;scanner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&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 highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;HIGH&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;goto&lt;/span&gt; &lt;span class="nx"&gt;throws&lt;/span&gt; &lt;span class="nx"&gt;loudly&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt; &lt;span class="nx"&gt;unreachable&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;Empty&lt;/span&gt; &lt;span class="nx"&gt;widths&lt;/span&gt; &lt;span class="nx"&gt;guard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="nx"&gt;min&lt;/span&gt; &lt;span class="nx"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;Random&lt;/span&gt; &lt;span class="nx"&gt;scan&lt;/span&gt; &lt;span class="nx"&gt;ID&lt;/span&gt; &lt;span class="nx"&gt;suffix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&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-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;pnpm test&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 agent-session-terminal"&gt;&lt;code&gt;$ pnpm test&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;Test Files 14 passed. Tests 84 passed. 0 failed.&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&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;PixelBreak complete and published to GitHub.&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/praveen-pravi6B/pixelbreak" rel="noopener noreferrer"&gt;https://github.com/praveen-pravi6B/pixelbreak&lt;/a&gt;&lt;br&gt;
Tests: 84/84 passing&lt;br&gt;
Security: 9 vulnerabilities fixed (3 CRITICAL, 6 HIGH)&lt;br&gt;
CI: Build + Test + Size Labeler + Security Audit all passing&lt;br&gt;
Branch protection: PRs required, owner bypass enabled&lt;br&gt;
Deadline: October 25 2026&lt;/p&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;
        17 of 12 messages
    &lt;/span&gt;
  &lt;/div&gt;
&lt;/div&gt;





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

&lt;p&gt;Before PixelBreak, a developer changing a CSS file would need to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open browser dev tools → resize to 375px → does it look right? (memory-based)&lt;/li&gt;
&lt;li&gt;Resize to 768px → check again&lt;/li&gt;
&lt;li&gt;Resize to 1024px → check again&lt;/li&gt;
&lt;li&gt;Resize to 1280px, 1440px, 1920px → check, check, check&lt;/li&gt;
&lt;li&gt;Compare visually against "what it looked like before" → impossible from memory&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Time per CSS change: 5–10 minutes if done properly. Realistically: skipped 90% of the time.&lt;/p&gt;

&lt;p&gt;With PixelBreak: 0 extra minutes. The commit either goes through or it doesn't.&lt;/p&gt;

&lt;p&gt;During this week's build, PixelBreak caught:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;min-width: 1200px&lt;/code&gt; on a flex container that caused &lt;strong&gt;857px overflow at 375px&lt;/strong&gt; — completely broken on mobile, would have shipped&lt;/li&gt;
&lt;li&gt;A color variable change creating &lt;strong&gt;787 changed pixels&lt;/strong&gt; at 1024px — would have passed code review unnoticed&lt;/li&gt;
&lt;li&gt;A table that overflowed at 375px when the metrics container was fixed — a bug &lt;em&gt;introduced by fixing another bug&lt;/em&gt;, caught automatically&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Community Wisdom: &lt;a href="https://dev.to/therizwansaleem/visual-regression-testing-for-modern-web-apps-strategies-tooling-and-a-practical-pipeline-124j"&gt;Visual regression testing for modern web apps&lt;/a&gt; by Rizwan Saleem — the hosted tool landscape that shaped the decision to go local-first.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>hf26challenge</category>
      <category>hacktoberfest</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
    <item>
      <title>MailMate AI Desktop — Open-Source Email Assistant That Summarizes, Prioritizes, and Creates Tasks Locally</title>
      <dc:creator>Praveen Kumar</dc:creator>
      <pubDate>Sat, 17 Oct 2026 06:50:20 +0000</pubDate>
      <link>https://dev.to/praveen_kumar_50c9892727f/mailmate-ai-desktop-open-source-email-assistant-that-summarizes-prioritizes-and-creates-tasks-i73</link>
      <guid>https://dev.to/praveen_kumar_50c9892727f/mailmate-ai-desktop-open-source-email-assistant-that-summarizes-prioritizes-and-creates-tasks-i73</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week2-2026-10-12"&gt;Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;Most people manage their inbox by reading every email and deciding what matters. That's the problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MailMate AI Desktop&lt;/strong&gt; flips this: two open-weight models read your Gmail first, summarize every email into 1–2 sentences, classify it by priority, and deliver only what needs your attention — directly to your Telegram. Your data never leaves your machine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Who would pay for this:&lt;/strong&gt; Freelancers, consultants, indie founders, and anyone whose inbox is a productivity tax. A tool that reads 80 emails and surfaces the 3 that matter — with context — is easily worth $10–20/month. The local-first approach makes it viable for anyone who can't feed client emails to a cloud API.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Pipeline
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Gmail (read-only)
  → Normalize email
  → Qwen2.5-0.5B via vLLM   ← summarize to 1-2 sentences  (local, free)
  → Laya typed-decision engine ← classify actionability + priority  (local CPU)
  → Application-side policy  ← decide what is permitted
  → SQLite                   ← persist if approved
  → Telegram bot             ← summary + notification / Yes/No confirmation
  → Google Calendar          ← separate explicit step, never automatic
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Two open-weight models, two jobs:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Job&lt;/th&gt;
&lt;th&gt;Runs on&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Qwen/Qwen2.5-0.5B-Instruct&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Summarize each email into 1–2 sentences&lt;/td&gt;
&lt;td&gt;Local vLLM (CPU)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;convaiinnovations/laya&lt;/code&gt; (typed-decisions)&lt;/td&gt;
&lt;td&gt;Classify actionability + priority&lt;/td&gt;
&lt;td&gt;Local CPU&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The summarizer runs first. Laya then classifies the &lt;em&gt;summary&lt;/em&gt; — not the raw email. Cleaner signal, better decisions.&lt;/p&gt;


&lt;h2&gt;
  
  
  Priority System
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Priority&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;th&gt;What happens&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;🔴 P0&lt;/td&gt;
&lt;td&gt;Critical incident / immediate risk&lt;/td&gt;
&lt;td&gt;Task created automatically&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🟠 P1&lt;/td&gt;
&lt;td&gt;Important with a clear deadline&lt;/td&gt;
&lt;td&gt;Asks for your confirmation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🟡 P2&lt;/td&gt;
&lt;td&gt;Routine actionable&lt;/td&gt;
&lt;td&gt;Asks for your confirmation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⚪ OTHER&lt;/td&gt;
&lt;td&gt;Informational&lt;/td&gt;
&lt;td&gt;Summary only&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Key safety rule:&lt;/strong&gt; A model prediction alone never authorises anything. An explicit policy module enforces the rules: ambiguous deadlines are never auto-scheduled, P1/P2 tasks require your confirmation, calendar events are always a separate explicit step.&lt;/p&gt;


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

&lt;p&gt;&lt;strong&gt;Step 1 — Bot starts up, /start shows the full priority system:&lt;/strong&gt;&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%2Fyoemspga68wty6nmffc3.jpg" 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%2Fyoemspga68wty6nmffc3.jpg" alt="MailMate AI /start welcome message showing P0 auto-creates tasks, P1/P2 ask confirmation, OTHER summarizes only, with available commands listed" width="800" height="1772"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2 — First Gmail poll: 10 real inbox emails summarized and classified. AI-generated summary shown for each email. Footer: "Processed 10 emails — no tasks":&lt;/strong&gt;&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%2F8liyd7db5i3q7mqflxfw.jpg" 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%2F8liyd7db5i3q7mqflxfw.jpg" alt="MailMate AI Email Summary showing inbox emails grouped under Updates, each with priority label and AI-generated summary in italics. Processed 10 emails — no tasks." width="800" height="1772"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3 — User sends /poll from Telegram after new test emails arrive. Bot responds immediately: "Polling Gmail now...":&lt;/strong&gt;&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%2Fsileih8oou49v1ursgdo.jpg" 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%2Fsileih8oou49v1ursgdo.jpg" alt="Bottom of email summary batch visible, user sends /poll, bot responds Polling Gmail now..." width="800" height="1772"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4 — /poll results. P0 critical security breach: task created automatically + Google Calendar event scheduled at 09:00 IST. P1 design review: AI summary shown, deadline extracted, Yes/No confirmation buttons appear:&lt;/strong&gt;&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%2Ft4blhvy2dtkll7kgkt4a.jpg" 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%2Ft4blhvy2dtkll7kgkt4a.jpg" alt="P0 Security breach task auto-created with calendar event. P1 Design review showing AI-generated summary, deadline 2026-10-28, and Yes create task / No skip buttons" width="800" height="1772"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5 — User clicks "Yes, create task". Task confirmed instantly. Google Calendar event created for P1 at 09:00 IST on 2026-10-28:&lt;/strong&gt;&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%2Fmcz1hvkc9wfsio7xxbmm.jpg" 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%2Fmcz1hvkc9wfsio7xxbmm.jpg" alt="Task confirmed message for P1 Design review. Calendar event created at 09:00 IST on 2026-10-28 shown immediately after confirmation" width="800" height="1772"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 6 — Full batch summary for the /poll run. Important/Tasks section shows P0 (auto-created) and P1 (awaiting confirmation). Updates section shows remaining emails with AI summaries:&lt;/strong&gt;&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%2Fr74djww2zvz6xuhs6h6s.jpg" 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%2Fr74djww2zvz6xuhs6h6s.jpg" alt="MailMate AI Email Summary showing Important/Tasks section with P0 and P1, followed by Updates section with OTHER emails and AI summaries" width="800" height="1772"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 7 — Google Calendar showing both events created from the pipeline:&lt;/strong&gt;&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%2F8qpzrbfmi3d8f0wuvvrs.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%2F8qpzrbfmi3d8f0wuvvrs.png" alt="Google Calendar showing two auto-created events from MailMate AI pipeline" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 8 — vLLM running Qwen2.5-0.5B locally, processing emails on CPU, zero cloud cost:&lt;/strong&gt;&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%2Fmo23mvk4hb7mip9wyd22.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%2Fmo23mvk4hb7mip9wyd22.png" alt="Terminal showing vLLM inference logs with token generation statistics per email" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 9 — macOS menu bar app: ✉ icon in the tray, click to see active tasks and trigger a poll:&lt;/strong&gt;&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%2Fo3ds4xrqcq96a3cytr4h.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%2Fo3ds4xrqcq96a3cytr4h.png" alt="macOS menu bar showing MailMate AI tray icon with dropdown: P0 Security breach task listed in red, 1 pending task, Poll now and Quit options" width="800" height="413"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Why Open Innovation Made This Possible
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Zero running cost.&lt;/strong&gt; Both models run locally on a MacBook Intel — no API bills, no per-token charges. That's what makes a Side Hustle viable: the marginal cost of processing 100 emails a day is electricity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Complete privacy.&lt;/strong&gt; Your inbox never touches a third-party server. OAuth tokens stay on disk. The SQLite database is local. For freelancers handling client emails, this is non-negotiable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Swappable components.&lt;/strong&gt; Because both models are open-weight and self-hosted, I can swap the summarizer for a better model as they improve, fine-tune Laya on my own email patterns, or run the whole stack on a Raspberry Pi. Closed APIs don't give you that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Explicit policy, not prompt magic.&lt;/strong&gt; The decision logic is a readable Python module with a clear routing table — not a prompt hoping a model will "be careful." You can read it, audit it, change it. That's only possible because the classification is a typed-decision engine, not a generative black box.&lt;/p&gt;


&lt;h2&gt;
  
  
  Build Session
&lt;/h2&gt;

&lt;p&gt;This project was built end-to-end in a single Claude Code session — 10 milestones, 365 tests, live integration testing with real Gmail and Telegram.&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="Claude Code"&gt;
&lt;/span&gt;
    &lt;span class="agent-session-title"&gt;Building MailMate AI Desktop — Local-First Email Assistant with Two Open-Weight Models&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;Let's go ahead with the planner file and build MailMate AI Desktop — a local-first email assistant that summarizes, prioritizes, and creates tasks from Gmail.&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;Starting with the project planner inspection and reference repo analysis. The PI version uses HuggingFace generative models and systemd — we'll replace those with Laya (typed-decision engine) and a Python-native pipeline.&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-read"&gt;Read&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;docs/mailmate-ai-desktop-planner.md&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 highlight markdown"&gt;&lt;code&gt;docs/mailmate-ai-desktop-planner.md&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 highlight markdown"&gt;&lt;code&gt;Planner loaded — 10 milestones from Laya engine to desktop UI&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&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;Fix the deadline state — I want NONE, CLEAR, AMBIGUOUS instead of a boolean.&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;Added DeadlineState enum and updated decide() with new routing: P0 always creates task (any deadline), P1/P2 need CLEAR deadline for confirmation, AMBIGUOUS → summarize only. 14 tests passing.&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-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;app/policy/decision_policy.py&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 highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;decision_policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;&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 highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;DeadlineState&lt;/span&gt; &lt;span class="n"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;added&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;decide&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;updated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt; &lt;span class="n"&gt;tests&lt;/span&gt; &lt;span class="k"&gt;pass&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&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;Go ahead with Milestone 2 — SQLite task store.&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;Built TaskStore with idempotency via UNIQUE source_email_id constraint. DuplicateEmailError on reprocessing. In-memory mode uses persistent connection for tests. 26 tests passing.&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-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;app/storage/task_store.py&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 highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;storage&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;task_store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;&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 highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;TaskStore&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;update_status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;update_confirmation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;set_calendar_event_id&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&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;Go ahead with Milestone 3 — connect Laya to policy.&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;Built ClassificationResult dataclass, classify_email() wrapper, and apply_policy() firewall. All Laya calls mocked in tests — no model loads. 78 tests passing. Key safety: model predictions alone cannot create tasks.&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-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;app/laya_engine/classifier.py&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 highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;laya_engine&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;classifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;&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 highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;ClassificationResult&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;classify_email&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;normalization&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;REVIEW&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;unknown&lt;/span&gt; &lt;span class="n"&gt;labels&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&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;Go ahead with Milestone 4 — email normalization and task extraction.&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;Built NormalizedEmail and TaskCandidate models. Regex-based deadline detector: ISO dates → CLEAR, relative terms (tomorrow, ASAP, next Friday, bare day names) → AMBIGUOUS, nothing → NONE. Multiple dates → AMBIGUOUS. 134 tests passing.&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-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;app/services/task_extractor.py&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 highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;task_extractor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;&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 highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;detect_deadline_state&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;CLEAR&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;AMBIGUOUS&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;NONE&lt;/span&gt; &lt;span class="n"&gt;classification&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&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;Go ahead with Milestone 5 — orchestration and idempotency.&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;Built process_email() pipeline: idempotency check → summarize → detect deadline → classify → policy → persist → return result. dry_run=True default. notify=True only after successful DB commit. 167 tests passing.&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-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;app/services/orchestrator.py&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 highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;orchestrator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;&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 highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;OrchestrationResult&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="n"&gt;SKIPPED&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;DRY_RUN&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;TASK_CREATED&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;AWAITING_CONFIRMATION&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;NO_ACTION&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;NEEDS_REVIEW&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ERROR&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&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;Go ahead with Milestone 6 — Telegram notifications.&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;Built NotificationTransport ABC, MockTransport, TelegramTransport. P2 confirmation via inline buttons: confirm:&amp;lt;task_id&amp;gt; / decline:&amp;lt;task_id&amp;gt;. handle_callback() with 48h timeout window. Declined tasks stay DECLINED, cannot be re-confirmed. 212 tests passing.&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-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;app/integrations/telegram.py&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 highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;integrations&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;telegram&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;&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 highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;TelegramTransport&lt;/span&gt; &lt;span class="n"&gt;reads&lt;/span&gt; &lt;span class="n"&gt;TELEGRAM_BOT_TOKEN&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;logs&lt;/span&gt; &lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;char&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&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;Go ahead with Milestone 7 — Google Calendar.&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;Built CalendarTransport ABC with MockCalendarTransport and GoogleCalendarTransport (live_writes=True gate). schedule_event() runs 6 eligibility checks before any API call: duplicate, declined status, non-CLEAR deadline, missing deadline, missing time, missing timezone. 245 tests passing.&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-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;app/services/calendar_service.py&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 highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;calendar_service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;&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 highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;check_eligibility&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;schedule_event&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;CREATED&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;DUPLICATE&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;INELIGIBLE&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;MISSING_TIME&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;MISSING_TIMEZONE&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ERROR&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&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;Go ahead with Milestone 8 — Gmail.&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;Built GmailTransport ABC, MockGmailTransport, GmailClient with gmail.readonly scope. MIME parser handles text/plain, text/html, multipart/alternative (prefers plain), multipart/mixed. fetch_new_emails() pre-filters by email_has_task() before fetching body. 276 tests passing.&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-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;app/integrations/gmail.py&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 highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;integrations&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;gmail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;&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 highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;MIME&lt;/span&gt; &lt;span class="n"&gt;parsing&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;load_credentials&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;OAuth&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="n"&gt;auto&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;refresh&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&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;Go ahead with Milestone 9 — desktop UI.&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;Built macOS menu bar app via rumps. Tray icon ✉/⏳/⚠ cycles with pipeline state. P2 tasks show Confirm/Decline sub-menus. Confirm/Decline/Complete all go through existing confirmation_handler. Timer-based polling with threading lock. 300 tests passing.&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-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;app/ui/menu_bar.py&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 highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;menu_bar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;&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 highlight python"&gt;&lt;code&gt;&lt;span class="nc"&gt;MailMateApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rumps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="n"&gt;menu&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="n"&gt;handling&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;live&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;dry&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&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;Go ahead with Milestone 10 — holdout validation.&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;Built 24-example human-reviewed holdout set. End-to-end integration tests covering duplicate processing, failure recovery, declined confirmation safety, ambiguous-deadline safety, notification guard. 361 tests passing.&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-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;tests/fixtures/holdout_emails.json&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 highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;tests/fixtures/holdout_emails.json&lt;/span&gt;&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 highlight json"&gt;&lt;code&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;holdout&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;examples:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;newsletters,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;P&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;incidents,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;P&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;deadlines,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;P&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;routine,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ambiguous&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;dates,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;mixed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;content&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&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;Let's change the logic — P0 always creates a task, P1/P2 need a clear deadline for confirmation, otherwise summarize.&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;Updated policy routing table: P0 + any deadline → CREATE_TASK_AND_NOTIFY. P1/P2 + CLEAR → ASK_CONFIRMATION. P1/P2 + NONE/AMBIGUOUS → SUMMARIZE_ONLY. Removed CLARIFY_DEADLINE as a policy outcome — simpler, more intuitive. 365 tests passing.&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-edit"&gt;Edit&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;app/policy/decision_policy.py&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 highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;decision_policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;&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 highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;New&lt;/span&gt; &lt;span class="n"&gt;routing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;P0&lt;/span&gt; &lt;span class="n"&gt;always&lt;/span&gt; &lt;span class="n"&gt;creates&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;P1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;P2&lt;/span&gt; &lt;span class="n"&gt;need&lt;/span&gt; &lt;span class="n"&gt;CLEAR&lt;/span&gt; &lt;span class="n"&gt;deadline&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&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;Add AI email summarization — I want actual summaries not just subject lines.&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;Found vLLM running locally with Qwen/Qwen2.5-0.5B-Instruct at localhost:8000. Built summarizer.py using OpenAI-compatible API. Pipeline updated: summarize first → pass summary to Laya (cleaner signal). Summary shown in every Telegram notification — batch summary, task created, P2 confirmation. HF Inference API as fallback (requires PRO credits). 365 tests passing.&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-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;app/services/summarizer.py&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 highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;summarizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;&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 highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;summarize_email&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;via&lt;/span&gt; &lt;span class="n"&gt;local&lt;/span&gt; &lt;span class="n"&gt;vLLM&lt;/span&gt; &lt;span class="n"&gt;primary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HF&lt;/span&gt; &lt;span class="n"&gt;API&lt;/span&gt; &lt;span class="n"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;empty&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;failure&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&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;Run live mode — send test emails, trigger /poll from Telegram.&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;Live pipeline confirmed end-to-end: Gmail fetch → vLLM summary → Laya classification → policy → SQLite → Telegram (batch summary + task notifications + P2 Yes/No) → Google Calendar event creation. P0 Security breach → task auto-created + calendar event. P1 Design review → AI summary shown + Yes/No buttons → confirmed → calendar event created. P2 meeting notes → summary only. OTHER → summary only.&lt;/p&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;
        28 of 18 messages
    &lt;/span&gt;
  &lt;/div&gt;
&lt;/div&gt;






&lt;h2&gt;
  
  
  Tech Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Qwen/Qwen2.5-0.5B-Instruct&lt;/strong&gt; via vLLM — local summarisation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;convaiinnovations/laya&lt;/strong&gt; (typed-decisions) — actionability + priority&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Python 3.11&lt;/strong&gt; — pipeline, policy, storage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQLite&lt;/strong&gt; — local task store with idempotency (365 tests)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Telegram Bot API&lt;/strong&gt; — notifications + inline confirmation buttons&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Calendar API&lt;/strong&gt; — scheduling (explicit step only)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gmail API&lt;/strong&gt; (read-only) — inbox polling&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;rumps&lt;/strong&gt; — macOS menu bar app&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  GitHub
&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/praveen-pravi6B" rel="noopener noreferrer"&gt;
        praveen-pravi6B
      &lt;/a&gt; / &lt;a href="https://github.com/praveen-pravi6B/mailmate-ai-desktop" rel="noopener noreferrer"&gt;
        mailmate-ai-desktop
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Local-first macOS email assistant — Laya typed decisions, SQLite, Telegram, Google Calendar
    &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;MailMate AI Desktop&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;A local-first macOS email assistant that identifies actionable emails
applies an explicit decision policy, and surfaces tasks via a menu bar
app and Telegram — without sending data to any cloud backend.&lt;/p&gt;




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

&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;Gmail (read-only)
  → Normalize email
  → HuggingFace Summarizer      ← human-readable summary of each email
  → Laya typed-decision engine  ← actionability + priority classification
  → Application-side policy     ← what is permitted
  → SQLite task store           ← persist if approved
  → Telegram notification       ← summary + notify / ask for confirmation
  → Google Calendar             ← separate explicit step, never automatic
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Two models, two jobs:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Job&lt;/th&gt;
&lt;th&gt;Runs on&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;openai/gpt-oss-120b:fastest&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Summarize each email into 1-2 sentences&lt;/td&gt;
&lt;td&gt;HuggingFace Inference API&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;convaiinnovations/laya&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Classify actionability + priority&lt;/td&gt;
&lt;td&gt;Local CPU&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;The model classifies; the policy decides; you confirm anything routine.
No model output can bypass that chain.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Priority levels&lt;/strong&gt;&lt;/p&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Priority&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;th&gt;Policy&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;P0&lt;/td&gt;
&lt;td&gt;Critical incident / immediate serious risk&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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/praveen-pravi6B/mailmate-ai-desktop" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;






&lt;h2&gt;
  
  
  What I'd Build Next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A Telegram webhook loop so callbacks are instant&lt;/li&gt;
&lt;li&gt;Fine-tune Laya on personal email patterns for better P2 accuracy&lt;/li&gt;
&lt;li&gt;Windows/Linux tray support (replace &lt;code&gt;rumps&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;A paid tier with multi-account support&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>hf26challenge</category>
      <category>python</category>
      <category>ai</category>
      <category>opensource</category>
    </item>
    <item>
      <title>🌿 HearWild — An AI That Listens to Birds, Then Gets Out of Your Way</title>
      <dc:creator>Praveen Kumar</dc:creator>
      <pubDate>Wed, 07 Oct 2026 20:23:17 +0000</pubDate>
      <link>https://dev.to/praveen_kumar_50c9892727f/hearwild-an-ai-that-listens-to-birds-then-gets-out-of-your-way-2f86</link>
      <guid>https://dev.to/praveen_kumar_50c9892727f/hearwild-an-ai-that-listens-to-birds-then-gets-out-of-your-way-2f86</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week1-2026-10-05"&gt;Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;Most AI products are designed to keep us on our screens.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HearWild is designed to do the opposite.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;HearWild is an open-source AI nature companion that lets you record a bird sound, identifies the bird using local AI, tells you a little about what you heard, and encourages you to go back outside.&lt;/p&gt;

&lt;p&gt;The idea is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Listen. Discover. Learn. Go outside.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You don't need to take a photo or know what bird you're looking at. Just point your microphone toward the sound, record for a few seconds, and let the AI listen.&lt;/p&gt;

&lt;p&gt;When a bird is confidently identified, it is automatically added to your &lt;strong&gt;Flock&lt;/strong&gt; and you earn XP:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🐦 New bird → &lt;strong&gt;+100 XP&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;🔁 Bird you've already discovered → &lt;strong&gt;+25 XP&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;⭐ Discover more birds → &lt;strong&gt;level up&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The important part is what happens next.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HearWild doesn't try to keep you inside the app.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once you've discovered the bird, the goal is to put the screen down and keep exploring.&lt;/p&gt;

&lt;p&gt;It's built for anyone who's curious about nature, especially people who don't know much about birds but want a reason to step outside and pay attention to what's around them.&lt;/p&gt;




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

&lt;p&gt;🎥 &lt;strong&gt;&lt;a href="https://drive.google.com/file/d/1cCQKCNYAq6arpISr9mSALr4vPk7V7Nsm/view?usp=sharing" rel="noopener noreferrer"&gt;Watch the HearWild demo&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The MVP currently runs locally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Record a bird sound
        ↓
BirdNET V3 identifies it
        ↓
See the bird + confidence
        ↓
Bird is added to your Flock
        ↓
Earn XP
        ↓
🌿 Keep Exploring
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;The complete source code is available on GitHub:&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/praveen-pravi6B" rel="noopener noreferrer"&gt;
        praveen-pravi6B
      &lt;/a&gt; / &lt;a href="https://github.com/praveen-pravi6B/hearwild" rel="noopener noreferrer"&gt;
        hearwild
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      HearWild is an open-source AI nature companion that lets you record a bird sound, identifies the bird using local AI, tells you a little about what you heard, and encourages you to go back outside.
    &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;HearWild 🌿&lt;/h1&gt;
&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Listen to the world. Discover what lives in it.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;HearWild is an open-source, offline-first AI nature companion that helps you identify birds by sound, build your personal flock, and get back outside.&lt;/p&gt;

&lt;p&gt;It uses &lt;strong&gt;BirdNET V3 ONNX&lt;/strong&gt; to identify bird sounds locally through a simple web interface.&lt;/p&gt;

&lt;p&gt;The idea is simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Listen → Discover → Learn → Go outside.&lt;/strong&gt;&lt;/p&gt;




&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🌿 Why HearWild?&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;AI should help you discover something outside — then get out of your way.&lt;/p&gt;

&lt;p&gt;HearWild is designed around short interactions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Record a bird sound for about 6 seconds.&lt;/li&gt;
&lt;li&gt;Let local AI identify the bird.&lt;/li&gt;
&lt;li&gt;Learn a little about what you heard.&lt;/li&gt;
&lt;li&gt;Add confidently identified birds to your personal flock.&lt;/li&gt;
&lt;li&gt;Earn XP as you discover more birds.&lt;/li&gt;
&lt;li&gt;Put your phone away and keep exploring.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There are no accounts, feeds, maps, or endless scrolling.&lt;/p&gt;




&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;✨ Features&lt;/h2&gt;
&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;🎙️ Identify birds by sound&lt;/h3&gt;

&lt;/div&gt;

&lt;p&gt;Record a short bird sound directly from…&lt;/p&gt;&lt;/div&gt;


&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/praveen-pravi6B/hearwild" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;





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

&lt;p&gt;The core of HearWild is &lt;strong&gt;BirdNET V3&lt;/strong&gt;, running locally through its ONNX model.&lt;/p&gt;

&lt;p&gt;I wanted the AI itself to be part of the open-source stack rather than simply calling a closed AI API.&lt;/p&gt;

&lt;h3&gt;
  
  
  🧠 The AI
&lt;/h3&gt;

&lt;p&gt;HearWild uses:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;BirdNET V3 → ONNX → local inference&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The audio recorded by the browser is sent to a local FastAPI backend, converted to the required format using FFmpeg, and passed to BirdNET V3.&lt;/p&gt;

&lt;p&gt;The model returns the predicted species and confidence.&lt;/p&gt;

&lt;p&gt;I then use confidence-aware behaviour:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Confidence&lt;/th&gt;
&lt;th&gt;HearWild's response&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;70%+&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Confident identification → add to Flock + earn XP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;20–69%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Possible identification → show result, but don't add&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&amp;lt;20%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Unknown → don't pretend to know&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That last part was important to me.&lt;/p&gt;

&lt;p&gt;If the model isn't confident, &lt;strong&gt;HearWild doesn't pretend it knows the answer.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🏗️ Architecture
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌──────────────────────────┐
│       Vue 3 + Vite       │
│                          │
│  🎙️ Record bird sound    │
└────────────┬─────────────┘
             │
             ▼
┌──────────────────────────┐
│         FastAPI          │
│                          │
│     Audio processing     │
└────────────┬─────────────┘
             │
             ▼
┌──────────────────────────┐
│         FFmpeg           │
│      Audio conversion    │
└────────────┬─────────────┘
             │
             ▼
┌──────────────────────────┐
│     BirdNET V3 ONNX      │
│                          │
│  Local bird identification│
└────────────┬─────────────┘
             │
             ▼
┌──────────────────────────┐
│         SQLite           │
│                          │
│       🐦 My Flock        │
└──────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The frontend is built with &lt;strong&gt;Vue 3 + Vite&lt;/strong&gt; and the backend uses &lt;strong&gt;Python + FastAPI&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;SQLite keeps track of the birds I've discovered, how many times I've heard them, and my XP progression.&lt;/p&gt;

&lt;p&gt;For bird imagery and short descriptions, HearWild uses Wikimedia when available.&lt;/p&gt;




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

&lt;p&gt;This project could have been built by calling a commercial bird-identification API.&lt;/p&gt;

&lt;p&gt;But that would have missed one of the most interesting parts of the challenge for me.&lt;/p&gt;

&lt;p&gt;I wanted the &lt;strong&gt;AI itself to be something I could run and understand locally&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Using an open model made it possible to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run bird identification locally&lt;/li&gt;
&lt;li&gt;Avoid sending bird recordings to a proprietary AI service&lt;/li&gt;
&lt;li&gt;Experiment with the model directly&lt;/li&gt;
&lt;li&gt;Control the inference pipeline&lt;/li&gt;
&lt;li&gt;Build without depending on an AI API subscription&lt;/li&gt;
&lt;li&gt;Keep the project reproducible for other developers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More importantly, it changed the way I thought about the product.&lt;/p&gt;

&lt;p&gt;The AI doesn't need to become the destination.&lt;/p&gt;

&lt;p&gt;It can simply be the bridge between &lt;strong&gt;technology and the real world&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That's what I like about open innovation here: the model becomes a building block that anyone can experiment with and build something completely different around.&lt;/p&gt;




&lt;h2&gt;
  
  
  🌿 What I Learned
&lt;/h2&gt;

&lt;p&gt;The biggest lesson from building HearWild was that an AI project doesn't necessarily need to give users &lt;em&gt;more&lt;/em&gt; to look at.&lt;/p&gt;

&lt;p&gt;It can help them notice what's already around them.&lt;/p&gt;

&lt;p&gt;Birdsong is happening all the time.&lt;/p&gt;

&lt;p&gt;Most of us just don't stop to listen.&lt;/p&gt;

&lt;p&gt;So instead of building another AI assistant that says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Here are 10 things you can do on your screen..."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I wanted to build one that says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"You heard a bird. Now go find it."&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's HearWild.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Listen to the world. Discover what lives in it.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🔗 Project
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🐙 &lt;a href="https://github.com/praveen-pravi6B/hearwild" rel="noopener noreferrer"&gt;GitHub — HearWild&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🌿 &lt;a href="https://dev.to/challenges/hacktoberfest-week1-2026-10-05"&gt;Hacktoberfest Open-Source AI Challenge&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>ai</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building MailMate: My First AI Assistant Experiment 🤖📬</title>
      <dc:creator>Praveen Kumar</dc:creator>
      <pubDate>Tue, 06 Oct 2026 18:43:33 +0000</pubDate>
      <link>https://dev.to/praveen_kumar_50c9892727f/building-mailmate-my-first-ai-assistant-experiment-2i2l</link>
      <guid>https://dev.to/praveen_kumar_50c9892727f/building-mailmate-my-first-ai-assistant-experiment-2i2l</guid>
      <description>&lt;p&gt;I’ve been thinking about a simple problem:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What if my email could do more than just sit in my inbox waiting for me?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That question led me to start building &lt;strong&gt;MailMate&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;MailMate is a lightweight AI-powered email assistant that I'm experimenting with on a &lt;strong&gt;Raspberry Pi&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The idea is simple:&lt;/p&gt;

&lt;p&gt;📩 Fetch emails&lt;br&gt;&lt;br&gt;
🧠 Process them using AI&lt;br&gt;&lt;br&gt;
📝 Generate useful summaries&lt;br&gt;&lt;br&gt;
✅ Identify potential tasks or actions&lt;br&gt;&lt;br&gt;
🔔 Send the important information to me through Telegram&lt;/p&gt;

&lt;p&gt;The interesting part isn't just summarizing emails.&lt;/p&gt;

&lt;p&gt;I want to explore how far we can take the idea of an assistant that can &lt;strong&gt;understand context, identify intent, and help turn information into action.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why MailMate?
&lt;/h3&gt;

&lt;p&gt;I receive plenty of emails that don't require immediate attention.&lt;/p&gt;

&lt;p&gt;But mixed in with them are things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An important request&lt;/li&gt;
&lt;li&gt;Something I need to follow up on&lt;/li&gt;
&lt;li&gt;A meeting invitation&lt;/li&gt;
&lt;li&gt;A deadline&lt;/li&gt;
&lt;li&gt;A notification that requires an action&lt;/li&gt;
&lt;li&gt;Information that I'll probably need later&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The problem isn't necessarily &lt;strong&gt;finding&lt;/strong&gt; these emails.&lt;/p&gt;

&lt;p&gt;It's &lt;strong&gt;knowing what matters.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's the problem I'm trying to solve.&lt;/p&gt;

&lt;h3&gt;
  
  
  Starting small
&lt;/h3&gt;

&lt;p&gt;I'm deliberately not trying to build a full-blown autonomous AI agent from the beginning.&lt;/p&gt;

&lt;p&gt;The current workflow is intentionally simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gmail → AI processing → Summary &amp;amp; task detection → Telegram&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I'm building this incrementally and learning along the way.&lt;/p&gt;

&lt;p&gt;Some of the things I want to explore next are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;⏰ Scheduled email processing&lt;/li&gt;
&lt;li&gt;📅 Calendar and task integration&lt;/li&gt;
&lt;li&gt;🔔 Better notification handling&lt;/li&gt;
&lt;li&gt;👤 Multiple email accounts&lt;/li&gt;
&lt;li&gt;🧠 Better context and task detection&lt;/li&gt;
&lt;li&gt;🤖 More autonomous workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What I want to learn
&lt;/h3&gt;

&lt;p&gt;This project is also an excuse to explore some interesting questions:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How should an AI assistant decide what is important?&lt;/p&gt;

&lt;p&gt;How do we prevent an assistant from becoming noisy?&lt;/p&gt;

&lt;p&gt;How much autonomy should we actually give it?&lt;/p&gt;

&lt;p&gt;What should it remember?&lt;/p&gt;

&lt;p&gt;And most importantly — how do we make it genuinely useful rather than just another AI wrapper?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;MailMate is my attempt to explore those questions through a real project.&lt;/p&gt;

&lt;p&gt;I'm building it in public, so I'll be sharing the architecture, experiments, mistakes, and lessons along the way.&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;The project is open on GitHub:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://github.com/praveen-pravi6B/MailMate?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;github.com/praveen-pravi6B/MailMate&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're interested in &lt;strong&gt;AI assistants, automation, Raspberry Pi projects, or building AI tools from scratch&lt;/strong&gt;, I'd love to hear what you're working on too.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Build. Learn. Experiment. Repeat. 🚀&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>raspberrypi</category>
    </item>
  </channel>
</rss>
