Blog ยท release
Latch 0.10.0
The habits module โ and a sharper statement of what the game is for. Latch is a game of self-improvement through play and fantasy: you write, you are honest, you do the work โ the training, the workout, the stretch, the instrument โ because you are a good boy and your Handler wants you to be the best boy you can be. This release adds the work.
habitsmodule (๐ฏ,/habits). A habit is an activity with its one-tap button on โ no second system โ so the streak, calendar colour, heat strip, stat tokens and hours-per-week chart all come from core with nothing written twice. What the module adds is the log row behind each event: how long, where it came from, and the key that stops an import repeating.- Three ways to log: one tap (a timed habit records your default length), the full form (minutes, a note, when), and a timer โ โถ start, do the thing, โ stop writes the minutes; it survives closing the page; discard writes nothing. Plus a short ๏ผ New habit form on the page, because a habit tracker you cannot add a habit to on a phone is not one.
- Calendar feeds. Practice trackers, habit apps and time trackers publish what they record
as iCalendar; paste the
webcal://link under Settings โ Habits, pick the habit, say which titles count, and Latch reads it every 30 minutes (habits.feed_minutes;0= never). Each finished entry becomes one log stamped at its end with its length; an all-day entry is a check-off at noon; an entry still in progress waits; a cancelled one is skipped. ๐ด Recurring entries are skipped, as a rule โ a schedule is a plan, not a record. ๐ด Re-fetching writes nothing twice, and an entry that later moves or grows has its old event struck through (anundoevent, the same door undo uses) and a new one written โ append-only survives an upstream edit. Several habits may read one calendar (one row each, fetched once). A stdlib parser: VEVENT only, TZID/UTC/floating/DATE, DURATION, unfolding, and ๐ด VTIMEZONE and VALARM blocks are never read as events. - File import. Upload an
.icsinstead โ same rules, same de-duplication, no network. - The first declared egress.
Module.egressis a new hook: one sentence, rendered on/settingsabove the module's knobs and named in the System line. Habits declares exactly what it fetches; with no URL configured it makes zero calls, so a fresh install is as sealed as 0.9. ๐ด On a hosted instance every feed URL โ and every redirect โ must resolve to a public address; private, loopback and link-local destinations are refused (SSRF). - A late entry counts but is not rewarded. Anything arriving more than 48 h after it ended
โ a year of practice history on the day a feed is added, a log typed a week late โ lands with
xp = 0. Streaks, calendar and totals take it in full. - API:
GET /api/v1/habits,POST /api/v1/habits/{log,start,stop}โ facts only, a log's note never crosses. A two-action iPhone Shortcut is indocs/api.md#habits. - Docs rewritten around the focus:
spirit.md,what-is-latch.md,index.md,quickstart.md(a new step 7),roadmap.md,modules.md,privacy.md,hosted.md,customise.md,api.md, and a newhabits.md. - Migration 11 (
habit_feeds,habit_logs),DURATION_SRC["habit"], both tables in the full export and excluded from the share export by construction. 552 tests.