<?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: Trakshan Mishra</title>
    <description>The latest articles on DEV Community by Trakshan Mishra (@trakshanmishra).</description>
    <link>https://dev.to/trakshanmishra</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%2F678422%2F6ee7e445-769b-4981-8b53-5ce93386da47.png</url>
      <title>DEV Community: Trakshan Mishra</title>
      <link>https://dev.to/trakshanmishra</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/trakshanmishra"/>
    <language>en</language>
    <item>
      <title>My AI agent's 34 tests passed. Then I broke the code 31 times.</title>
      <dc:creator>Trakshan Mishra</dc:creator>
      <pubDate>Thu, 05 Nov 2026 04:41:22 +0000</pubDate>
      <link>https://dev.to/trakshanmishra/my-ai-agents-34-tests-passed-then-i-broke-the-code-31-times-506k</link>
      <guid>https://dev.to/trakshanmishra/my-ai-agents-34-tests-passed-then-i-broke-the-code-31-times-506k</guid>
      <description>&lt;p&gt;"All tests passing" is the most common line in an AI agent's final summary. I wanted to know what it is worth.&lt;/p&gt;

&lt;p&gt;Disclosure first: this week I'm working with the team behind &lt;a href="https://lemoncode.ai/home?ref=597b9ec3-59f5-4cd2-936d-7d527ae1b0c4" rel="noopener noreferrer"&gt;Lemon Code&lt;/a&gt;, a free coding agent. That's exactly why I didn't want to stop at "it passed".&lt;/p&gt;

&lt;h2&gt;
  
  
  The build
&lt;/h2&gt;

&lt;p&gt;I asked it for a weather and travel planner: search a city, show the 7-day forecast, pick trip dates, rank the best days to go, and suggest a packing list. Plain Vite and vanilla JS, live data from Open-Meteo.&lt;/p&gt;

&lt;p&gt;About 3 minutes later I had a working preview. On the way, 3 of its tests failed on the first run. It read the errors, fixed them, and reran. The final summary said 34 tests passing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check 1: run the tests outside the agent
&lt;/h2&gt;

&lt;p&gt;I downloaded the zip and ran it on my own laptop.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; ✓ test/storage.test.js (8 tests)
 ✓ test/weather.test.js (11 tests)
 ✓ test/planner.test.js (15 tests)

 Tests  34 passed (34)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Good, but that only proves the tests pass. It says nothing about whether they would fail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check 2: delete each function and see who notices
&lt;/h2&gt;

&lt;p&gt;There's a good post here on dev.to, &lt;a href="https://dev.to/jeff_pdc/the-test-that-survives-its-own-implementation-578d"&gt;The Test That Survives Its Own Implementation&lt;/a&gt;, about agent tests that keep passing after you delete the code they cover. So I tried it.&lt;/p&gt;

&lt;p&gt;For each of the 21 exported functions in the logic files, I added &lt;code&gt;return undefined;&lt;/code&gt; as the first line and reran the suite.&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="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body_start&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;exported_functions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;original&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;body_start&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;  return undefined;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;original&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;body_start&lt;/span&gt;&lt;span class="p"&gt;:])&lt;/span&gt;
    &lt;span class="n"&gt;failed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;npx vitest run --reporter=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;numFailedTests&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;original&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result: &lt;strong&gt;21 out of 21 caught.&lt;/strong&gt; Every gutted function broke at least one test, from 1 failure (&lt;code&gt;geocodeUrl&lt;/code&gt;) up to 8 (&lt;code&gt;parseISODate&lt;/code&gt;). No dead weight.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check 3: small, realistic bugs
&lt;/h2&gt;

&lt;p&gt;Deleting a function is a loud bug. Real bugs are quiet. So I made 10 one-line changes to the trip planner:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Change&lt;/th&gt;
&lt;th&gt;Tests that failed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Off-by-one in the day count (drop &lt;code&gt;+ 1&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Date filter drops the last day (&lt;code&gt;&amp;lt;=&lt;/code&gt; to &lt;code&gt;&amp;lt;&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best days sorted in reverse&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"End date before start date" check removed&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rain penalty halved&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wind threshold 20 to 30 km/h&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sunny-day bonus removed&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Snow penalty removed&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"Too hot" threshold 30 to 35°C&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tie-break between equal days reversed&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;4 caught, 6 survived.&lt;/p&gt;

&lt;p&gt;The pattern is clear. Dates, ranges and sort order are well tested. The day-scoring rules are not. &lt;code&gt;scoreDay&lt;/code&gt; has one test, and it only checks that a clear, calm day scores higher than a storm. Any weight you tweak still passes that.&lt;/p&gt;

&lt;p&gt;Also worth saying: the UI code (&lt;code&gt;ui.js&lt;/code&gt; and &lt;code&gt;main.js&lt;/code&gt;, about 480 lines) has no unit tests at all. The agent checked the UI by driving the app in a browser instead, searching two cities and saving a trip. That's a reasonable choice for a small app, but it's not something &lt;code&gt;npm test&lt;/code&gt; will protect.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd take from this
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;"34 passing" was true, and the tests weren't fake.&lt;/strong&gt; They caught every deleted function and the date bugs I'd worry about most.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The gaps are where the logic is fuzzy.&lt;/strong&gt; Scoring rules with magic numbers got one sanity test. That's the kind of code where I'd ask the agent for more: "write a test that fails if the rain penalty changes."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The check is cheap.&lt;/strong&gt; Breaking 31 things and rerunning took a couple of minutes with a small script. I'd do this on any agent-written suite before trusting it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to try the same thing, Lemon Code is free and doesn't need an API key: &lt;a href="https://lemoncode.ai/home?ref=597b9ec3-59f5-4cd2-936d-7d527ae1b0c4" rel="noopener noreferrer"&gt;lemoncode.ai&lt;/a&gt;. Build something, download it, and break it. I'd like to hear what your tests let through.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Related reading: &lt;a href="https://dev.to/jeff_pdc/every-agent-task-should-end-with-a-command-you-can-run-mlm"&gt;Every Agent Task Should End With a Command You Can Run&lt;/a&gt; and &lt;a href="https://dev.to/potapov/how-to-check-your-test-can-catch-the-bug-3m3"&gt;How to Check Your Test Can Catch the Bug&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>testing</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>PocketTrail: three small things to notice outside, picked by a small open-weight model</title>
      <dc:creator>Trakshan Mishra</dc:creator>
      <pubDate>Tue, 06 Oct 2026 14:00:39 +0000</pubDate>
      <link>https://dev.to/trakshanmishra/pockettrail-three-small-things-to-notice-outside-picked-by-a-small-open-weight-model-6eh</link>
      <guid>https://dev.to/trakshanmishra/pockettrail-three-small-things-to-notice-outside-picked-by-a-small-open-weight-model-6eh</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 Week 1 "Touch Grass" challenge&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;PocketTrail is a small web app for people who want to look up from their phone for twenty minutes.&lt;/p&gt;

&lt;p&gt;You tell it how much time you have (10, 20 or 30 minutes), where you are going (a park, a garden, your neighborhood, or just a window or balcony), what it is like outside (daytime, evening, rainy) and your mood (calm, curious, creative). You can add a note like "stay seated, no photos". It gives you three short things to notice, with durations that add up to the time you picked.&lt;/p&gt;

&lt;p&gt;Then you save the walk to your device, put the phone away, and open it again when you want the next prompt. Saved walks work without a connection. There are no accounts, streaks, maps or feeds.&lt;/p&gt;

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

&lt;p&gt;Live app: &lt;a href="https://pockettrail-6dyu.onrender.com" rel="noopener noreferrer"&gt;https://pockettrail-6dyu.onrender.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The hosted demo runs in &lt;strong&gt;sample mode&lt;/strong&gt;. It serves original, hand-written activities and makes no model call, and the page says so. I did not put a paid model or voice key on the public instance. The real model path works locally, which is what the numbers below come from.&lt;/p&gt;

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


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/trakshan-mishra" rel="noopener noreferrer"&gt;
        trakshan-mishra
      &lt;/a&gt; / &lt;a href="https://github.com/trakshan-mishra/pockettrail" rel="noopener noreferrer"&gt;
        pockettrail
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A little less screen. A little more outside. Short nature activities with offline saved walks.
    &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;PocketTrail&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;A little less screen. A little more outside.&lt;/p&gt;
&lt;p&gt;PocketTrail turns your time, setting, mood and outdoor conditions into three gentle nature activities. Save a walk on your device, then take a pause outdoors or by a window. Saved activity text works without a connection. Optional narration is available when ElevenLabs is configured.&lt;/p&gt;
&lt;p&gt;Live demo: &lt;a href="https://pockettrail-6dyu.onrender.com" rel="nofollow noopener noreferrer"&gt;https://pockettrail-6dyu.onrender.com&lt;/a&gt; (free instance, so the first load after idle can take about a minute). The hosted demo runs in sample mode: it serves authored activities with no model calls and no voice. Model generation and narration need the configuration described below.&lt;/p&gt;
&lt;p&gt;Created during the Hacktoberfest Week 1 2026 &lt;strong&gt;Touch Grass&lt;/strong&gt; challenge. This repository covers Week 1 only.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Run locally&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;Requires Node.js 24 and Python 3.13+.&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;cp .env.example .env
bash scripts/dev.sh&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Open &lt;a href="http://127.0.0.1:8000" rel="nofollow noopener noreferrer"&gt;http://127.0.0.1:8000&lt;/a&gt;. The script builds the production frontend so offline caching can be tested locally. For interface development run the backend separately and use…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/trakshan-mishra/pockettrail" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Run it locally with &lt;code&gt;bash scripts/dev.sh&lt;/code&gt;. The README covers Ollama, Backboard and ElevenLabs settings.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Stack.&lt;/strong&gt; React and TypeScript on the front, FastAPI with Pydantic on the back, SQLite for cache and usage quotas, IndexedDB on the device for saved walks. One Docker image builds the frontend and serves it from FastAPI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What the model does, and what it does not.&lt;/strong&gt; My first instinct was to let the model write the activities. I dropped that quickly. A small model gets confident about things it cannot know, and this app tells people to go stand somewhere.&lt;/p&gt;

&lt;p&gt;So the instructions are written by me, in a catalog of about fifteen activities per context. The model does two jobs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pick three distinct activities that fit the request.&lt;/li&gt;
&lt;li&gt;Write a short personal "focus" line for each.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The server then checks the output against the catalog (setting, equipment, evening and rain rules), rejects duplicates and unknown activities, and assigns durations that sum exactly to the requested time. A rainy request can never return a daylight-only activity. A window request only draws from the window catalog. One validation repair is allowed; after that the request fails instead of looping.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Two small models, same cases.&lt;/strong&gt; I ran &lt;code&gt;qwen2.5-coder:3b&lt;/code&gt; and Phi-3-mini-128k through Ollama on my laptop, three identical requests each.&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;Valid packs&lt;/th&gt;
&lt;th&gt;Mean latency&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;qwen2.5-coder:3b&lt;/td&gt;
&lt;td&gt;3 / 3&lt;/td&gt;
&lt;td&gt;29.8 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phi-3-mini-128k&lt;/td&gt;
&lt;td&gt;3 / 3&lt;/td&gt;
&lt;td&gt;67.4 s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This is a small pilot, not a benchmark. Both passed the structural checks, so the more useful result was in what the checks missed when I read the outputs. Qwen suggested a stroll in its introduction even though the preferences said stationary. Phi claimed a heartbeat could be synchronized with breathing. I changed the introduction to authored text and added a rejection rule for heartbeat claims. Free-text wording can still get past a keyword check, so a human should read any pack before it goes in a demo. I also found the focus lines from the small model are sometimes generic or repeated. I did not fix that.&lt;/p&gt;

&lt;p&gt;Qwen is a coding model. I used it because it was already installed, not because it is the best choice for this task.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Other checks.&lt;/strong&gt; A script went through all 108 combinations of context, setting, mood and duration against the catalog and schema. A Docker image built and served the health endpoint as a non-root user, and I fixed a volume-permission failure that showed up there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keeping spend small.&lt;/strong&gt; Identical requests reuse a cached response. Every hosted model attempt, including the repair, reserves a quota slot in SQLite before the call is made. Narration only runs when you press "Add voice", and it takes a saved pack ID, not arbitrary text. These are call and character limits, not dollar caps, and the README says so.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Offline.&lt;/strong&gt; The shell, fonts, saved packs and any downloaded audio are stored locally. Offline phone use covers saved walks. Generating a new pack still needs a connection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Timers.&lt;/strong&gt; Walk Mode has an optional timer with a short chime made locally with Web Audio, plus vibration where the browser supports it. I tested this on desktop only. Phones can suspend audio and timers when the screen is locked, so I do not claim pocket reliability.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I did not finish
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A real outdoor trial. I tested the flow in a desktop browser, not on a walk, so I have no field results to report.&lt;/li&gt;
&lt;li&gt;A physical phone test of offline reload, vibration and lock-screen behavior.&lt;/li&gt;
&lt;li&gt;Hosted model and voice. The code supports Backboard and ElevenLabs, but I made no real calls with either, so I am not listing them as integrations.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;The model here is replaceable. It is called through a thin adapter, so the same app ran against two different local models and can point at a hosted one by changing a few environment variables. That made the comparison above possible, and it meant I could read the model card, run it on my own machine, and keep preferences on the device when I chose local inference.&lt;/p&gt;

&lt;p&gt;It also made the failures visible. With an open-weight model I could compare two models on the same inputs and see exactly where each one made things up. That is why most of the safety work ended up in the catalog and the validator, and not in a prompt asking the model to behave.&lt;/p&gt;

&lt;p&gt;If you choose a hosted model, your preferences go to that provider. With local Ollama they stay on your machine.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>stepfix: tech support that never writes the command for you</title>
      <dc:creator>Trakshan Mishra</dc:creator>
      <pubDate>Mon, 05 Oct 2026 06:47:28 +0000</pubDate>
      <link>https://dev.to/trakshanmishra/stepfix-tech-support-that-never-writes-the-command-for-you-5hdi</link>
      <guid>https://dev.to/trakshanmishra/stepfix-tech-support-that-never-writes-the-command-for-you-5hdi</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-weekend-2026-10-01"&gt;Hacktoberfest Weekend Challenge: Build for a Friend&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;Most of us have a friend or a parent who calls when the Wi-Fi breaks. Helping over the phone means reading commands out letter by letter, or telling them to paste something they can't read. I wanted something I could send them instead, that is careful in the same way I'd be.&lt;/p&gt;

&lt;p&gt;stepfix is a support chat for people who aren't technical. You describe the problem in plain words, like "my Wi-Fi shows no networks". It asks a couple of questions, then walks you through the fix one step at a time.&lt;/p&gt;

&lt;p&gt;Each step is a card with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the exact command to copy&lt;/li&gt;
&lt;li&gt;why we're running it&lt;/li&gt;
&lt;li&gt;what you should see if it worked&lt;/li&gt;
&lt;li&gt;"it worked" and "it didn't" buttons, so the next step depends on what actually happened&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You run every command yourself. stepfix never touches your machine.&lt;/p&gt;

&lt;p&gt;The one rule I didn't want to bend: &lt;strong&gt;the AI never writes a command.&lt;/strong&gt; Every command comes from a public, reviewed library of 63 scripts covering Wi-Fi and Bluetooth on Ubuntu and Windows 11, plus a few developer-tool fixes. Each one has a risk level, and 39 of them only read information without changing anything. The model picks which step comes next. The app fills in the exact text. If the model tries to slip a command into its reply anyway, a scanner strips it out.&lt;/p&gt;

&lt;p&gt;Why so strict? "Open your terminal and paste this" is exactly how a lot of scams work now. Someone who doesn't know what a command does can't tell a fix from an attack. So stepfix only hands out commands that anyone can read on GitHub first.&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/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8fter7636oug1p5k5pgy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8fter7636oug1p5k5pgy.gif" alt="stepfix demo" width="720" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The demo is a live run on Ubuntu, unedited:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;"My laptop says it's connected to Wi-Fi but nothing loads"&lt;/li&gt;
&lt;li&gt;It asks one question at a time (which OS, when it started) and fills in the case panel as I answer&lt;/li&gt;
&lt;li&gt;It switches to step-by-step fixing and shows the first card: a read-only check, with "why" and "what you should see"&lt;/li&gt;
&lt;li&gt;I click "I ran it" without pasting anything. It won't move on: a check with no output proves nothing, so it asks for the output&lt;/li&gt;
&lt;li&gt;I type "it got fixed". It still doesn't mark the case resolved, because nothing was verified&lt;/li&gt;
&lt;li&gt;I stop, and get a report I can copy or download. It says plainly that nobody has been contacted&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That last part is the point. It would rather stop and hand you an honest report than guess at a fix.&lt;/p&gt;

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


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/trakshan-mishra" rel="noopener noreferrer"&gt;
        trakshan-mishra
      &lt;/a&gt; / &lt;a href="https://github.com/trakshan-mishra/stepfix" rel="noopener noreferrer"&gt;
        stepfix
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      AI tech support that never writes the command for you. Open-weight models, a reviewed public script library, you run every step.
    &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;stepfix&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;stepfix is an AI tech-support helper for people who are not technical. It explains each diagnostic or repair step, and the person runs every command themselves.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Safety model&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;The AI is never allowed to write commands. Every command comes from the reviewed, public script library in &lt;code&gt;library/*.yaml&lt;/code&gt;, which is linted for dangerous patterns. This is the opposite of “paste this into your terminal” scams: the model selects a bounded step, while the application supplies the exact command and explains what it does.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Models&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;Open-weight models only: gpt-oss-20b and gpt-oss-120b on Groq, with GLM-4.7-flash on Cloudflare Workers AI as the fallback, and a scripted playbook if every model is down. No closed models are used.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Run locally&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;You need Node.js, npm, a Cloudflare account with Workers AI access, and a Groq API key.&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm install
cp .dev.vars.example .dev.vars
npx wrangler login
npm run dev&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Fill in the required values…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/trakshan-mishra/stepfix" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


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

&lt;p&gt;stepfix runs on Cloudflare Workers with Durable Objects, using the open-source Cloudflare Agents SDK and the AI SDK. Every support session is its own Durable Object. A separate Coordinator object handles admission and keeps a quota ledger, so a free-tier app doesn't fall over the moment a few people show up.&lt;/p&gt;

&lt;p&gt;There are two roles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Support&lt;/strong&gt; asks questions and fills in a case file: OS, problem area, symptom, when it started, what changed. It can't hand off until the case file is complete.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Technician&lt;/strong&gt; only sees the scripts for that OS and problem area, and recommends one at a time based on what the previous step showed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Models:&lt;/strong&gt; gpt-oss-20b for support and gpt-oss-120b for the technician, both on Groq. GLM-4.7-flash on Cloudflare Workers AI is the fallback. Before every model call, the router reserves quota. If every model is down, a scripted playbook continues the case instead of leaving the person stuck.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The script library&lt;/strong&gt; is YAML. A linter rejects dangerous patterns, like piping a download straight into a shell or recursive deletes. It's then compiled and hashed, so the app only serves what's in the reviewed file. There are 462 unit tests, two browser tests that click through a full repair and a stop-and-report, and 13 simulated support conversations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The best part of this weekend was a bug.&lt;/strong&gt; When I first switched from mock mode to real models, stepfix answered nothing. No error, no message, just silence.&lt;/p&gt;

&lt;p&gt;It turned out the quota ledger used JavaScript &lt;code&gt;Map&lt;/code&gt;s, and the Durable Object saves its state as JSON. &lt;code&gt;JSON.stringify(new Map())&lt;/code&gt; is &lt;code&gt;{}&lt;/code&gt;. After a restart, the ledger came back as empty plain objects, the first &lt;code&gt;.get()&lt;/code&gt; threw, and the error was swallowed before it reached the user.&lt;/p&gt;

&lt;p&gt;The fix had three parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;maps that serialize properly&lt;/li&gt;
&lt;li&gt;loading old broken state without crashing&lt;/li&gt;
&lt;li&gt;falling back to the playbook instead of going silent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While testing that, I found the technician had never actually seen the script catalog. It was loaded with &lt;code&gt;require()&lt;/code&gt;, which doesn't exist in a Worker, and the &lt;code&gt;catch&lt;/code&gt; hid that too. Two silent failures in one path. Now there's a test for each.&lt;/p&gt;

&lt;p&gt;Then I recorded myself using it and watched it back. In one reply, the model wrote "run: ip -brief address" right in the chat. My scanner missed it for two reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;its list of command names didn't include a single command from my own library&lt;/li&gt;
&lt;li&gt;it ignored anything near the word "Wi-Fi", which is every Wi-Fi conversation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now the scanner learns every command from the library itself, and the exact text from that recording is a test case.&lt;/p&gt;

&lt;p&gt;I used AI coding tools along the way, mostly Claude for debugging: going through logs with me and watching my screen recordings back to find where the flow broke. The Map bug and the scanner gaps both came out of those sessions.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Trust.&lt;/strong&gt; The thing that decides what runs on someone's computer should be inspectable. The script library is public. The models are open-weight, so you know exactly what's behind the chat, and so does anyone auditing it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fallback only works because the weights are open.&lt;/strong&gt; stepfix's main and backup providers are different companies serving open-weight models. When Groq rate-limits, the same kind of model takes over on Cloudflare. With a single closed model, "fallback" means "nothing".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It can go local.&lt;/strong&gt; Because the models are open-weight, the next step is running the whole thing on the person's own machine, for anyone who doesn't want their system output leaving it. That isn't built yet, but nothing in the design blocks it.&lt;/p&gt;

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

&lt;p&gt;Overall. I didn't use the partner technologies for this one.&lt;/p&gt;

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