<?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: James Divis</title>
    <description>The latest articles on DEV Community by James Divis (@jamesdivis).</description>
    <link>https://dev.to/jamesdivis</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%2F4170142%2Fdfc7142c-7dd4-499b-b479-43ac55f2d2db.png</url>
      <title>DEV Community: James Divis</title>
      <link>https://dev.to/jamesdivis</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jamesdivis"/>
    <language>en</language>
    <item>
      <title>grasscast: a "should I go outside?" forecast that learns your taste from a few dozen outings (TabPFN + Temporal)</title>
      <dc:creator>James Divis</dc:creator>
      <pubDate>Thu, 08 Oct 2026 14:10:38 +0000</pubDate>
      <link>https://dev.to/jamesdivis/grasscast-a-should-i-go-outside-forecast-that-learns-your-taste-from-a-few-dozen-outings-jac</link>
      <guid>https://dev.to/jamesdivis/grasscast-a-should-i-go-outside-forecast-that-learns-your-taste-from-a-few-dozen-outings-jac</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week1-2026-10-05"&gt;Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;Weather apps tell you it'll be 64°F with 10 mph wind on Saturday. They can't tell you whether &lt;em&gt;you&lt;/em&gt; will enjoy a hike in that, or whether Thursday morning would be the better bet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;grasscast&lt;/strong&gt; is a small command-line tool that answers &lt;em&gt;"when should I go outside this week?"&lt;/em&gt; for one person. You keep a tiny log of your outings, one line each: date, start time, hours, activity, and how much you enjoyed it on a 1–5 scale. grasscast joins each outing with the weather you had, learns your taste with &lt;strong&gt;TabPFN&lt;/strong&gt; (an open-weight tabular foundation model), scores every daylight window in the next 7 days, and gives back:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the &lt;strong&gt;best window for each day&lt;/strong&gt;, with the chance you'd rate it 4–5 stars,&lt;/li&gt;
&lt;li&gt;a one-line &lt;strong&gt;"why"&lt;/strong&gt; that compares it with the conditions of your best outings,&lt;/li&gt;
&lt;li&gt;an &lt;strong&gt;&lt;code&gt;.ics&lt;/code&gt; file&lt;/strong&gt; so the plan goes into your calendar and you can close the laptop.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The screen time is the point. Logging an outing is one command when you get home (&lt;code&gt;grasscast log hike 5 --hours 2.5&lt;/code&gt;), and the plan is something you glance at once a week, or once a morning if you let it run on a schedule. Everything else happens outside.&lt;/p&gt;

&lt;p&gt;It's for anyone who has a vague sense of "I like hiking when it's cool and calm" and would rather have a tool learn the details than check four weather apps.&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%2Fe90kz433b9zw2bb15th0.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%2Fe90kz433b9zw2bb15th0.gif" alt="grasscast demo: logging an outing, planning the week, and a durable run surviving a flaky network" width="800" height="599"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The demo above is a real terminal recording (asciinema → GIF) of the commands below, run against the bundled demo log.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Honesty note on the demo data:&lt;/strong&gt; I don't have a real outing log yet, so the bundled &lt;code&gt;examples/outings.sample.csv&lt;/code&gt; is &lt;strong&gt;synthetic&lt;/strong&gt;. It uses real Salt Lake City weather from April to October 2026 and a made-up person, whose ratings come from a hidden formula plus noise. That turned out to be useful: because the true taste is known, I can check whether the model actually learns it (see &lt;em&gt;How I Built It&lt;/em&gt;).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here's the weekly plan it produced on Oct 7 (lightly trimmed):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ grasscast plan --ics plan.ics
grasscast: your best windows to get outside (learned from 63 logged outings)

Best window each day. 'chance' = how likely you'd rate it 4-5 stars; '?' = the model is extrapolating.

      GO  Wed Oct 07  17:00-18:30  bike  chance  67%  likely 2-5★   feels 75°F, wind 7 mph, clouds 0%, 1% rain
          why: warmer than you like
*     GO  Thu Oct 08  10:00-11:30  bike  chance  95%  likely 4-5★   feels 67°F, wind 3 mph, clouds 1%, 1% rain
          why: right in your sweet spot
      GO  Fri Oct 09  09:00-10:30  bike  chance  91%  likely 4-5★   feels 62°F, wind 7 mph, clouds 38%, 2% rain
          why: higher rain risk than you like
     GO?  Sun Oct 11  12:00-13:30  bike  chance  91%  likely 4-5★   feels 68°F, wind 13 mph, clouds 8%, 81% rain
          why: windier than you like; gustier than you like; higher rain risk than you like
          ? untested: you've never logged an outing in gusts this strong, rain risk this high; treat as a guess
     ...
Your sweet spot (from 4-5 star outings): feels 55°F-73°F, wind under 9 mph.
* = top pick of the week. Built with PriorLabs-TabPFN.

Wrote 7 windows to plan.ics (import it into any calendar app).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Look at Sunday. The model gives a bike ride in an 81%-rain forecast a 91% chance of being great, which is obviously wrong. It's wrong for an honest reason: the synthetic person almost never went out in rain (Salt Lake City summers are dry; only &lt;strong&gt;one&lt;/strong&gt; of 63 outings had a rain chance above 40%), so the model has no evidence either way. Instead of pretending, grasscast detects that the window sits outside anything in your log, marks it &lt;code&gt;GO?&lt;/code&gt;, and ranks it below the windows it actually has evidence for. Thursday is the top pick, not Sunday. Log a couple of drizzly walks and the model learns the rest.&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/divisCorp" rel="noopener noreferrer"&gt;
        divisCorp
      &lt;/a&gt; / &lt;a href="https://github.com/divisCorp/grasscast" rel="noopener noreferrer"&gt;
        grasscast
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Personal outdoor-window forecast: learns the weather you enjoy with TabPFN, optional durable Temporal workflow
    &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;grasscast 🌱&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;When should &lt;em&gt;I&lt;/em&gt; go outside this week?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Weather apps tell you it'll be 64°F and cloudy. They can't tell you whether &lt;em&gt;you'll&lt;/em&gt; enjoy a hike in that. grasscast learns that from a tiny log of your own outings, scores every daylight window in the next 7 days, and puts the best ones in your calendar. After that you can close the laptop.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Learns from a few dozen outings.&lt;/strong&gt; It uses &lt;a href="https://github.com/PriorLabs/TabPFN" rel="noopener noreferrer"&gt;TabPFN&lt;/a&gt;, an open-weight tabular foundation model that learns in context from small tables. There's no training loop and no tuning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runs locally on a CPU.&lt;/strong&gt; Your outing log never leaves your machine. The only network call sends your latitude and longitude to &lt;a href="https://open-meteo.com" rel="nofollow noopener noreferrer"&gt;Open-Meteo&lt;/a&gt; (free, no API key). With a cached forecast it runs with no network at all.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Says when it's guessing.&lt;/strong&gt; Each window gets a probability and a range. If the forecast is outside anything you've…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/divisCorp/grasscast" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Python, MIT licensed, about 1,000 lines plus 17 tests. Quick start:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--index-url&lt;/span&gt; https://download.pytorch.org/whl/cpu &lt;span class="nt"&gt;--extra-index-url&lt;/span&gt; https://pypi.org/simple &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;".[dev]"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;GRASSCAST_LAT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;40.7608 &lt;span class="nv"&gt;GRASSCAST_LON&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;-111&lt;/span&gt;.8910 &lt;span class="nv"&gt;GRASSCAST_TZ&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;America/Denver
grasscast plan &lt;span class="nt"&gt;--log&lt;/span&gt; examples/outings.sample.csv &lt;span class="nt"&gt;--ics&lt;/span&gt; plan.ics
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

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

&lt;p&gt;&lt;strong&gt;The open pieces:&lt;/strong&gt; &lt;a href="https://github.com/PriorLabs/TabPFN" rel="noopener noreferrer"&gt;TabPFN&lt;/a&gt; v2 (open weights, local CPU inference) for the model, &lt;a href="https://github.com/temporalio/temporal" rel="noopener noreferrer"&gt;Temporal&lt;/a&gt; (open-source server plus Python SDK) for durable execution, and &lt;a href="https://open-meteo.com" rel="noopener noreferrer"&gt;Open-Meteo&lt;/a&gt; open weather data (free, no API key).&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Why TabPFN is the right model for a personal log
&lt;/h3&gt;

&lt;p&gt;A personal outing log is tiny: 20, 40, maybe 100 rows. That's the regime where classic ML struggles and where TabPFN is built to shine. TabPFN is a transformer pretrained on millions of synthetic tabular problems. At &lt;code&gt;fit()&lt;/code&gt; time it doesn't run gradient descent. It reads your whole table &lt;em&gt;as context&lt;/em&gt; and predicts in a single forward pass. So there's no training loop, no hyperparameter search, and nothing to overfit with a grid search on 40 rows.&lt;/p&gt;

&lt;p&gt;The part I like most is that TabPFN's regressor returns a &lt;strong&gt;full predictive distribution&lt;/strong&gt;, not just a number. grasscast uses three things from it:&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="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;full&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;score&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mean&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;                                    &lt;span class="c1"&gt;# expected rating
&lt;/span&gt;&lt;span class="n"&gt;low&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;quantiles&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;quantiles&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;      &lt;span class="c1"&gt;# 80% band
&lt;/span&gt;&lt;span class="n"&gt;p_great&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;criterion&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;cdf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;logits&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mf"&gt;3.5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# P(you rate it 4-5 stars)  (simplified)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Windows are ranked by &lt;code&gt;p_great&lt;/code&gt;. "95% chance this is a great outing" is something a person can act on in a way that "predicted 4.3" isn't.&lt;/p&gt;

&lt;p&gt;Setup is one line. Fitting on 63 outings and scoring all ~200 candidate windows of the week takes about 5 seconds on a plain CPU (no GPU):&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="n"&gt;TabPFNRegressor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_default_for_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ModelVersion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;V2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cpu&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                           &lt;span class="n"&gt;categorical_features_indices&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ACTIVITY_COL&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;(I pinned the v2 weights because they download without an account, so anyone can clone and run this.)&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Features: train on forecasts, not hindsight
&lt;/h3&gt;

&lt;p&gt;For each outing, grasscast summarizes the hourly weather during it: feels-like temperature, humidity, rain amount, max rain chance, cloud, sunshine, mean wind, max gust, plus start hour, weekend, and activity (as a categorical feature, so one model learns that you like biking warmer than running).&lt;/p&gt;

&lt;p&gt;One detail matters a lot. Past weather comes from Open-Meteo's &lt;strong&gt;historical *forecast&lt;/strong&gt;* archive: what the forecast said at the time, not the reanalysis of what actually happened. The model is trained on the same kind of number it sees at prediction time, so it learns "I enjoy days &lt;em&gt;forecast&lt;/em&gt; like this", which is the question you're actually asking.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Does it actually learn? (yes, and faster than the baselines)
&lt;/h3&gt;

&lt;p&gt;Since the synthetic person's real taste is known, I could measure it. &lt;code&gt;grasscast eval&lt;/code&gt; runs repeated 5-fold cross-validation against simple baselines, plus a learning curve on held-out outings:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;5-fold cross-validation, repeated twice (lower MAE is better):
                    model  MAE (stars)  rank corr
       TabPFN (grasscast)         0.59       0.87
            random forest         0.73       0.82
         ridge regression         0.89       0.76
     average per activity         1.13       0.30
always guess your average         1.31      -0.20

Held-out MAE as the log grows (trimmed; full table in demo/eval.txt):
outings  TabPFN  avg/activity  random forest
10         1.06          1.27           1.15
20         0.95          1.29           1.07
40         0.66          1.16           0.78
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;TabPFN is the most accurate at every log size, and its lead over the random forest is largest when the log is smallest (10–20 outings), which is exactly where a personal tool spends its first month. The &lt;code&gt;eval&lt;/code&gt; command works on your own log too, so you can see how well it knows &lt;em&gt;you&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  4. Making it durable with Temporal
&lt;/h3&gt;

&lt;p&gt;The useful version of this tool runs by itself at 6 AM. Over a week of mornings, a free weather API will time out at some point and a laptop will go to sleep mid-run. So the same pipeline also ships as a &lt;strong&gt;Temporal workflow&lt;/strong&gt; with four activities:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;build_taste_table  -&amp;gt;  get_forecast  -&amp;gt;  score_windows (TabPFN)  -&amp;gt;  write_plan (.txt + .ics)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Weather calls retry with exponential backoff (capped at 2 minutes) for up to 30 minutes.&lt;/li&gt;
&lt;li&gt;Each completed step is recorded in the workflow history, so a crashed worker resumes at the next step without re-fetching anything.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--cron "0 6 * * *"&lt;/code&gt; refreshes the calendar file every morning.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;grasscast durable --local&lt;/code&gt; spins up Temporal's open-source dev server in-process. No account, no cloud.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To show it working, there's a chaos switch that makes a percentage of weather calls fail:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ GRASSCAST_CHAOS=0.75 grasscast durable --local      # log prefixes trimmed
15:19:19 build_taste_table: start (attempt 1)
15:19:19 build_taste_table: attempt 1 failed: chaos monkey: simulated flaky network -&amp;gt; Temporal will retry
15:19:20 build_taste_table: start (attempt 2)
   ... attempts 2-4 also fail; Temporal backs off 1s, 2s, 4s, 8s between tries ...
15:19:34 build_taste_table: start (attempt 5)
15:19:34 build_taste_table: done
15:19:35 get_forecast: attempt 1 failed ... attempt 2 failed ...
15:19:39 get_forecast: done
15:19:44 score_windows: done
15:19:44 write_plan: done
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And a nastier test (&lt;code&gt;demo/crash_resume.sh&lt;/code&gt;): start a worker, &lt;strong&gt;&lt;code&gt;kill -9&lt;/code&gt; it in the middle of the TabPFN step&lt;/strong&gt;, then start a fresh worker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[worker1] build_taste_table: done
[worker1] get_forecast: done
[worker1] score_windows: start (attempt 1)
== worker #1 killed with SIGKILL during score_windows
[worker2] score_windows: start (attempt 2)    &amp;lt;- picks up exactly here; no weather re-fetch
[worker2] score_windows: done
[worker2] write_plan: done
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The new worker never re-runs the two weather steps. Their results come from Temporal's history.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Tests
&lt;/h3&gt;

&lt;p&gt;17 pytest tests cover feature extraction, the planner (daylight-only windows, one pick per day, untested windows demoted, valid RFC 5545 calendar output), the weather cache and offline mode, the real TabPFN model learning a hidden preference, an end-to-end plan, and the Temporal workflow surviving injected network failures on a real local server. The tests fake the weather API, so they run without a network.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Your outing log is sensitive data.&lt;/strong&gt; It's a record of when you leave home, for how long, and where you like to go. That's exactly the data I don't want to upload to a third-party API so it can tell me "go Thursday." With open weights, it never leaves my machine. The only thing sent anywhere is a latitude and longitude to a free weather service. I verified the whole plan also runs inside a network namespace with &lt;strong&gt;no network at all&lt;/strong&gt; once the forecast is cached (&lt;code&gt;demo/offline-run.txt&lt;/code&gt;). It works at a trailhead with one bar of signal, or none.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It costs nothing to run, forever.&lt;/strong&gt; No API key, no per-call billing, no account. TabPFN v2 runs on a plain CPU in seconds, the Temporal dev server is a local binary, and Open-Meteo is free. A tool you're supposed to forget about for a week can't come with a monthly bill or an API key that expires.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Open models give you the whole distribution, not a sentence.&lt;/strong&gt; Because I run TabPFN myself, I get its full predictive distribution and can compute "probability of a 4–5 star outing" exactly. A closed chat API would give me a confident-sounding paragraph. I'd have no calibrated probability and no way to tell when it's extrapolating. The &lt;code&gt;untested&lt;/code&gt; flag depends on being able to inspect both the data and the model's uncertainty.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I can swap and inspect every layer.&lt;/strong&gt; The model version is one line (v2 today, a newer TabPFN tomorrow), the weather source is a function, and the durability layer is a self-hosted open-source server rather than someone's SaaS. If a piece disappears, I replace that piece without rewriting the tool.&lt;/p&gt;

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

&lt;p&gt;Full disclosure: grasscast was built with an AI coding agent, which the challenge rules allow. I didn't export the session to DevRelay. In place of the session, the repo includes everything needed to check the work: &lt;code&gt;demo/record_demo.sh&lt;/code&gt; regenerates the demo GIF from real runs, &lt;code&gt;demo/crash_resume.sh&lt;/code&gt; reproduces the kill-the-worker test, and the captured outputs (&lt;code&gt;demo/eval.txt&lt;/code&gt;, &lt;code&gt;demo/durable-chaos.txt&lt;/code&gt;, &lt;code&gt;demo/crash-resume.txt&lt;/code&gt;, &lt;code&gt;demo/offline-run.txt&lt;/code&gt;) are unedited.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of TabPFN&lt;/strong&gt;: TabPFN is the model at the center of grasscast. In-context regression on a tiny personal log, using the full predictive distribution for P(4–5★) ranking and uncertainty bands, benchmarked against baselines with a learning curve.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Temporal&lt;/strong&gt;: the plan pipeline runs as a durable Temporal workflow with retried weather activities, crash-resume (demonstrated with &lt;code&gt;kill -9&lt;/code&gt;), and a cron schedule, all on the local open-source dev server.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Built with PriorLabs-TabPFN · Weather data by &lt;a href="https://open-meteo.com" rel="noopener noreferrer"&gt;Open-Meteo.com&lt;/a&gt; (CC BY 4.0)&lt;/em&gt;&lt;/p&gt;

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