<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Behavior on SAFER Documentation</title><link>https://safer-capstone.pages.dev/developer-docs/overview/behaviors/</link><description>Recent content in Behavior on SAFER Documentation</description><generator>Hugo</generator><language>en</language><atom:link href="https://safer-capstone.pages.dev/developer-docs/overview/behaviors/index.xml" rel="self" type="application/rss+xml"/><item><title>CPM Pipeline</title><link>https://safer-capstone.pages.dev/developer-docs/overview/behaviors/activity-cpm-pipeline/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://safer-capstone.pages.dev/developer-docs/overview/behaviors/activity-cpm-pipeline/</guid><description>&lt;h2 id="scope"&gt;Scope&lt;/h2&gt;
&lt;p&gt;This document defines the runtime CPM pipeline from accelerometer samples to
prediction consumption.&lt;/p&gt;
&lt;h2 id="canonical-flow"&gt;Canonical Flow&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;App.tsx&lt;/code&gt; starts &lt;code&gt;startActivityService()&lt;/code&gt; on mount and calls
&lt;code&gt;stopActivityService()&lt;/code&gt; on cleanup.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;activityService&lt;/code&gt; starts &lt;code&gt;expo-sensors&lt;/code&gt; accelerometer streaming at ~30 Hz.&lt;/li&gt;
&lt;li&gt;Sensor samples are buffered in memory (&lt;code&gt;src/sensors/accelerometer.ts&lt;/code&gt;),
converted from &lt;code&gt;g&lt;/code&gt; to &lt;code&gt;m/s^2&lt;/code&gt;, timestamped from the native sensor event, and
pruned to the last ~75 seconds.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;activityService&lt;/code&gt; treats a CPM window as ready only when it spans nearly 60
seconds, allowing one configured sensor interval of tolerance.&lt;/li&gt;
&lt;li&gt;Every 60 seconds, &lt;code&gt;activityService&lt;/code&gt; reads the most recent ready window and
calls &lt;code&gt;computeCpmFrom60s(...)&lt;/code&gt; in &lt;code&gt;src/model/inferenceActivity.ts&lt;/code&gt;, which
consumes the collected 30 Hz window directly.&lt;/li&gt;
&lt;li&gt;When CPM computation succeeds, one row is written to &lt;code&gt;cpm_history&lt;/code&gt; in SQLite
through &lt;code&gt;src/db/cpmDb.ts&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Callers such as &lt;code&gt;predictionHeatRisk&lt;/code&gt; and &lt;code&gt;PredictionCoreTempCard&lt;/code&gt; consume
&lt;code&gt;getActivityCpm40Average()&lt;/code&gt; from &lt;code&gt;activityService&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="readiness-contract-getactivitycpm40average"&gt;Readiness Contract (&lt;code&gt;getActivityCpm40Average&lt;/code&gt;)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Window: last 40 minutes.&lt;/li&gt;
&lt;li&gt;Minimum history: at least 35 rows.&lt;/li&gt;
&lt;li&gt;Freshness: latest row must be &amp;lt;= 2 minutes old.&lt;/li&gt;
&lt;li&gt;Return: average CPM when ready, otherwise &lt;code&gt;null&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="supporting-references"&gt;Supporting References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Schema: &lt;a href="https://safer-capstone.pages.dev/developer-docs/overview/schemas/cpm-history"&gt;schemas/cpm-history.md&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Diagram: &lt;a href="../diagrams/activity-cpm-pipeline.mmd"&gt;../diagrams/activity-cpm-pipeline.mmd&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="invariants"&gt;Invariants&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Model behavior lives in &lt;code&gt;src/model/inferenceActivity.ts&lt;/code&gt;; orchestration should
stay in &lt;code&gt;activityService&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The model consumes the collected 30 Hz window directly; there is no separate
60 Hz downsampling stage.&lt;/li&gt;
&lt;li&gt;Each successful minute tick produces at most one persisted CPM row.&lt;/li&gt;
&lt;li&gt;Storage shape, retention, and query ordering live in the schema doc.&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Daily Work Area</title><link>https://safer-capstone.pages.dev/developer-docs/overview/behaviors/daily-work-area-precache/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://safer-capstone.pages.dev/developer-docs/overview/behaviors/daily-work-area-precache/</guid><description>&lt;h1 id="daily-work-area-pre-cache-behavior"&gt;Daily Work-Area Pre-Cache Behavior&lt;/h1&gt;
&lt;h2 id="scope"&gt;Scope&lt;/h2&gt;
&lt;p&gt;This document defines the once-per-day work-area screen flow that pre-warms
weather cache entries from a farmer-selected circular work area.&lt;/p&gt;
&lt;h2 id="canonical-flow"&gt;Canonical Flow&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;When the Home/work-area screen becomes focused, the app checks whether the
local calendar day has already shown the work-area pre-cache modal.&lt;/li&gt;
&lt;li&gt;If the day has not shown the modal, a blocking full-screen modal asks the
farmer to define today’s work area by tapping a map center point, selecting
an address suggestion, or finding a typed address, then choosing a radius.&lt;/li&gt;
&lt;li&gt;The modal seeds from today’s saved area first; otherwise it pre-fills from
the most recent prior work area within the fallback window; otherwise it
opens centered on Sacramento and may recenter once to current device location
if foreground permission succeeds before the farmer edits.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Save today’s area&lt;/code&gt; persists one &lt;code&gt;DailyWorkAreaCircle&lt;/code&gt; for the current local
day and marks the day handled.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Use previous work day&lt;/code&gt; is available only when a saved work area exists
within the previous 7 local calendar days; it does not create a new circle
for today, but it does mark today handled after pre-cache runs.&lt;/li&gt;
&lt;li&gt;A top-right &lt;code&gt;Close&lt;/code&gt; action is available only when no recent fallback exists;
it dismisses the already-shown daily prompt without warming weather cells.&lt;/li&gt;
&lt;li&gt;The chosen circle is expanded by one weather-cache cell (&lt;code&gt;2.5 km&lt;/code&gt;) for
safety, converted into deduped cache-cell center points, and passed to
&lt;code&gt;precacheWeatherForLocations(...)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;precacheWeatherForLocations(...)&lt;/code&gt; warms one forecast cell per unique
location by fetching and storing a fresh 24-hour forecast horizon for that
cell.&lt;/li&gt;
&lt;li&gt;Manual reopen/edit from Home uses the same modal and re-runs pre-cache when
the farmer saves a new circle later that day.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="persistence-rules"&gt;Persistence Rules&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;One circle is stored per local day key (&lt;code&gt;YYYY-MM-DD&lt;/code&gt; in device-local time).&lt;/li&gt;
&lt;li&gt;Prompt-shown state is stored separately from daily circles so app launch alone
cannot suppress the work-area prompt before the farmer reaches the
Home/work-area screen.&lt;/li&gt;
&lt;li&gt;Fallback lookup only considers the most recent prior saved work day within 7
days.&lt;/li&gt;
&lt;li&gt;Daily pre-cache treats the current hour as part of the horizon when the
upstream NDFD response includes it; otherwise it accepts the next 24
contiguous forecast hours.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="invariants"&gt;Invariants&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Daily work-area pre-caching does not change prediction weather sourcing;
foreground and background predictions still use live device location.&lt;/li&gt;
&lt;li&gt;Pre-cache writes must go through &lt;code&gt;precacheWeatherForLocations(...)&lt;/code&gt;, which
uses a dedicated fetch/store warming path rather than the single-hour
&lt;code&gt;getWeatherPointCached(...)&lt;/code&gt; lookup contract.&lt;/li&gt;
&lt;li&gt;The modal is blocking only for the first focused Home/work-area screen visit
of the local day where the modal has not already appeared; later edits are
user-initiated from Home and are dismissible.&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Weather Caching Behavior</title><link>https://safer-capstone.pages.dev/developer-docs/overview/behaviors/weather-cache/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://safer-capstone.pages.dev/developer-docs/overview/behaviors/weather-cache/</guid><description>&lt;h2 id="scope"&gt;Scope&lt;/h2&gt;
&lt;p&gt;This document defines the runtime lookup policy for &lt;code&gt;getWeatherPointCached(...)&lt;/code&gt;
in &lt;code&gt;src/services/weatherService.ts&lt;/code&gt;. Daily work-area pre-warming uses the same
weather service module but follows its own dedicated 24-hour horizon warming
path through &lt;code&gt;precacheWeatherForLocations(...)&lt;/code&gt;.&lt;/p&gt;</description></item></channel></rss>