<?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: Rohith Pavithran</title>
    <description>The latest articles on DEV Community by Rohith Pavithran (@rohithtp).</description>
    <link>https://dev.to/rohithtp</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%2F509052%2F1a0f8134-7793-4e1e-9821-f06880c29390.png</url>
      <title>DEV Community: Rohith Pavithran</title>
      <link>https://dev.to/rohithtp</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rohithtp"/>
    <language>en</language>
    <item>
      <title>Tides: Tactile After-School Energy Pacing for My 11-Year-Old Daughter</title>
      <dc:creator>Rohith Pavithran</dc:creator>
      <pubDate>Sun, 04 Oct 2026 16:45:58 +0000</pubDate>
      <link>https://dev.to/rohithtp/tides-tactile-after-school-energy-pacing-for-my-11-year-old-daughter-4ga</link>
      <guid>https://dev.to/rohithtp/tides-tactile-after-school-energy-pacing-for-my-11-year-old-daughter-4ga</guid>
      <description>&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I built &lt;strong&gt;Tides&lt;/strong&gt; for my 11-year-old daughter, &lt;strong&gt;Nia&lt;/strong&gt;, who just started 6th grade.&lt;/p&gt;

&lt;p&gt;Entering middle school is an immense sensory, physical, and cognitive leap. Every afternoon around 3:30 PM, Nia walks through the front door carrying an oversized backpack and an empty mental battery after 7 hours of changing classrooms, navigating social dynamics, noisy cafeterias, and intense physical education. &lt;/p&gt;

&lt;p&gt;Whenever we tried traditional task managers or homework tracking apps, they made things worse:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;High executive function barrier:&lt;/strong&gt; Asking a drained 11-year-old to type task titles, configure due dates, and estimate minute durations creates immediate resistance and friction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Guilt and anxiety spirals:&lt;/strong&gt; When a 6th-grader falls behind, traditional apps flash red overdue badges and warning exclamation marks, creating avoidance and shame.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Homework bloat eating into sleep:&lt;/strong&gt; Without strict boundaries, 20 minutes of math expands into the evening, pushing out her playtime, dinner, and bedtime.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Tides&lt;/strong&gt; is an adaptive, offline-first personal energy-pacing Progressive Web App (PWA) designed to solve this in under 10 seconds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;10-Second Arrival Check-In:&lt;/strong&gt; Nia opens the app on her phone or tablet, sees &lt;em&gt;"How full is your tank, Nia?"&lt;/em&gt;, and drags a single fluid, spring-physics slider. Releasing her finger triggers a satisfying haptic pulse and automatically logs her battery level. Zero "Submit" buttons, zero typing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The 3-Zone Desk Dial:&lt;/strong&gt; Her afternoon is visually mapped into three tactile zones:

&lt;ul&gt;
&lt;li&gt;🔵 &lt;strong&gt;Focus (Deep Blue):&lt;/strong&gt; High cognitive work (homework, math). Hard-capped to prevent exhaustion.&lt;/li&gt;
&lt;li&gt;🟢 &lt;strong&gt;Reset (Sage):&lt;/strong&gt; Nervous system down-regulation (snack, walk, shower, quiet Lego time).&lt;/li&gt;
&lt;li&gt;🟡 &lt;strong&gt;Joy (Amber):&lt;/strong&gt; Non-negotiable play, drawing, games, and reading for fun.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pluggable Adaptive Rule Engine:&lt;/strong&gt; If Nia logs an arrival battery $\le 30\%$, Tides instantly triggers the &lt;strong&gt;Battery MVP Fail-Safe&lt;/strong&gt;—shrinking focus to 20 minutes (only 1 Must-Do task allowed) and shifting 40 minutes into Reset. It also detects recurring fatigue patterns (e.g., &lt;strong&gt;Zombie Thursdays&lt;/strong&gt; from double-PE and band) to proactively shield her schedule.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frictionless Task Sorter &amp;amp; 15m Sprint Runner:&lt;/strong&gt; Large tactile cards with single-tap stamps: 🔴 &lt;strong&gt;Must Do&lt;/strong&gt;, 🟡 &lt;strong&gt;Next Up&lt;/strong&gt;, and 🟢 &lt;strong&gt;Later&lt;/strong&gt;. She taps "Start Sprint", focuses through a distraction-free 15-minute countdown, and finishes with confetti and 3 tactile reflection chips: &lt;strong&gt;🟢 Breeze&lt;/strong&gt;, &lt;strong&gt;🟡 Fine&lt;/strong&gt;, or &lt;strong&gt;🔴 Drag&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Guilt-Free 21-Day Static Decay:&lt;/strong&gt; Tasks parked in "Later" that sit untouched for 21 days are auto-sunsetted without alarming notifications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parent Dashboard for Rohith:&lt;/strong&gt; Gives me visibility into Nia's weekly &lt;strong&gt;Vital 4 Metrics&lt;/strong&gt; (Average Arrival Tank, Joy:Focus Ratio, Task Drag Rate, and Zombie Days) with rule calibration controls and an audit trail explaining why Tides adjusted her schedule.&lt;/li&gt;
&lt;/ul&gt;




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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live Demo URL:&lt;/strong&gt; &lt;a href="https://tides-go8j.onrender.com/" rel="noopener noreferrer"&gt;https://tides-go8j.onrender.com/&lt;/a&gt; &lt;em&gt;(or run locally via &lt;code&gt;npm run dev&lt;/code&gt; at &lt;code&gt;http://localhost:5173/&lt;/code&gt;)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Architecture Blueprint &amp;amp; Specs:&lt;/strong&gt; Included directly in the repository under &lt;a href="//docs/BLUEPRINT.md"&gt;&lt;code&gt;docs/BLUEPRINT.md&lt;/code&gt;&lt;/a&gt; and &lt;a href="//docs/IMPLEMENTATION_NOTES.md"&gt;&lt;code&gt;docs/IMPLEMENTATION_NOTES.md&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Visual Walkthrough
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Nia's Arrival Tank &amp;amp; The 10-Second Slider
&lt;/h4&gt;

&lt;p&gt;When Nia arrives home, she adjusts the fluid slider with spring physics and tactile haptic feedback. If battery drops $\le 30\%$, the &lt;strong&gt;MVP Fail-Safe&lt;/strong&gt; activates automatically:&lt;br&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%2Fdp6baa6jn4kmoji95ne5.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%2Fdp6baa6jn4kmoji95ne5.png" alt="Nia Arrival Tank Check-In" width="800" height="528"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  2. The Tactile 3-Zone Desk Dial &amp;amp; Task Sorter
&lt;/h4&gt;

&lt;p&gt;Afternoon time is distributed dynamically across Focus, Reset, and Joy. Nia can prioritize her work in under 15 seconds with single-tap 🔴/🟡/🟢 stamps:&lt;br&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%2Fuvvfbkmnb908a53w38tb.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%2Fuvvfbkmnb908a53w38tb.png" alt="Tactile 3-Zone Desk Dial and Task Triage" width="800" height="528"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  3. Rohith's Parent Dashboard &amp;amp; Vital 4 Metrics
&lt;/h4&gt;

&lt;p&gt;A bird's-eye view of chronic burnout risks, weekly joy-to-focus balance, and live rule audit trails:&lt;br&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%2Fk70s2sovo32f7emgbn62.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%2Fk70s2sovo32f7emgbn62.png" alt="Parent Retrospective Dashboard" width="800" height="528"&gt;&lt;/a&gt;&lt;/p&gt;


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

&lt;p&gt;The complete source code is open-source and hosted on GitHub:&lt;br&gt;
&lt;strong&gt;&lt;a href="https://github.com/irmein/tides" rel="noopener noreferrer"&gt;https://github.com/irmein/tides&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Key Code Highlight: The Extensible Rule Pipeline
&lt;/h3&gt;

&lt;p&gt;Tides avoids spaghetti &lt;code&gt;if-else&lt;/code&gt; business logic by using a pluggable, priority-driven rule engine. Here is the contract and the &lt;strong&gt;Battery MVP Rule&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/engine/rules/base.rule.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;EvaluationContext&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;todayBattery&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 0 - 100%&lt;/span&gt;
  &lt;span class="nl"&gt;recentLogs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BatteryCheckIn&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt; &lt;span class="c1"&gt;// Past 14-21 days of logs&lt;/span&gt;
  &lt;span class="nl"&gt;activeTasks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nl"&gt;currentSchedule&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DaySchedule&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserSettings&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;RuleResult&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;ruleId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;ruleName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;triggered&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 1-100 (100 = Critical safety override)&lt;/span&gt;
  &lt;span class="nl"&gt;actionType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OVERRIDE_TODAY&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MUTATE_WEEK&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DECOMPOSE_TASK&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;AUTO_SUNSET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;AdaptiveRule&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EvaluationContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;RuleResult&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/engine/rules/batteryMvp.rule.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BatteryMvpRule&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AdaptiveRule&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;battery-mvp-fail-safe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Enforce MVP on Critical Battery&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Highest priority override&lt;/span&gt;
  &lt;span class="na"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;todayBattery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;settings&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;threshold&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;batteryMvpThreshold&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;todayBattery&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;threshold&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;ruleId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;battery-mvp-fail-safe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;ruleName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Enforce MVP on Critical Battery&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;triggered&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;actionType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OVERRIDE_TODAY&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;isMvpMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;maxFocusMinutes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;allowedPriorities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MUST_DO&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
          &lt;span class="na"&gt;reallocateZone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RESET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;autoShiftMinutes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Battery at &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;todayBattery&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;% (&amp;lt;= &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;threshold&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;%): Switched to MVP Mode. Only 1 urgent task allowed; Focus shrunk to 20m and 40m transferred to Reset.`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






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

&lt;p&gt;Tides was built from the ground up prioritizing speed, instant offline access, and tactile kid ergonomics:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Technology Stack
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Framework:&lt;/strong&gt; React 19 + TypeScript + Vite for instant bundling and minimal footprint.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Offline-First Reactive Database:&lt;/strong&gt; &lt;strong&gt;Dexie.js (IndexedDB)&lt;/strong&gt;. Every check-in, task status, and schedule adjustment is written synchronously to local device storage. The app works flawlessly on airplane mode or spotty home Wi-Fi.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PWA &amp;amp; Cache Strategy:&lt;/strong&gt; &lt;strong&gt;&lt;code&gt;vite-plugin-pwa&lt;/code&gt; + Workbox&lt;/strong&gt;. The application shell, typography, and SVGs are precached via &lt;code&gt;CacheFirst&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State Management:&lt;/strong&gt; &lt;strong&gt;Zustand&lt;/strong&gt; micro-stores (&lt;code&gt;useEnergyStore&lt;/code&gt;, &lt;code&gt;useScheduleStore&lt;/code&gt;, &lt;code&gt;useTaskStore&lt;/code&gt;, &lt;code&gt;useEngineStore&lt;/code&gt;) cleanly decoupled from UI rendering.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tactile Physics &amp;amp; Motion:&lt;/strong&gt; &lt;strong&gt;Framer Motion&lt;/strong&gt; hydraulic spring configurations (&lt;code&gt;stiffness: 300&lt;/code&gt;, &lt;code&gt;damping: 24&lt;/code&gt;), Web Vibration API haptics, and pure HTML5 Web Audio API sound synthesis (zero external audio network requests).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Styling:&lt;/strong&gt; Tailwind CSS with custom luminescent CSS variable tokens for the 3 zones.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. AI Agent Pair Programming
&lt;/h3&gt;

&lt;p&gt;The entire architecture, domain models, rule engine, and components were pair-programmed using the &lt;strong&gt;Google Antigravity IDE&lt;/strong&gt; and autonomous agent harness:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fast prototyping of tactile ergonomics (verifying thumb touch zones and 64px tap targets).&lt;/li&gt;
&lt;li&gt;End-to-end browser subagent automated testing with video session capture.&lt;/li&gt;
&lt;li&gt;Structured architectural blueprinting in markdown prior to writing production code.&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;When designing technology for children—especially around mental health, daily energy, and school stress—&lt;strong&gt;open innovation is not optional; it is fundamental.&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Child Privacy &amp;amp; Zero Commercial Telemetry (COPPA Compliance):&lt;/strong&gt;
Commercial children's educational apps frequently harvest analytics, device identifiers, and behavioral profiles. With Tides, all neuro-physiological data, daily mood tags, and schedule friction logs stay strictly inside Nia's device IndexedDB sandbox. There are no tracking scripts, ad SDKs, or cloud analytics.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Freedom from Gamified Dark Patterns:&lt;/strong&gt;
Many commercial study apps rely on streak pressure, red warning notifications, and monetization popups that trigger anxiety in young kids. An open-source, local-first app allows us to prioritize emotional safety: auto-sunsetting tasks without guilt badges and protecting playtime over homework bloat.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extensibility for Diverse Neurotypes:&lt;/strong&gt;
Every child's brain regulates energy differently. Because Tides is built around a pluggable open rule engine, parents, teachers, and developers can contribute open heuristic modules:

&lt;ul&gt;
&lt;li&gt;Rules for ADHD hyperfocus and executive function resets.&lt;/li&gt;
&lt;li&gt;Seasonal sports practice exhaustion mitigations.&lt;/li&gt;
&lt;li&gt;Exam season pace shields and sleep deficit protectors.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Open innovation made it possible to build a calm, respectful tool that serves a child's well-being rather than a tech company's engagement metrics.&lt;/p&gt;




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

&lt;p&gt;This project was architected, implemented, and verified with the help of an autonomous AI agent in the Antigravity IDE:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;{% agent_session 4bc093b2-1a41-445c-9a11-efd2a777e451 %}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;(Session transcript includes architectural blueprints, Dexie.js database schema migrations, rule engine unit evaluations, and automated browser walkthrough recordings).&lt;/em&gt;&lt;/p&gt;




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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Primary Track:&lt;/strong&gt; Build for a Friend / Loved One &lt;em&gt;(Built specifically for my 11-year-old daughter, Nia, to protect her after-school energy and joy).&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Special Categories:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Best Offline-First / PWA Experience&lt;/li&gt;
&lt;li&gt;Best Open Innovation &amp;amp; Human-Centered Design&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>The Alpine Mirage: How Upgrading Python Broke My Build and Led to a Truer Security Posture</title>
      <dc:creator>Rohith Pavithran</dc:creator>
      <pubDate>Thu, 30 Jul 2026 03:50:29 +0000</pubDate>
      <link>https://dev.to/rohithtp/the-alpine-mirage-how-upgrading-python-broke-my-build-and-led-to-a-truer-security-posture-38ne</link>
      <guid>https://dev.to/rohithtp/the-alpine-mirage-how-upgrading-python-broke-my-build-and-led-to-a-truer-security-posture-38ne</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/bugsmash"&gt;DEV's Summer Bug Smash: Smash Stories&lt;/a&gt; powered by &lt;a href="https://sentry.io/" rel="noopener noreferrer"&gt;Sentry&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Initial Goal: "Upgrade and Secure"
&lt;/h2&gt;

&lt;p&gt;Like many developers, I recently fell into the trap of assuming that "smaller is always better, and newer is always safer." I decided to upgrade my terminal-based web UI project, &lt;code&gt;py_terminal&lt;/code&gt;, to the bleeding-edge &lt;code&gt;python:3.15-rc-alpine&lt;/code&gt; Docker base image. &lt;/p&gt;

&lt;p&gt;The logic was sound: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Alpine Linux&lt;/strong&gt; has a much smaller footprint, meaning a smaller attack surface. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Python 3.15 Release Candidate&lt;/strong&gt; would give me early access to performance improvements and patches.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;What followed was a cascading series of build failures that taught me a valuable lesson about container architecture, Python's C-API, and what &lt;em&gt;actually&lt;/em&gt; makes a container secure.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Descent into Dependency Hell
&lt;/h2&gt;

&lt;p&gt;The moment I pushed the Dockerfile update and ran &lt;code&gt;docker build&lt;/code&gt;, the pipeline exploded.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Missing Wheels
&lt;/h3&gt;

&lt;p&gt;The first error was abrupt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ERROR: No matching distribution found for litellm==1.93.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because I was combining a release candidate of Python (3.15-rc) with Alpine (which uses &lt;code&gt;musl&lt;/code&gt; libc instead of the standard &lt;code&gt;glibc&lt;/code&gt;), pre-compiled binaries (wheels) simply didn't exist for several of my packages. &lt;code&gt;pip&lt;/code&gt; was forced to download raw source code and build from scratch.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The Rust Compiler (Wait, Rust?)
&lt;/h3&gt;

&lt;p&gt;One of &lt;code&gt;litellm&lt;/code&gt;'s underlying dependencies is &lt;code&gt;fastuuid&lt;/code&gt;, which is written in Rust. Because &lt;code&gt;pip&lt;/code&gt; was building from source, it attempted to download the Rust toolchain (&lt;code&gt;cargo&lt;/code&gt;). It immediately failed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error loading shared library libgcc_s.so.1: No such file or directory
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because Alpine is so incredibly stripped down, it didn't even have the basic C runtime library (&lt;code&gt;libgcc&lt;/code&gt;) required to run the Rust compiler.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Fighting the PyO3 API
&lt;/h3&gt;

&lt;p&gt;Determined to win, I added the heavy build tools to Alpine (&lt;code&gt;apk add build-base cargo libffi-dev&lt;/code&gt;). The build got further, but then crashed while compiling &lt;code&gt;tiktoken&lt;/code&gt; and &lt;code&gt;pydantic-core&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The bridge between Rust and Python is handled by a library called &lt;code&gt;PyO3&lt;/code&gt;. It explicitly rejected Python 3.15 because it was too new! I bypassed this by injecting an environment variable: &lt;code&gt;PYO3_USE_ABI3_FORWARD_COMPATIBILITY=1&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;I thought I had won, until the final boss appeared:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;E0609&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="n"&gt;tp_new&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="n"&gt;PyTypeObject&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Python 3.15 had made fundamental changes to its internal C-API, hiding fields like &lt;code&gt;tp_new&lt;/code&gt; and &lt;code&gt;tp_base&lt;/code&gt;. The Rust bindings in &lt;code&gt;pydantic-core&lt;/code&gt; were incompatible at a structural level. It was physically impossible to build.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Pivot: What Does "Secure" Actually Mean?
&lt;/h2&gt;

&lt;p&gt;I took a step back. I realized that by trying to use Alpine to create a "secure, minimal" container, I was actually doing the exact opposite. &lt;/p&gt;

&lt;p&gt;If I wanted to stay on Alpine, I was going to have to leave heavy compilers (GCC, Make, Rust) inside my container or build complex multi-stage pipelines. Compilers inside production images are a massive security risk.&lt;/p&gt;

&lt;p&gt;I pivoted back to &lt;code&gt;python:3.12-slim&lt;/code&gt; (a Debian-based image) and focused on &lt;strong&gt;actual&lt;/strong&gt; security best practices rather than just chasing a smaller megabyte footprint.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix
&lt;/h3&gt;

&lt;p&gt;Here is the final Dockerfile we settled on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:3.12-slim&lt;/span&gt;

&lt;span class="c"&gt;# 1. Create a non-root user for security&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;groupadd &lt;span class="nt"&gt;-r&lt;/span&gt; appuser &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; useradd &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; appuser appuser

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; requirements.txt ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--no-cache-dir&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . ./&lt;/span&gt;

&lt;span class="c"&gt;# 2. Change ownership of the app to the non-root user&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; appuser:appuser /app

&lt;span class="c"&gt;# 3. Switch to the non-root user before running the app&lt;/span&gt;
&lt;span class="k"&gt;USER&lt;/span&gt;&lt;span class="s"&gt; appuser&lt;/span&gt;

&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; PYTHONUNBUFFERED=1&lt;/span&gt;
&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; ["python", "terminal_web/main.py"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of fighting &lt;code&gt;musl&lt;/code&gt; compilation, we leaned on Debian's pre-compiled wheels (keeping the image compiler-free). Then, we stripped the application of &lt;code&gt;root&lt;/code&gt; privileges. If a vulnerability is ever exploited in my app, the attacker is trapped inside the restricted &lt;code&gt;appuser&lt;/code&gt;, heavily minimizing the blast radius.&lt;/p&gt;




&lt;h2&gt;
  
  
  Going the Extra Mile: Trivy Automation
&lt;/h2&gt;

&lt;p&gt;To ensure we didn't blindly introduce vulnerable packages again, we integrated &lt;a href="https://trivy.dev/" rel="noopener noreferrer"&gt;Trivy&lt;/a&gt; scanning.&lt;/p&gt;

&lt;p&gt;Not only did we add Trivy to our GitHub Actions CI pipeline to fail the build if &lt;code&gt;CRITICAL&lt;/code&gt; or &lt;code&gt;HIGH&lt;/code&gt; vulnerabilities are found, but we also built a custom AI Agent Skill to automate local reporting. &lt;/p&gt;

&lt;p&gt;Now, with a single command, my local environment spins up a background Trivy scan, extracts the JSON data, and parses it into a beautiful Markdown and HTML table, ensuring that no vulnerable library sneaks in before I even push to the remote.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Alpine is a double-edged sword for Python:&lt;/strong&gt; Unless you are prepared to build multi-stage Dockerfiles and compile C/Rust extensions manually, Debian-slim images are often much safer and significantly faster to build.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Small" does not equal "Secure":&lt;/strong&gt; Adding build-tools to an image negates the security benefits of its small size.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Identity is everything:&lt;/strong&gt; Running your container as a non-root user is one of the single highest-impact security improvements you can make, regardless of your base image.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This Bug Smash journey was frustrating, but the end result is a highly stable, automatically-scanned, and truly secure container architecture.&lt;/p&gt;

</description>
      <category>bugsmash</category>
      <category>python</category>
      <category>docker</category>
      <category>security</category>
    </item>
    <item>
      <title>Cleaning up Repository Bloat: Removing Redundant requirements.txt</title>
      <dc:creator>Rohith Pavithran</dc:creator>
      <pubDate>Sat, 18 Jul 2026 13:53:16 +0000</pubDate>
      <link>https://dev.to/rohithtp/cleaning-up-repository-bloat-removing-redundant-requirementstxt-3akk</link>
      <guid>https://dev.to/rohithtp/cleaning-up-repository-bloat-removing-redundant-requirementstxt-3akk</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/bugsmash"&gt;DEV's Summer Bug Smash: Clear the Lineup&lt;/a&gt; powered by &lt;a href="https://sentry.io/" rel="noopener noreferrer"&gt;Sentry&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Overview
&lt;/h2&gt;

&lt;p&gt;The project &lt;code&gt;rohithtp-cv&lt;/code&gt; is a personal repository dedicated to managing and rendering professional CV/resume configurations and pipelines. It streamlines dependency management to ensure clean, reproducible environments for building modern CV layouts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bug Fix or Performance Improvement
&lt;/h2&gt;

&lt;p&gt;In this update, I targeted a common issue in repository maintenance: redundant configuration files. The repository contained a leftover &lt;code&gt;requirements.txt&lt;/code&gt; file that was no longer actively utilized or synchronized with the core dependency management flow. &lt;/p&gt;

&lt;p&gt;Leaving unused configuration files in a codebase increases technical debt, confuses automated dependency scanners (like Dependabot), and risks causing installation mismatches for future collaborators.&lt;/p&gt;

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

&lt;p&gt;You can view the full changes and the exact cleanup in the commit linked below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/rohithtp/rohithtp-cv/commit/0f1f373a33255a6367dd8b9893106178b98e26c7" rel="noopener noreferrer"&gt;Clean up redundant requirements.txt&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  My Improvements
&lt;/h2&gt;

&lt;p&gt;The optimization involved a direct pruning of the project architecture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Identified that the package dependencies were already properly specified elsewhere or no longer required this file.&lt;/li&gt;
&lt;li&gt;Removed the redundant &lt;code&gt;requirements.txt&lt;/code&gt; to streamline the repository structure.&lt;/li&gt;
&lt;li&gt;Verified that local builds and automated pipelines function optimally without the file.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This simple architectural hygiene task reduces the clutter in the codebase, simplifies onboarding, and prevents potential security/version mismatches from unmaintained files.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>bugsmash</category>
      <category>devops</category>
      <category>python</category>
    </item>
    <item>
      <title>Free Voice Music Curator: Ditch Premium Music Fees with ElevenLabs &amp; Google AI</title>
      <dc:creator>Rohith Pavithran</dc:creator>
      <pubDate>Sun, 12 Jul 2026 15:18:44 +0000</pubDate>
      <link>https://dev.to/rohithtp/free-voice-music-curator-ditch-premium-music-fees-with-elevenlabs-google-ai-454c</link>
      <guid>https://dev.to/rohithtp/free-voice-music-curator-ditch-premium-music-fees-with-elevenlabs-google-ai-454c</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/challenges/weekend-2026-07-09"&gt;Weekend Challenge: Passion Edition&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;I built the &lt;strong&gt;Free Voice Music Curator&lt;/strong&gt;, an intelligent full-stack audio player powered entirely by public APIs, legal Creative Commons music, and zero paid subscription walls.&lt;/p&gt;

&lt;p&gt;Inspired by the challenge prompt of &lt;strong&gt;passion&lt;/strong&gt;, I wanted to capture the absolute devotion fans and hobbyists pour into their musical worlds. However, classic web-streaming apps are trapped behind heavy OAuth logic or aggressive paid premium tiers. The &lt;em&gt;Free Voice Music Curator&lt;/em&gt; solves this by allowing users to command a local audio player using natural voice strings (via ElevenLabs), which are dynamically parsed by Google AI to pull over 500,000 legal, free-streaming tracks from Jamendo.&lt;/p&gt;

&lt;h3&gt;
  
  
  🟢 The Free-Tier Architecture
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ ElevenLabs Agent ] ➔ Webhook ➔ [ Backend Server ] ➔ Jamendo REST API
                                        │
                                        ▼
                        [ HTML5 Audio Player Engine ] ➔ (Plays raw .mp3 stream)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;The application is fully configured and ready!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live Development Webhook:&lt;/strong&gt; &lt;code&gt;https://ais-dev-vtsuihfhfsyunprfhoszsh-559194232025.asia-east1.run.app/api/webhook/elevenlabs&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Production Webhook Simulator:&lt;/strong&gt; Included directly inside the UI console so you can fire direct preset configurations (e.g., &lt;code&gt;💤 Lofi Study&lt;/code&gt;, &lt;code&gt;🏎️ Synthwave&lt;/code&gt;, &lt;code&gt;🎸 Acoustic&lt;/code&gt;) to watch the system respond in real time.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;The interface features a gorgeous deep interstellar slate and emerald canvas (&lt;code&gt;bg-slate-900&lt;/code&gt; / &lt;code&gt;text-emerald-400&lt;/code&gt;) alongside modern typography pairings (&lt;code&gt;Space Grotesk&lt;/code&gt; and &lt;code&gt;Inter&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Here is the clean &lt;strong&gt;Python Core Engine&lt;/strong&gt; snippet used to process the incoming webhook metadata securely:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;vlc&lt;/span&gt;  &lt;span class="c1"&gt;# Install via: pip install python-vlc
&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FreeVoiceMusicCurator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;client_id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client_id&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;base_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.jamendo.com/v3.0/tracks/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_curated_stream_urls&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target_genre&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target_artist&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Querying free cloud library for: Genre=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;target_genre&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, Artist=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;target_artist&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;client_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;format&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;limit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;audioformat&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mp32&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;order&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;popularity_total&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;target_genre&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tags&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;target_genre&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;target_artist&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;artist_name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;target_artist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;tracks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;results&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;

            &lt;span class="n"&gt;stream_targets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tracks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;stream_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;audio&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;stream_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;stream_targets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;artist&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;artist_name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;stream_url&lt;/span&gt;
                    &lt;span class="p"&gt;})&lt;/span&gt;

            &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shuffle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream_targets&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;stream_targets&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;API Fetch Error: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;The execution pipeline flows fluidly across three modern technical frameworks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Intelligent Conversational Agent (ElevenLabs):&lt;/strong&gt; I built a blank agent powered by a custom webhook tool named &lt;code&gt;play_free_genre_music&lt;/code&gt;. It listens for spoken triggers like &lt;em&gt;"Play some high-energy synthwave beats"&lt;/em&gt; and extracts clean textual params (&lt;code&gt;prompt&lt;/code&gt;, &lt;code&gt;genre&lt;/code&gt;, &lt;code&gt;artist&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contextual AI Translation Engine (Google AI Studio):&lt;/strong&gt; The backend leverages the &lt;code&gt;gemini-3.5-flash&lt;/code&gt; model to analyze the full natural-language transcripts, scrubbing out specific moods, obscure tags, or strict artist names, complete with a local rule-based keyword fallback parser to guarantee zero downtime.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Responsive Web Player Platform:&lt;/strong&gt; Built an HTML5 audio context interface complete with a live API resource monitor (tracking Jamendo's 35,000 free monthly request tier cap) and real-time scrolling telemetry log panels recording every single serverless event transcript.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;This application is being submitted to the following prize categories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of ElevenLabs:&lt;/strong&gt; For mapping custom voice conversational tools to a local audio state architecture seamlessly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Google AI:&lt;/strong&gt; Using Gemini to turn messy, natural speech commands into highly structured metadata payloads.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
      <category>googleai</category>
      <category>elevenlabs</category>
    </item>
    <item>
      <title>Terminal Web 2.0: AI Preflight, Healing, and Safety</title>
      <dc:creator>Rohith Pavithran</dc:creator>
      <pubDate>Sun, 07 Jun 2026 11:45:57 +0000</pubDate>
      <link>https://dev.to/rohithtp/terminal-web-20-ai-preflight-healing-and-safety-dbj</link>
      <guid>https://dev.to/rohithtp/terminal-web-20-ai-preflight-healing-and-safety-dbj</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/github-2026-05-21"&gt;GitHub Finish-Up-A-Thon Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Terminal Web (&lt;code&gt;py_terminal&lt;/code&gt;)&lt;/strong&gt; is a powerful terminal-based UI web project utilizing Python and the &lt;a href="https://github.com/Textualize/rich" rel="noopener noreferrer"&gt;Rich&lt;/a&gt; library for beautiful terminal output combined with advanced command execution capabilities.&lt;/p&gt;

&lt;p&gt;As part of the Finish-Up-A-Thon, I transformed this tool by integrating an &lt;strong&gt;AI Safety Net&lt;/strong&gt;—a proactive layer designed to protect users from executing destructive shell commands (e.g., &lt;code&gt;rm -rf&lt;/code&gt;, &lt;code&gt;git push --force&lt;/code&gt;) while maintaining a fluid and rapid developer experience. The safety net employs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tier-1 Heuristics:&lt;/strong&gt; Instant, offline protection against common dangerous commands.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tier-2 AI Preflight:&lt;/strong&gt; LLM-powered risk analysis that summarizes potential consequences and affected resources for &lt;code&gt;MUTATING+&lt;/code&gt; risk levels.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Intelligent Self-Healing:&lt;/strong&gt; A workflow that diagnoses failed commands (e.g., permission errors, missing paths) and suggests safe alternatives to get you back on track.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;&lt;strong&gt;Project Repository:&lt;/strong&gt; &lt;a href="https://github.com/rohithtp/py_terminal" rel="noopener noreferrer"&gt;https://github.com/rohithtp/py_terminal&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Comeback Story
&lt;/h2&gt;

&lt;p&gt;Previously, &lt;code&gt;py_terminal&lt;/code&gt; was an effective CLI wrapper with dual execution modes (interactive and capture) and beautifully formatted outputs. However, it had one critical flaw: it blindly executed whatever bash command was provided, offering no protection against accidental system damage. In a modern development environment where LLMs are sometimes used to generate complex, unverified commands, ensuring those commands are safe to run locally became a high priority.&lt;/p&gt;

&lt;p&gt;To "finish it up" for this hackathon, I drastically leveled up the tool's intelligence and safety by adding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;An AI Preflight Loop:&lt;/strong&gt; Intercepts risky commands, uses LLMs to generate reversibility notes, and blocks execution until explicit user confirmation is given.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A Self-Healing Workflow:&lt;/strong&gt; Catches non-zero exit codes, diagnoses the error (e.g., "No such file or directory"), and proposes an LLM-generated fix that gets re-routed through the safety preflight loop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQLite Caching:&lt;/strong&gt; Caches preflight AI evaluations to avoid duplicate API calls and guarantees zero latency for repeated commands.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Offline Graceful Degradation:&lt;/strong&gt; The UI falls back beautifully to local heuristic warnings when the LLM API is unavailable, ensuring the tool is always usable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A Status Capture Utility:&lt;/strong&gt; A built-in telemetry tool to rapidly verify repository and dependency health.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  My Experience with GitHub Copilot
&lt;/h2&gt;

&lt;p&gt;GitHub Copilot acted as an exceptionally fast pair programmer throughout this challenge. It was instrumental in scaffolding the &lt;code&gt;pexpect&lt;/code&gt;-based automated test suite for validating the AI Safety Net, mocking out LLM network responses, and quickly laying out the boilerplate for the Rich UI panels. &lt;/p&gt;

&lt;p&gt;When constructing the SQLite caching mechanism, Copilot seamlessly anticipated the database schema I needed and handled boilerplate queries, allowing me to focus entirely on the core business logic of the safety heuristics and healing loop. It transformed complex refactoring and UI layout tasks into smooth, effortless completions.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Team Members:&lt;/strong&gt; &lt;a class="mentioned-user" href="https://dev.to/rohithtp"&gt;@rohithtp&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>githubchallenge</category>
    </item>
    <item>
      <title>mnemo — A local-first learning agent that remembers, without leaking</title>
      <dc:creator>Rohith Pavithran</dc:creator>
      <pubDate>Sun, 31 May 2026 09:20:10 +0000</pubDate>
      <link>https://dev.to/rohithtp/mnemo-a-local-first-learning-agent-that-remembers-without-leaking-d49</link>
      <guid>https://dev.to/rohithtp/mnemo-a-local-first-learning-agent-that-remembers-without-leaking-d49</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hermes-agent-2026-05-15"&gt;Hermes Agent Challenge&lt;/a&gt;: Build With Hermes Agent&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;mnemo&lt;/strong&gt; is a learning-management agent for kids and self-directed learners. It tracks topics, sequences them by prerequisites, schedules spaced-repetition reviews (SM-2), generates quizzes, and adapts the plan over time through a Hermes-driven feedback loop.&lt;/p&gt;

&lt;p&gt;The problem: hosted AI tutors send a child's mistakes, struggles, and reading level to someone else's servers. Browser-only chat loops forget everything the moment the tab closes — no cross-session adaptation, no long-term plan. And LLMs happily hallucinate URLs and quiz answers, so nothing stops an unreviewed link from reaching a 6th-grader.&lt;/p&gt;

&lt;p&gt;mnemo's answer is a three-part stance baked into the schema, not bolted on:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Local-first by default.&lt;/strong&gt; SQLite (WAL) on-device, 7 tables, 3 migrations. Hermes-3 runs locally via Ollama. A HuggingFace API path exists for constrained hardware but requires explicit opt-in and is clearly labelled in the UI — every hosted call is logged to the &lt;code&gt;events&lt;/code&gt; table.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Two gates before any content reaches the learner.&lt;/strong&gt; Every external &lt;code&gt;resource&lt;/code&gt; starts &lt;code&gt;approved = 0&lt;/code&gt; in the schema. A second gate joins a &lt;code&gt;source_allowlist&lt;/code&gt; table at the SQL layer — even an approved resource is suppressed if its origin isn't a trusted source (&lt;code&gt;khan-academy&lt;/code&gt;, &lt;code&gt;ck12&lt;/code&gt;, internal-curriculum). Both gates have dedicated scenario tests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The agent proposes; a human approves.&lt;/strong&gt; Pace changes, resource-type shifts, and any preference write goes through a confirmation gate. The agent literally cannot mutate learner preferences without a human checkbox — enforced via an MCP deny-list, not just UI.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;Pitch deck (single-file Reveal.js, no build step):&lt;br&gt;
&lt;strong&gt;&lt;a href="https://plain-frost-2119.rohithtp.workers.dev/" rel="noopener noreferrer"&gt;pitch.html&lt;/a&gt;&lt;/strong&gt; — 6 slides covering the problem, the Hermes differentiator, architecture, the two-gate safety model, and a realistic dashboard mockup of the shipped UI.&lt;/p&gt;

&lt;p&gt;Quick local run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv .venv &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
sqlite3 learning.db &amp;lt; migrations/001_init.sql
sqlite3 learning.db &amp;lt; migrations/002_quiz_bank.sql
sqlite3 learning.db &amp;lt; migrations/003_source_allowlist.sql
python &lt;span class="nt"&gt;-m&lt;/span&gt; uvicorn webapp.app:app &lt;span class="nt"&gt;--reload&lt;/span&gt; &lt;span class="nt"&gt;--port&lt;/span&gt; 8000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;code&gt;http://localhost:8000&lt;/code&gt; for the dashboard, or run a Hermes session end-to-end:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama pull hermes3
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:8000/api/agent/session &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"learner_id": 1, "backend": "ollama"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The dashboard streams each tool call the agent makes, then refreshes progress and the review queue automatically.&lt;/p&gt;

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

&lt;p&gt;Repository: &lt;strong&gt;&lt;a href="https://gitea.com/rohithtp/mnemo" rel="noopener noreferrer"&gt;gitea.com/rohithtp/mnemo&lt;/a&gt;&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Key directories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;webapp/&lt;/code&gt; — FastAPI REST + SSE + static dashboard (25+ endpoints)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mcp_server/&lt;/code&gt; — stdio MCP server exposing 7 tools to Hermes&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/agent/&lt;/code&gt; — Hermes session orchestrator, allowlist, memory, insights&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/learning/&lt;/code&gt; — SM-2 algorithm, sequencing logic, safety/privacy gates&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;migrations/&lt;/code&gt; — 3 SQL files, schema-version tracked&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tests/&lt;/code&gt; — 69 passing tests (SM-2 unit + integration + API + scenario)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docs/&lt;/code&gt; — full build plan, decisions log, 25-risk register, two-profile docs&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  My Tech Stack
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Choice&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Database&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;SQLite&lt;/strong&gt; (WAL mode) on-device · libSQL/Turso documented as forward path&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Backend&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;FastAPI&lt;/strong&gt; + uvicorn + SSE streaming&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agent runtime&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Hermes-3&lt;/strong&gt; via &lt;strong&gt;Ollama&lt;/strong&gt; (local) · HuggingFace Inference API fallback&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tool surface&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;stdio MCP&lt;/strong&gt; (Hermes) + &lt;strong&gt;WebMCP&lt;/strong&gt; progressive enhancement (Chrome 146+)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Frontend&lt;/td&gt;
&lt;td&gt;Vanilla JS + plain CSS — no framework, no build step&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Spaced repetition&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;SM-2&lt;/strong&gt; algorithm, implemented as pure functions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tests&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;pytest&lt;/strong&gt; — 15 SM-2 unit + 18 integration + 31 API + 5 scenario = &lt;strong&gt;69 passing&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deployment&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Dockerfile&lt;/strong&gt; + systemd unit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Language&lt;/td&gt;
&lt;td&gt;Python 3.11+ (3.14 tested)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;All Python deps are pinned in &lt;code&gt;requirements.txt&lt;/code&gt;. The Hermes-3 model digest is pinned by SHA256 and asserted at startup so a silent upstream change can't drift the agent's behaviour mid-session (R02 mitigation).&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Used Hermes Agent
&lt;/h2&gt;

&lt;p&gt;Hermes-3 is the orchestration brain for the whole adaptive loop. The reason it had to be Hermes specifically, not a stateless prompt loop, comes down to four capabilities:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Tool-calling over a real schema.&lt;/strong&gt; &lt;code&gt;src/agent/session.py&lt;/code&gt; runs a tool-calling loop where Hermes drives a study session by calling the 7 MCP tools (&lt;code&gt;get_progress_summary&lt;/code&gt;, &lt;code&gt;get_ready_topics&lt;/code&gt;, &lt;code&gt;start_topic&lt;/code&gt;, &lt;code&gt;get_next_review_items&lt;/code&gt;, &lt;code&gt;record_review_result&lt;/code&gt;, &lt;code&gt;recommend_resources&lt;/code&gt;, &lt;code&gt;generate_quiz&lt;/code&gt;). Each call is logged to the &lt;code&gt;events&lt;/code&gt; table with arguments and result. The agent isn't generating advice in prose — it's writing to SQLite through audited tools.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Cross-session memory.&lt;/strong&gt; Every session writes a &lt;code&gt;memory_note&lt;/code&gt; event summarising patterns the agent noticed. The next session's system prompt is injected with the most recent notes for that learner, so Hermes "remembers" that this kid struggles with unlike denominators across sessions, not just within one tab. Memory notes are per-learner and stay on-device.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Pattern analysis + human-approvable proposals.&lt;/strong&gt; Phase 6 added &lt;code&gt;POST /api/agent/insights/{learner_id}&lt;/code&gt;. Hermes reads the event trail across a configurable window, computes &lt;code&gt;avg_quality&lt;/code&gt;, &lt;code&gt;days_active&lt;/code&gt;, resource-type variety, and emits structured proposals like &lt;code&gt;{"type": "pace", "direction": "increase", "reason": "avg quality above 4.0"}&lt;/code&gt;. Each proposal is stored with &lt;code&gt;resolved_at = NULL&lt;/code&gt; and surfaces in the dashboard with Approve / Dismiss buttons. The agent never silently applies pace changes — a human resolves each proposal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Allowlist-enforced tool boundary.&lt;/strong&gt; &lt;code&gt;src/agent/allowlist.py&lt;/code&gt; defines &lt;code&gt;AGENT_ALLOWLIST&lt;/code&gt; and &lt;code&gt;AGENT_DENY_LIST&lt;/code&gt; as constants. &lt;code&gt;set_learner_preferences&lt;/code&gt; is on the deny-list, so even if the model is jailbroken into trying to mutate preferences directly, the session orchestrator raises &lt;code&gt;PermissionError&lt;/code&gt; before the tool runs. This is the difference between "the UI hides it" and "the agent cannot do it."&lt;/p&gt;

&lt;p&gt;The combination — local model + persistent memory + audited tool calls + human-in-the-loop on every state-mutating proposal — is what makes mnemo trustable as a coach for a child, not just for an adult tinkerer. That posture is what the Hermes agent makes practical; a hosted stateless chatbot can't enforce any of it.&lt;/p&gt;

</description>
      <category>hermesagentchallenge</category>
      <category>devchallenge</category>
      <category>agents</category>
      <category>hermesagent</category>
    </item>
    <item>
      <title>StudyTrak // Astra Core – Gemma 4 Challenge Submission</title>
      <dc:creator>Rohith Pavithran</dc:creator>
      <pubDate>Sat, 23 May 2026 17:42:27 +0000</pubDate>
      <link>https://dev.to/rohithtp/studytrak-astra-core-gemma-4-challenge-submission-cc6</link>
      <guid>https://dev.to/rohithtp/studytrak-astra-core-gemma-4-challenge-submission-cc6</guid>
      <description>&lt;h1&gt;
  
  
  StudyTrak // Astra Core – Gemma 4 Challenge Submission
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/google-gemma-2026-05-06"&gt;Gemma 4 Challenge: Build with Gemma 4&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;StudyTrak (Astra Core)&lt;/strong&gt; is an immersive, high-fidelity student spaced repetition planner and neural coaching console. Designed to work completely local-first or proxy securely via remote endpoints, StudyTrak solves the "academic attention fragmentation" problem. It merges class schedules, homework tracker boards, spaced-repetition card decks (SM-2 scheduler), and deep neural academic helpers into a single HUD-inspired dashboard. &lt;/p&gt;

&lt;h3&gt;
  
  
  Core Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;🗓️ &lt;strong&gt;Astra Chrono Scheduler&lt;/strong&gt;: Interactive class blocks and room assignments synced with responsive real-time layout structures.&lt;/li&gt;
&lt;li&gt;🎯 &lt;strong&gt;Spaced Repetition Flashcards&lt;/strong&gt;: Localized FSRS/SM-2 simulator (with grades: &lt;em&gt;Forgot&lt;/em&gt;, &lt;em&gt;Hard Link&lt;/em&gt;, &lt;em&gt;Good Match&lt;/em&gt;, &lt;em&gt;Perfect Spot&lt;/em&gt;) scheduling item intervals adaptively.&lt;/li&gt;
&lt;li&gt;🎙️ &lt;strong&gt;Multi-Modal Capture Panel&lt;/strong&gt;: Scan worksheets (Camera/Photo uploads) or type natural language inputs to automatically parse schedule drafts and pending homework proposals.&lt;/li&gt;
&lt;li&gt;💬 &lt;strong&gt;Subject Advisory Chat Tutor&lt;/strong&gt;: Academic conversational helper grounded directly in defined high-school/college subjects.&lt;/li&gt;
&lt;li&gt;🧘‍♀️ &lt;strong&gt;Empathetic Reflection Journal&lt;/strong&gt;: Conversational weekly debriefs tracking achievements, struggles, and proposed behavioral corrections.&lt;/li&gt;
&lt;li&gt;🔊 &lt;strong&gt;Voice Speech Synthesis&lt;/strong&gt;: Listen to high-fidelity audio versions of daily briefings with an interactive audio player.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  App In Google AI
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AiStudio&lt;/strong&gt;: &lt;a href="https://ai.studio/apps/97a83485-4fc2-43ae-8eb7-b82d63cdb1e9" rel="noopener noreferrer"&gt;https://ai.studio/apps/97a83485-4fc2-43ae-8eb7-b82d63cdb1e9&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;The complete, pristine full-stack source code is published on Gitea at &lt;a href="https://gitea.com/rohithtp/studytrak" rel="noopener noreferrer"&gt;https://gitea.com/rohithtp/studytrak&lt;/a&gt;. You can clone, audit, or deploy the application directly from this repository.&lt;/p&gt;




&lt;h2&gt;
  
  
  How I Used Gemma 4
&lt;/h2&gt;

&lt;p&gt;StudyTrak leverages the lightweight yet highly competent capabilities of the &lt;strong&gt;Gemma 4&lt;/strong&gt; model lineup to deliver a privacy-preserving co-pilot:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Model Choices and Fit&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gemma 4 Tiny (E2B - 1.5GB)&lt;/strong&gt;: Configured as the optimal on-device WebLLM/MediaPipe companion. We chose the E2B formulation because it easily fits within the standard modern browser sandbox, enabling sub-150ms real-time token generation for micro-scans and speech transcription parsing without any outbound network latency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemma 4 Standard (E4B - 3GB)&lt;/strong&gt;: Selected for core desktop semantic analysis, empathetic reflection summaries, and structuring homework proposals from handwritten worksheet snapshots. It balances rapid execution speeds with reasoning traits needed to provide high-quality structural mentorship.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Context Grounding&lt;/strong&gt;:&lt;br&gt;
Every prompt generated goes through a deep localized context packaging layer, supplying active subject indices, schedule constraints, and historic reflection streaks to completely ground prompt results with zero external leak risk.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>devchallenge</category>
      <category>gemmachallenge</category>
      <category>gemma</category>
    </item>
  </channel>
</rss>
