An Issue is something missing or unfinished in what was logged: a sleep with no bedtime, an interval that was never ended, a required field left empty, a day the Rundown asked about that nobody answered. The line between an issue and a refusal is the line between missing and malformed. A value that cannot be what its field declares (a word where a number goes, a number past its limit) is refused at the write (The List Model). A value that is merely absent is accepted and becomes an issue, so logging the half you know is never blocked by the half you do not.

Issues are worked out when read and never stored, in packages/core/src/issues.ts. Only a person’s choice to set one aside is stored.

The kinds

ISSUE_KIND gives each kind its severity, the title its list is headed by, and its fixes, first the one to try.

KindTitleSeverityRaised forFixes
runningRunninginfothe latest open interval, within its limitend it now, open it
staleNever endedwarningan interval open past its trackable’s Stale after (16 hours by default), or an older one left open when a later one startedopen it, delete it
emptyLeft emptywarningan interval that ended with no start logged (“Has no bedtime”), or a required field left empty once the entry has endedopen it
unansweredNot answeredwarninga day the trackable was asked and has no entryanswer the day
outsideOutside its routinewarningan entry whose time falls before its routine began or after it ended (Events)open it
exclusiveTwo of an exclusive tagwarninga trackable under two child tags of an Exclusive tagchange its tags

A running entry holds only what it has so far, so it is asked for its required fields only once it ends. Which end an issue names follows the interval’s own words for its ends (Intervals).

Every list of them (issuesOf) puts Never ended first: an interval with no end reads as begun and measures nothing until it ends, and the last one a trackable began also stays in the running bar until then (Intervals). The other warnings follow, then Running; newest first within each.

Not answered is raised only for a trackable that asks for it: the setting “Left unanswered is an issue”, under “A day with nothing logged”, records the day it was turned on (capture.issue_unanswered_since), and only days from then are checked, up to the day before today. A day counts only if the Rundown asked the trackable that day (The Rundown), and until the Rundown is read none does; something was logged by you that day (a day with only entries logged for you is not one you used the app, Logged for You), and no Disruption holds it. A trackable whose empty days mean none raises none, since it has no unanswered day.

Setting one aside

Detection always runs, and splitIssues divides what it finds into active and ignored, so anything set aside can be restored.

  • Dismiss sets aside one issue. The dismissal is kept against the issue’s key with a fingerprint of the entry as it stood (entryFingerprint, a hash of its time and stored value), so editing the entry brings the issue back. An outside issue’s fingerprint includes the routine’s times, and an exclusive one’s the tags it names, so either comes back when those change. Dismissals are stored in issue_dismissal and synced like the rest of a profile.
  • Mute sets aside a whole kind everywhere, in the issues:muted setting.

Where they show

Every list and count is the library’s IssueList and IssueTrigger (Jeliroco Components), fed by one Datler component, IssueLines (apps/renderer/src/components/issues/IssueActions.tsx), which turns each issue into a row and runs its fixes. The first fix is drawn as the primary one, and Delete in the danger tone.

  • The top bar has an Issues button with the count of open warnings (a running interval is not counted, useIssues().asking), opening a drawer of every open issue with its fixes, each headed by its trackable and opening its entry, with the Issues page at its foot (IssuesButton). The sidebar’s Issues entry carries the same count.
  • The Issues page (/issues) lists them grouped by kind, with Mute and Unmute per kind, and Dismissed with Restore and Restore all, each with when it happened.
  • On an entry: a badge with the fixes in the entries table, in a day’s list, and above the form in the entry dialog; opening it or pressing a fix never opens the row it sits in. A day’s list also names each trackable not answered that day, with Answer and Dismiss. Answer opens the log panel on that day, in a dialog the shell draws once (IssueAnswerHost), so it outlives the popover it was pressed in.

Settings that raise them

All three are safe to change, since they decide only what is reported:

  • Required, on any field: an entry that has ended with that field empty is an issue, never a refusal, so each person decides what they hold themselves to. Someone with a watch can require its readiness score; someone without one leaves it optional.
  • Stale after, on an interval field: how long an interval may run before it is reported as never ended.
  • Left unanswered is an issue, offered in the trackable form under “A day with nothing logged” when such a day is left unanswered rather than meaning none.

The List Model · Intervals · The Rundown · Events · Entry