<?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: JinYi123456</title>
    <description>The latest articles on DEV Community by JinYi123456 (@jinyi123456).</description>
    <link>https://dev.to/jinyi123456</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%2F4174845%2Fce43baaf-a484-4627-995b-fbd149abe4b2.png</url>
      <title>DEV Community: JinYi123456</title>
      <link>https://dev.to/jinyi123456</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jinyi123456"/>
    <language>en</language>
    <item>
      <title>Helio: an open-weight AI that makes you touch grass — and refuses to believe you did</title>
      <dc:creator>JinYi123456</dc:creator>
      <pubDate>Sun, 11 Oct 2026 18:36:20 +0000</pubDate>
      <link>https://dev.to/jinyi123456/helio-an-open-weight-ai-that-makes-you-touch-grass-and-refuses-to-believe-you-did-2hm5</link>
      <guid>https://dev.to/jinyi123456/helio-an-open-weight-ai-that-makes-you-touch-grass-and-refuses-to-believe-you-did-2hm5</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week1-2026-10-05"&gt;Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A photo of your keyboard does not count. I checked.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;&lt;strong&gt;Helio&lt;/strong&gt; is an offline-first PWA that gets you off the screen and into the world — built on open-weight models, running on your own machine. It does two jobs no other outdoors app does:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;It tells you &lt;em&gt;when&lt;/em&gt; to go.&lt;/strong&gt; A tiny tabular foundation model — &lt;strong&gt;TabPFN&lt;/strong&gt; — reads ten years of your city's weather history plus the days you personally walked, and scores the next seven days for grass-worthiness. On CPU. In about a second. No training loop — it learns in-context.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It verifies that you actually went.&lt;/strong&gt; When you come back and photograph what you found, a local &lt;strong&gt;Gemma&lt;/strong&gt; vision model checks the photo against the mission's proof criteria — &lt;em&gt;on your device&lt;/em&gt;. No upload. If the photo is your desk, the verdict is "not grass".&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Reviewing the loop visually — the dial that reads a decade of weather, the door that hands you one whisper, the pocket screen that sends you away, the stamp that only a real photo earns:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy8w9q89pbrxjnovcx2vd.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%2Fy8w9q89pbrxjnovcx2vd.png" alt="helio's dial — today's grass window and the seed card" width="780" height="1688"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Between those two poles sits the experience:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;the dial&lt;/strong&gt; — a sun-compass that lights up the best outdoor hours of today, over a one-line weather strip (today's high/low, rain, cloud, the week ahead); one tap on &lt;em&gt;use my location&lt;/em&gt; finds your actual sky — Helio reverse-geocodes you, keeps the nearest baked city's decade of history if you're within 50 km, and otherwise builds the climate rules from two years of open weather archive for your own coordinates&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;the door&lt;/strong&gt; — a Mastra + Gemma &lt;em&gt;mission compiler&lt;/em&gt; writes you a tiny whispered assignment ("Find the oldest standing thing within walking distance…"), and a &lt;strong&gt;Temporal workflow&lt;/strong&gt; holds that mission on a durable timer until its grass window&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;the pocket screen&lt;/strong&gt; — literally tells you the screen is done now&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;the proof&lt;/strong&gt; — the on-device verdict, stamped with confidence and what the model saw&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;the journal &amp;amp; meadow&lt;/strong&gt; — every verified walk gets a 5-7-5 haiku and grows a meadow with a 12-species field dex&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The design rule from commit one: &lt;strong&gt;every dependency is a leaf node&lt;/strong&gt;. Sever any edge of the graph and the product still works, labelled honestly — the dial shows climatology when the model is away, hand-written seeds walk in when the LLM is down, the browser reads the whisper when the voice API is missing. It survives airplane mode, backcountry, and a dead wifi router — which is exactly what an outdoors app should do. &lt;em&gt;(Fun failure mode: it also survives the wrong photo. Try your keyboard.)&lt;/em&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live:&lt;/strong&gt; &lt;a href="https://helio-agent.onrender.com" rel="noopener noreferrer"&gt;https://helio-agent.onrender.com&lt;/a&gt; (free Render instance — first load may take ~1 min to wake)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repo:&lt;/strong&gt; &lt;a href="https://github.com/JinYi123456/helio" rel="noopener noreferrer"&gt;https://github.com/JinYi123456/helio&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;79-second walkthrough&lt;/strong&gt; — the whole loop recorded live: onboarding, helio locating you and re-reading the sky over your own coordinates, the mission compiled by Gemma, the photo verified on-device, the journal that remembers where you were standing, and the meadow grown:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/ar8bz7y_dWM" rel="noopener noreferrer"&gt;https://youtu.be/ar8bz7y_dWM&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;90-second local run:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm ci
ollama pull gemma4:e2b
npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On a laptop with no camera, the proof screen falls back to file upload — the app treats that as a first-class path, not an error.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp37bjqncbyy6ry7o8hrg.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%2Fp37bjqncbyy6ry7o8hrg.png" alt="the door — one whisper, one proof criterion" width="780" height="1688"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvh82uppglounagx83u4z.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%2Fvh82uppglounagx83u4z.png" alt="the pocket screen — the product that asks to be put away" width="780" height="1688"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzpavtc0jgah2sy7vydpp.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%2Fzpavtc0jgah2sy7vydpp.png" alt="the stamp — a real sprout photo, judged on-device at 95%" width="780" height="1688"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The meadow only grows on verified walks — twelve species to meet, one streak to keep alive without lying:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl1ajd13jj9qntai1x879.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%2Fl1ajd13jj9qntai1x879.png" alt="the meadow and the species dex" width="780" height="1750"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Three services, one loop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apps/web            Vite + React PWA — dial · door · pocket · proof · journal · meadow
services/agent      Hono + Mastra — mission compiler agent, vision verifier, haiku, TTS
services/tabpfn     FastAPI — TabPFN grass-window model + precompute baker
services/tinker     Python — dataset builder + LoRA fine-tune of Helio's whisper voice
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The grass window is the heart. The whole preference chain is ~20 lines:&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="c1"&gt;# services/tabpfn/app/service.py
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;precompute_only&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;                      &lt;span class="c1"&gt;# tiny host? serve the bake
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;load_precomputed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;city_key&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;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;city_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;          &lt;span class="c1"&gt;# TabPFN, in-context, on CPU
&lt;/span&gt;    &lt;span class="n"&gt;scores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;predict_days&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;served&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="sh"&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="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;_mark_model_failed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;city_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;         &lt;span class="c1"&gt;# 600s cooldown — never retry-storm
&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;pre&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;load_precomputed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;city_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# bake wins next
&lt;/span&gt;        &lt;span class="n"&gt;pre&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;served&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;precomputed-fallback&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;pre&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;FileNotFoundError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;scores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;heuristic_scores&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;city_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# still honest
&lt;/span&gt;        &lt;span class="n"&gt;served&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;heuristic&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The mission compiler is one Mastra agent with three tools (grass window, local ground notes, field memory) and a zod'd draft schema. Every mission — model-written or fallback — carries &lt;strong&gt;photo-checkable proof criteria&lt;/strong&gt;, because a mission you can't verify isn't a mission, it's a vibe.&lt;/p&gt;

&lt;p&gt;The vision verdict comes back as strict JSON and is clamped on the way in — a model that hallucinates "confidence: 500" can't stamp anything:&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;// services/agent/src/lib/vision.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;verdictFromRaw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;engine&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="nx"&gt;ms&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="nx"&gt;Verdict&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// … clamp confidence to [0,1], default `seen`, mark `loose` when the&lt;/span&gt;
  &lt;span class="c1"&gt;// pass/fail flag is missing rather than trusting the model's prose.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tests are the contract: &lt;strong&gt;44 vitest specs&lt;/strong&gt; across tools, verdicts, windows, seeds, location matching and the durability layer, plus &lt;strong&gt;21 pytest specs&lt;/strong&gt; for the forecast chain and the bring-your-own-sky coordinates (the model specs run against the real license-accepted model — see below). CI runs both on every push, and a daily GitHub Action re-bakes the grass windows on the real model and commits the JSON — the free-tier host just serves the bake.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Grounded in the real runtime, not in guesses.&lt;/strong&gt; Every claim in this section was verified by running the thing: model versions, ports, timings, and every failure below is a real failure from the build log (kept in &lt;code&gt;docs/building-log.md&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;And when the walk ends, the local model writes it a 5-7-5 haiku and files it away — photo, verdict, weather, stamp, tags:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpgq1mph84nkbxrg6oda8.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%2Fpgq1mph84nkbxrg6oda8.png" alt="the field journal — one verified page" width="780" height="1688"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;TabPFN's weights are license-gated.&lt;/strong&gt; The first server boot tried to open a browser for a one-time license acceptance at 2 AM — and hung waiting on stdin. A server must never block on an interactive login. Fix that became a feature: &lt;code&gt;TABPFN_NO_BROWSER=1&lt;/code&gt;, a 600-second failure cooldown, and the fallback chain above. The polite fix for tiny hosts: &lt;code&gt;app/precompute.py&lt;/code&gt; bakes windows by hand or in CI; a daily Action refreshes them so the hosted demo always serves fresh, model-scored JSON.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Thinking models don't stop thinking.&lt;/strong&gt; &lt;code&gt;gemma4:e2b&lt;/code&gt; is a thinking model — without suppression it burns its whole budget reasoning and never answers. On Ollama's native API &lt;code&gt;think:false&lt;/code&gt; fixes it; over the OpenAI-compatible endpoint you inject &lt;code&gt;reasoning_effort:"none"&lt;/code&gt; via &lt;code&gt;transformRequestBody&lt;/code&gt;. Verified: three clean tokens back instead of a 4,000-token monologue. It's in the code as a provider-scoped transform.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your walks post-date the weather archive.&lt;/strong&gt; Personal "I walked today" labels were silently matching nothing — the archive ends before today. Fix: synthesize feature rows from the walk-time weather (which the app records anyway) and fill the rest from same-day climatology. Now the model actually learns &lt;em&gt;your&lt;/em&gt; good days.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React StrictMode raced the mission compiler.&lt;/strong&gt; Dev double-mount meant two ~70-second Gemma missions started in parallel; one finished and rendered, the other overwrote state — same walk, two different mission titles. An in-flight ref guard fixed it. Production was never affected, but a confused user would have been — and a confused &lt;em&gt;me&lt;/em&gt; at 3 AM definitely was.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Free instances are 512MB; torch is not.&lt;/strong&gt; So the deployed grass-window service deliberately does not install tabpfn — it serves CI-baked windows, recomputes live forecasts when it can, and keeps heuristic scoring as the floor. Zero paid anything, honest &lt;code&gt;served&lt;/code&gt; field on every response so you always know which layer answered.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sentry's "one-line" Mastra integration silently did nothing.&lt;/strong&gt; Node reads an ESM module graph &lt;em&gt;before&lt;/em&gt; any module body runs, so &lt;code&gt;init()&lt;/code&gt; called from app code lands after &lt;code&gt;@mastra/core&lt;/code&gt; has already loaded — and already-loaded modules are never instrumented. The fix that made it real: a four-line, DSN-gated &lt;code&gt;node --import&lt;/code&gt; preload, plus a constructed &lt;code&gt;Mastra&lt;/code&gt; instance (a lone &lt;code&gt;Agent&lt;/code&gt; emits nothing to an exporter). Verified against exactly what Render runs: every compile is now one &lt;code&gt;gen_ai&lt;/code&gt; trace with token usage — and with no DSN, Sentry never enters the process at all.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A mission is a promise with a deadline — that's a workflow, not a cron.&lt;/strong&gt; "Walk when the window opens, prove it before it closes" is exactly the shape Temporal exists for, so every compiled mission starts a &lt;code&gt;missionLifecycle&lt;/code&gt; workflow: sleep until the TabPFN-picked golden hour, a 6-hour expiry, and one &lt;code&gt;markDone&lt;/code&gt; signal the verifier fires when your photo passes. The workflow races &lt;code&gt;sleep()&lt;/code&gt; against &lt;code&gt;condition(done)&lt;/code&gt; and honestly returns &lt;code&gt;"verified"&lt;/code&gt; or &lt;code&gt;"missed"&lt;/code&gt;. Verified for real: a mission that signalled during its sleep completed as &lt;code&gt;Result: "verified"&lt;/code&gt; (2m33s wall time, timer cancelled), and a probe workflow woke at its golden hour, POSTed a &lt;code&gt;ripe&lt;/code&gt; event back into the agent, then closed as &lt;code&gt;"missed"&lt;/code&gt; — all visible in the Temporal UI. With no &lt;code&gt;TEMPORAL_ADDRESS&lt;/code&gt;, the mission still compiles and the API says &lt;code&gt;lifecycle: { scheduled: false }&lt;/code&gt; — leaf node, as promised.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What It Can't Do (Yet)
&lt;/h2&gt;

&lt;p&gt;Honest limits, because the meadow only grows on verified walks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It can't prove &lt;em&gt;you&lt;/em&gt; took the photo.&lt;/strong&gt; The vision check verifies content, not authorship — no location attestation, no sensor checks. A determined cheater with a stock photo of moss could still fool it. Helio is a nudge with a memory, not a cop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The hosted demo answers for any coordinates, but only three skies are pre-baked.&lt;/strong&gt;
&lt;em&gt;Use my location&lt;/em&gt; reverse-geocodes where you are: within 50 km of a baked city you get that city's sky with an honest distance note; anywhere else Helio rounds your coordinates to three decimals and keys the whole pipeline off them — a two-year
climate archive fetched on demand, percentile-derived label rules, and a live
forecast whenever the free forecast endpoint will answer a datacenter IP (archived
climatology for your exact coordinates when it won't). With Torch on your machine
that sky scores on the real model; on the free-tier host it falls back to the
heuristic chain, and the &lt;code&gt;served&lt;/code&gt; field always says which layer answered.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The deployed window service serves precomputed scores.&lt;/strong&gt; Torch doesn't fit a 512MB
free instance, so the real model runs in the daily GitHub Action bake and the service
recomputes live forecasts on top of it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;On-device verdicts take ~45 seconds on CPU.&lt;/strong&gt; That's the honest price of the photo
never leaving your machine. The hosted demo uses cloud Gemma instead; locally, put the
kettle on while it judges your grass.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No accounts, no cross-device sync&lt;/strong&gt; unless you point it at MongoDB Atlas; photos and
logs live in your browser's IndexedDB, exportable and burnable by you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The hosted demo doesn't run a Temporal cluster.&lt;/strong&gt; Durable lifecycle timers need a
Temporal server next to the worker (&lt;code&gt;temporal server start-dev&lt;/code&gt; + &lt;code&gt;npm run temporal:worker&lt;/code&gt;); on the hosted build &lt;code&gt;/api/health&lt;/code&gt; reports &lt;code&gt;temporal: false&lt;/code&gt; and missions are simply not scheduled — everything else works.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Every app that "helps you go outside" should itself be able to survive outside. Closed, server-dependent AI fails exactly when you need it most — on a mountain, on a plane, at the edge of a network. Helio inverts the default: the model runs on your machine, your photos never leave the device, and the whole thing costs nothing to run because there's nothing to meter.&lt;/p&gt;

&lt;p&gt;There's also a philosophical bit I care about: an app that gamifies touching grass shouldn't demand that you stare at it. Helio's pocket screen literally sends you away. Its memory of your walks lives in your browser's IndexedDB, exportable and burnable by you. The weights are open — ollama today, llama.cpp tomorrow, the model belongs to everyone. When the product's pitch is "own your attention", the stack should practice what it preaches. That's what open weights make possible: a tool that can be &lt;em&gt;entirely yours&lt;/em&gt;.&lt;/p&gt;

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

&lt;p&gt;I built Helio in an agentic coding session, and the most useful pattern was treating the agent as an accountable colleague rather than an autocomplete:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Research before code.&lt;/strong&gt; The session started with the partner stack: what TabPFN actually is (in-context tabular foundation model — perfect for weather+habit scoring), which ports were free, which model names were real. Several "obvious" choices died in research rather than in code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Everything ran for real.&lt;/strong&gt; No mocked model calls. The full loop was walked in a browser against real services — the screenshots in this post are that session, including a real sprout photo stamped &lt;strong&gt;95% sure, checked in 42s on CPU&lt;/strong&gt; — and a keyboard photo was &lt;strong&gt;correctly rejected&lt;/strong&gt; on an earlier pass.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Errors became features.&lt;/strong&gt; The three nastiest bugs (license-gated weights, thinking token burn, StrictMode race) each ended up &lt;em&gt;shaping the architecture&lt;/em&gt; — the cooldown, the provider-scoped transform, the in-flight guard. That's the log in &lt;code&gt;docs/building-log.md&lt;/code&gt;, kept unedited.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tests as the contract.&lt;/strong&gt; Before touching the vision normalizer or the fallback chain, specs existed for the ugly cases: null garbage, confidence clamping, missing flags, single-hour windows. The agent's output could then be trusted precisely where trust was earned.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The honest version: the agent was brilliant at breadth (research, scaffolding, tests) and needed supervision at depth (the 2 AM browser-hang was &lt;em&gt;my&lt;/em&gt; reviewer instinct catching a hang the code was happy to wait out). The best results came from the loop — build, verify on the real runtime, and let the failures teach.&lt;/p&gt;

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

&lt;p&gt;All 16 partner categories, with receipts where Helio truly uses the tech (every one of them degrades gracefully when absent — try removing any):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;In Helio&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Render&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;render.yaml&lt;/code&gt; blueprint: agent (Node, serves the PWA) + grass-window service (Python, precompute mode). Free tier, two services, one blueprint.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TabPFN&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The grass window itself — in-context over 10y of weather (or a 2-year archive fetched on demand for coordinates you bring), personal labels from real walks, CPU inference, license-aware fallback chain.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Gemma&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Two jobs: the mission compiler (via Mastra) and the photo proof verifier — both on-device via Ollama.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mastra&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The mission compiler agent: three tools, multi-step, structured draft + repair pass.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ElevenLabs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Whisper TTS for missions, disk-cached; falls back to browser speech.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SerpApi&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;"What's in season right now" ground notes folded into missions.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;MongoDB Atlas&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Field memory over walk notes — &lt;code&gt;$vectorSearch&lt;/code&gt; when configured, RAM otherwise.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Sentry&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Real agent tracing: a DSN-gated &lt;code&gt;--import&lt;/code&gt; preload wires runtime instrumentation, so every mission compile lands in Sentry as one trace — &lt;code&gt;http.server → mission.compile → gen_ai.invoke_agent → gen_ai.chat → http.client&lt;/code&gt; — with model name, input messages and token usage as &lt;code&gt;gen_ai.*&lt;/code&gt; attributes. API errors are captured too.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tinker&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Helio's whisper voice as a trainable artifact: &lt;code&gt;services/tinker/&lt;/code&gt; distills the hand-written field corpus into context→whisper pairs and fine-tunes a small open-weight model over Tinker's SDK; the agent then samples whispers through Tinker's OpenAI-compatible endpoint. Wired end-to-end and env-gated — the training run is waiting on the account's billing/credit activation.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Temporal&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The durable mission lifecycle: every mission is a &lt;code&gt;missionLifecycle&lt;/code&gt; workflow — timer to the TabPFN-picked golden hour, 6-hour expiry, &lt;code&gt;markDone&lt;/code&gt; signal from the verifier. Verified locally end-to-end: signal → &lt;code&gt;Result: "verified"&lt;/code&gt;; timer → &lt;code&gt;ripe&lt;/code&gt; + &lt;code&gt;missed&lt;/code&gt; events posted back to the agent. No &lt;code&gt;TEMPORAL_ADDRESS&lt;/code&gt;? The mission compiles anyway, honestly unscheduled.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tiger Data&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The time-series shadow of the meadow: walks land in a &lt;code&gt;footprints&lt;/code&gt; hypertable (TimescaleDB, via &lt;code&gt;pg&lt;/code&gt;) and &lt;code&gt;GET /api/footprints&lt;/code&gt; returns the server-side 7-day series. Wired end-to-end and env-gated: no &lt;code&gt;TIGER_URL&lt;/code&gt; → the endpoint answers &lt;code&gt;{enabled:false}&lt;/code&gt; and the app is untouched; with a URL it's one key away.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DigitalOcean&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Not used this week — Render carries the hosted demo.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Backboard&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Not used — Helio's memory layer must run offline-first; a hosted control plane is against the grain.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Entire&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Not used.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GitHub Copilot&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Not used.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Arduino&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Not used — no hardware in this build… yet. A sun-dial lamp that glows when your window opens is the obvious next step.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;&lt;em&gt;Helio: proof of grass. MIT-licensed, photos never leave your device, and the meadow only&lt;br&gt;
grows when you actually go. See you outside.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>hacktoberfest</category>
      <category>softwaredevelopment</category>
    </item>
  </channel>
</rss>
