Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Tasks Plugin (@lapis-notes/tasks)

Source: packages/plugins/plugin-tasks/src/

Package: @lapis-notes/tasks. Manifest: id tasks, version 0.0.1, min app version 1.7.7.

The tasks package owns browser-first task capture and management as a bundled first-party plugin. It is currently a transitional implementation that is being aligned to TaskNotes’ markdown-first model without relying on desktop-only integrations or Obsidian internal APIs.

This package is a vendoring of the upstream TaskNotes plugin into Lapis Notes. That upstream plugin should be treated as the implementation reference for any functionality we decide to support here, while the standalone TaskNotes specification remains the behavioral contract for markdown model semantics.

TaskNotes Direction

TaskNotes is explicitly markdown first: the intended end state is one markdown note per task with YAML frontmatter for machine-readable properties and note body content for freeform detail. The standalone TaskNotes specification is the behavioral contract for future read/write semantics, especially around model mapping, operations, temporal fields, recurrence, validation, configuration, dependencies, reminders, and links.

For future feature work, start from upstream TaskNotes behavior and data flow first, then adapt it for this host only where browser constraints, shared package boundaries, or non-Obsidian runtime differences require a documented deviation.

The current plugin now claims the TaskNotes core-lite conformance profile through a dedicated adapter bridge. The primary storage model is markdown first and supports persisted folder and field-role configuration plus stricter validation, while advanced TaskNotes semantics remain intentionally out of scope.

See Upstream Feature Audit for the current gap inventory and phased roadmap derived from upstream TaskNotes docs and source references.

Implementation Sequence

Vendoring proceeds in ordered slices instead of a wholesale upstream import:

  1. Keep the current first-party Lapis plugin shell, workspace boot wiring, and @lapis-notes/ui-based Tasks view.
  2. Unwind the current non-conforming primary model by removing JSON-backed manual tasks and generic checklist aggregation from the main Tasks dataset.
  3. Replace transitional storage with markdown-first TaskNotes task-note writes and task-folder indexing.
  4. Add TaskNotes semantic field mapping, browser-safe configuration handling, and strict validation for the supported core behavior.
  5. Add TaskNotes fixture or conformance-backed validation before expanding into recurrence or other advanced features.

The first six slices are now in place, and the adapter now also covers the current core-lite bridge surface. The remaining roadmap is now split into concrete feature families: schema/settings parity, richer editor and inline-capture surfaces, remaining Bases parity, recurrence/dependency/link semantics, time-management surfaces, and host-constrained external integrations.

Registration

  • View type: plugin:tasks.
  • Settings tab entry: Tasks, which renders the persisted task settings form directly in the plugin settings panel.
  • Command: tasks:open-view.
  • Commands: tasks:open-task-list-base, tasks:open-kanban-base, tasks:open-fizzy-base, tasks:open-fizzy-calendar-base, and tasks:open-mini-calendar-base.
  • Ribbon action: opens the Tasks view.
  • Core-plugin activation through the workspace shell.

Data And Persistence

The current slice stores each task as a markdown note in a configurable managed task folder, defaulting to TaskNotes/Tasks/. Supported task-note frontmatter roles currently include:

  • title
  • status
  • priority
  • due
  • scheduled
  • tags
  • projects
  • blockedBy
  • recurrence
  • recurrenceAnchor
  • completeInstances
  • skippedInstances
  • timeEntries
  • dateCreated
  • dateModified
  • completedDate

The task identifier is currently derived from the note path rather than stored as a separate frontmatter field. The plugin indexes the configured task-note folder as its primary dataset, also indexes markdown notes outside that folder when the task parser accepts them and their mapped frontmatter tags include the configured task tag, persists folder and field-role settings through plugin data, creates missing folder paths in a browser-safe way, and updates task status, priority, scheduled dates, relationship links, Fizzy pin or golden state, and other frontmatter-backed task properties by mutating mapped frontmatter fields through the vault API with the same path-aware semantics used by the shared Properties and FrontMatter editors, automatically touching dateModified whenever one of those mutations changes task frontmatter. The initial full-vault rebuild now gathers candidate note content on the host thread but offloads bulk task-note parsing and index construction to a dedicated worker with a main-thread fallback if worker startup fails. Strict validation now also enforces required temporal fields, completedDate conditional requiredness, due-value parsing, and dateModified >= dateCreated ordering for the currently supported model.

The persisted settings model now also carries a broader schema foundation for later TaskNotes parity work, including:

  • extended frontmatter-role mapping for scheduled dates, contexts, projects, time estimates, recurrence, reminders, blockers, and time entries
  • title-storage configuration for frontmatter vs filename-based titles
  • default task values and task-detection strategy data
  • richer status and priority vocabularies
  • Fizzy board preferences for Not Now status, entropy enablement, and entropy age; pinned card state is persisted in task-note frontmatter as pinned: true/false rather than in plugin settings
  • custom user-field definitions with NLP and suggestion-filter metadata
  • modal field-group layout metadata

The Tasks settings tab now exposes the persisted managed folder, marker tag, title-storage mode, filename strategy, default status/priority/date presets, task-detection rules, Fizzy Not Now lane, Fizzy entropy controls, status and priority vocabularies, and JSON-backed custom fields directly inside the plugin settings panel. The interactive runtime also now uses that persisted schema for creation defaults, preset recurrence rules, recurring completion history, mapped reminder visibility, dependency readiness state, Fizzy frontmatter-backed pin state and entropy moves, and timeEntries-backed task timers. Modal field-group editing and richer schema-specific editors remain future work.

UI Ownership

The first view slice is a dedicated Tasks leaf with:

  • toolbar Add task dialog for task-note capture (preserves #tasks-title, due date, and tags for E2E); settings configuration lives in Settings → Tasks, not an inline settings card
  • command-driven inline task conversion from the current Markdown editor line, a single-line selection, or all supported prefixed task lines in the current note into TaskNote links
  • partial metadata extraction during inline conversion for hashtags and explicit ISO due-date tokens
  • reading-mode convert affordances for promoting supported prefixed Markdown task candidates into TaskNotes
  • source-mode and live-preview convert affordances for promoting supported prefixed Markdown task candidates in place
  • task-note summary widgets in reading mode, source mode, and live preview for indexed task notes, including markdown notes outside the managed task folder when their mapped frontmatter tags include the configured task tag and the task parser accepts them, now rendered through a reusable upstream-shaped task-row surface with an upstream-style cycling status button (none -> open -> in-progress -> done) that emits app toasts, centered priority/menu affordances, completed-row dimming, an inner hover surface that preserves a visible outer gutter, scheduled-date metadata buttons and the overflow Schedule submenu both driven by an upstream-style popup menu with increment/basic/weekday sections plus Pick date & time... and Clear date, where Pick date & time... opens a shared @lapis-notes/ui date-time picker dialog, YAML tag metadata from the mapped note tags field rendered immediately beside the scheduled chip with markdown tag styling, including the task tag when it is present on the note, due metadata pills, mapped reminder metadata pills, priority none, preset recurrence actions that write mapped recurrence fields, recurrence-aware completion that rolls the next due or scheduled date forward while recording completeInstances, a Skip next occurrence recurrence action that advances the current recurring instance while recording skippedInstances, recurring history metadata pills that surface the latest completed or skipped recurrence instance, dependency readiness metadata pills that surface blocked, ready, and blocking state from the resolved task relationships, a task-card start/stop timer button with tracked-duration pills backed by timeEntries, and a richer overflow menu for status, priority, scheduling, reminders, dependencies, organization, recurrence, copy, open, and delete actions. The dependency and organization sections open a shared @lapis-notes/ui command dialog with fuzzy search and match highlighting (same interaction model as the workspace command and file palettes) for blocker, dependent, project, and subtask linking instead of expanding every candidate task in nested submenus; reminder actions still mutate mapped reminders, and the note-widget variant now renders dedicated Reminders and relationship detail content with reminder entries, nested blocked-by and blocking task cards, linked projects, and recursive subtask rows using indentation guides instead of section labels, without a Relationships header or Open relationships entrypoint. When either panel would render, both stay collapsed by default behind a shadcn Collapsible with a hover-only chevron beside the overflow menu and click-to-expand on the card surface, while collapsed relationship summary pills remain visible in the main metadata row and hover feedback scopes to the whole card when collapsed or to individual sections and nested child cards when expanded.
  • a dedicated Tasks settings-tab form that writes the persisted TaskNotes-style schema through updateSettings() so folder/tag/title/defaults/detection/vocabulary changes are available without direct test-only runtime calls
  • task-link overlays in reading mode, source mode, and live preview that now reuse the same task-row family in a smaller inline layout instead of a separate compact pill surface, keeping a single compact row with status, priority, title, always-visible details and overflow actions that open the shared task detail dialog for relationship stacks and metadata instead of rendering relationship pills inline, and inactive CodeMirror source/live-preview lines that replace the raw [[...]] task link text with the overlay widget instead of showing both
  • parsed relationship-link groundwork for projects and blockedBy, with runtime helper lookups for derived subtasks, blockers, and blocked-by tasks so future recursive trees and relationship widgets can build on the indexed markdown task-note dataset
  • generated TaskNotes-style .base files under the managed task views folder, defaulting to TaskNotes/Views/, including a generated Fizzy base; the Fizzy view settings now expose labeled controls for the column property, Maybe and Not Now column values, title property, and hide-empty-columns toggle through the shared Bases settings sidebar
  • custom task-focused Bases renderers for Task List, Kanban Board, Fizzy, Fizzy Calendar, and Mini Calendar views, registered through Plugin.registerBasesView() and rendered from the BasesQueryResult supplied by plugin-bases; task-specific views consume the already filtered and grouped Bases dataset instead of rebuilding or re-filtering task entries locally, keep a reactive snapshot of the latest Bases query result, and also invalidate themselves when the Tasks runtime emits tasks-changed so late query refreshes, task-index rebuilds, and frontmatter mutations repopulate open task Bases views; Task List and Kanban Board rows now use the full note-widget task-card surface with inline metadata, increased outer view padding, and a hover-only details button that opens a medium-width task detail dialog with header status/priority badges, note body, relationship stacks, and a built-in-properties sidebar that surfaces interactive status, priority, scheduled, due, recurrence, reminder, timer, and timestamp controls together with linked projects and blockers rendered through NoteLink where a task note target exists, plus Bases-provided extra properties, instead of compact rows or an embedded task card, while the generated Fizzy .base now persists board-specific view config including the column-driving property, special Maybe and Not Now values, user-arranged column order, and per-column title/color overrides, and the generated Fizzy Calendar .base adds an activity timeline that derives Added, Updated, and Done lanes from each task note’s current dateCreated, dateModified, and completedDate metadata rather than a durable event log, collapsing consecutive empty visible days into a single gap row when Show empty days is enabled
  • a Fizzy board renderer inspired by Basecamp Fizzy (“Kanban as it should be”) that now groups the markdown task-note dataset by a configurable metadata property, defaulting to the mapped status field, while still supporting dedicated Maybe and Not Now values plus completed columns; the board applies an optional entropy move from stale tasks into Not Now on open, resolves column colors from either configured status colors or persisted per-column overrides, applies each column color to every card in that lane instead of deriving card backgrounds from priority, supports @dnd-kit/svelte-backed drag-and-drop moves across every column by mutating the configured note property instead of hardcoding status writes, keeps only fixed column positions non-reorderable, exposes a compact inline column-action popup for moving workflow lanes left or right and editing persisted title or color metadata, renders frontmatter-backed pinned cards (pinned: true/false) in a bottom pin stack, uses explicit frontmatter-backed golden tickets (golden: true/false) instead of highest-priority inference, provides full-screen per-column grid and card detail views, embeds the reusable editable markdown preview/editor for the task-note body inside detail together with the reusable task-card controls beneath the title, supports inline detail-title edits that write back to the task note, preserves Done and Not Now stamps plus entropy countdown copy, scopes Fizzy keyboard shortcuts to the active visible board or detail surface instead of document-wide handlers, hands lane search off through the shared Bases query controller, and keeps the page root height-locked with independent column scrolling
  • Task-focused Bases view chrome, including Fizzy board, detail, and calendar surfaces, now ships through the Tasks package stylesheet artifacts (app.css and styles.css) rather than component-local <style> blocks; runtime values such as per-card or per-column colors are passed through CSS custom properties that those external styles consume so the same override surface is available in both workspace and standalone builds
  • Tasks styling inherits the shared Obsidian-aligned global theme through core background, border, text, accent, warning, success, and error variables. Task-specific variables keep status, due-date, recurrence, and relationship semantics distinct without defining a separate app palette.
  • Tasks leaf toolbar Task views dropdown that creates or opens the generated task Bases files through the shared Bases runtime (replacing the former Views card)
  • local create-form validation and inline submission errors for task-note capture in the toolbar dialog
  • a shadcn-svelte-style data table as the primary browse surface (see Tasks leaf browse surface below and task id TASK-PLUGIN-018)
  • completion toggling, deletion, note-open actions, and task-note path badges through table rows and the shared task-card overflow menu
  • shared @lapis-notes/ui controls for form fields, data table, table, badges, and actions
  • namespaced tasks-... selectors for plugin-owned styling

Tasks leaf browse surface

Tracked as TASK-PLUGIN-018. The main Tasks leaf (plugin:tasks) uses a data-table-first layout aligned with the shadcn-svelte tasks example:

flowchart TB
  header[Header: title + stats]
  toolbar[Toolbar: search + filters + Add task + Views + columns]
  table[Primary data table]
  pagination[Pagination footer]
  header --> toolbar --> table --> pagination
ColumnBehavior
CompleteCheckbox → plugin.setTaskCompleted()
TitleSortable; NoteLink hover preview and click-to-open when the task has a note path; path as muted subtitle
Statusplugin.getTaskStatusLabel(); faceted filter
PriorityDot + label; faceted filter
DuegetTaskDueLabel() / tone classes
TagsBadge with tasks-view__meta-pill tasks-view__meta-pill--tag, #tag format
Meta (hideable)Reminder, recurrence, dependency badges from existing helpers
ActionsFull task-card overflow menu (extracted from card-row.svelte)

The toolbar provides search, status/priority faceted filters, reset, column visibility, Add task, and Task views. Row filtering reuses filterTasks() at the view level. The overflow menu is shared between table row actions and task-card surfaces. Bulk row selection and new @lapis-notes/ui faceted-filter primitives are out of scope.

Future upstream-style audits for task-row surfaces must compare the rendered widget DOM against the upstream TaskCard implementation surface, not just the visible controls and token palette. That audit must cover styles/task-card-bem.css, the TaskCard status-cycle/runtime wiring, taskCardProperties metadata renderers, the upstream DateContextMenu popup structure, status and priority settings vocabularies, and the upstream task context menu action set. Alignment, hover hit-area placement, metadata text sizing and color, tag rendering, state vocabulary, overflow-menu breadth, and scheduled-date menu grouping are part of the feature contract.

Task completion updates TaskNotes-style frontmatter through the vault API instead of maintaining plugin JSON state or inline checklist mirrors.

The package now also carries source-level conformance status metadata targeting tasknotes-spec 0.1.0-draft, documenting current configuration providers, core-lite capabilities, and known deviations. It exposes a dedicated ESM conformance adapter entrypoint alongside adapter-style meta.*, date.*, field.*, config.*, validation.*, create_compat.create, op.*, delete.remove, task.load, task.create, and the existing internal OP.* mutation aliases.

This slice is intentionally browser-safe and self-contained. It does not depend on community-plugin compatibility shims, desktop-only HTTP/OAuth flows, or internal embed/editor APIs.

Shared UI primitives for this package should come from @lapis-notes/ui. If the plugin needs an additional control, it should first be added to @lapis-notes/ui using the existing shadcn-svelte / Bits UI wrapper approach before introducing a plugin-local control implementation.

Things-Like Planner Workflow

A Things-like planner workflow now ships as a Lapis-specific layer over the existing markdown-first Tasks runtime. It helps users decide what deserves attention now without replacing the existing Tasks data table, generated Bases views, task-card widgets, recurrence/reminder/dependency behavior, or Fizzy board workflows.

The planner is implemented first as a dedicated workspace view backed by the Tasks runtime (getTasks() plus tasks-changed). A generated Planner Base now ships as a companion query surface, but the daily workflow still lives in the first-class planner view rather than in a database browser.

The planner buckets are:

BucketRuntime semantics
InboxActive tasks that still need triage: no scheduled date, no due date, no project links, no area links, and no explicit when.
TodayTasks intentionally selected for today through today’s scheduled date or explicit planner placement, ordered by todayOrder.
This EveningA lower-emphasis section for tasks planned for today but deferred to evening, persisted with today’s scheduled date plus when.
UpcomingActive tasks with a future scheduled/start date, rendered as a calendar-like list with near-term days visible and later empty runs collapsed into gap rows.
AnytimeActive tasks available now but not committed to Today, not parked in Someday, and not still untriaged in Inbox.
SomedayIntentionally parked active work, represented explicitly by planner metadata rather than by the absence of a date.
LogbookCompleted work grouped by completion date or completion-status metadata.

Due dates and scheduled dates must stay distinct. A due date is a deadline; a scheduled date is the date a task should become available or planned. The default planner model should not treat due-today tasks as Today commitments, though a later setting may add that behavior as an explicit option. Someday must be explicit planner metadata; undated tasks should classify as Inbox or Anytime.

The planner metadata layer now includes mapped when, areas, todayOrder, projectOrder, projectSection, and reviewed fields. The planner settings surface persists the default planner bucket, due-today inclusion, Anytime review threshold, Someday review threshold, and the mapped field names for those planner-specific properties.

The dedicated planner view now owns:

  • quick Inbox capture that bypasses date defaults
  • a settings-pane-style resizable sidebar and independently scrolling main pane, with a draggable divider that does not show a visible grip icon
  • planner scheduling actions for Today, This Evening, Tomorrow, This Weekend, Next Week, Someday, and Clear
  • first-class area and project side rails with linked task views
  • a persistent Areas rail section that remains visible even before any area-linked task exists
  • compact planner rows that show a checkbox, title, and minimal metadata in the collapsed state
  • double-click row expansion that opens a frontmatter-hidden inline live-preview editor, focuses an editable title field on open with the caret at end, keeps the expanded row stable while focus moves between the title, body editor, and footer actions, dismisses only from planner list/body background clicks or a different task row while ignoring app chrome, sidebars, planner headers, capture controls, expanded-row content, and portaled menus or dialogs, animates close/open switching so double-clicking a different row closes the old panel before opening the new one without losing the second click target, and preserves the task note’s frontmatter on write
  • expanded-row footer actions for planner placement, due/deadline editing and clearing, area/project assignment, full detail opening, note opening, and overflow task actions
  • Upcoming calendar rows that show the date number and weekday, insert month dividers, and collapse longer empty spans such as June 4-30
  • manual ordering in Today and project lists through drag-and-drop plus move up or down controls
  • project sections persisted in task frontmatter and edited from project views
  • a review surface that highlights Inbox triage, stale Anytime tasks, stale Someday tasks, and projects without a next action, with actions to mark reviewed or re-plan the task in place

The generated Planner Base companion now creates TaskNotes/Views/Planner.base with Inbox, Today, Upcoming, Anytime, Someday, Logbook, and Deadlines views. That Base intentionally remains a companion approximation: it exposes planner metadata and the closest safe query representations Bases can express, but it does not replace the dedicated planner’s runtime-only bucketing and review logic.

Known Deviations And Gaps

  • Richer relationship widgets, richer metadata extraction, and natural-language parsing are still missing. Inline task capture now covers command, reading-mode, source-mode, and live-preview conversion for supported prefixed Markdown task candidates with formatting-preserving replacements plus hashtag and explicit ISO due-date extraction, the task-note widget now renders dedicated Reminders and relationship detail content together with linked projects, nested blocked-by and blocking task cards, dependency sections, reminder metadata, blocked/ready/blocking state pills, and recursive subtask rows, and inline task-link overlays now route relationship detail through the shared task detail dialog instead of inline pills. Remaining relationship work is focused on broader dedicated widgets, deeper parity polish, and broader metadata extraction. Task IDs: TASK-PLUGIN-007, TASK-PLUGIN-011.
  • Task schema/settings parity now has an interactive Tasks-view settings surface, including Fizzy controls for Not Now lane selection, entropy enable/days, status and priority vocabularies, and JSON-backed custom fields, but modal field-group editing, richer typed editors for custom fields and suggestion filters, and deeper filename-strategy parity are still missing. Task ID: TASK-PLUGIN-009.
  • The initial Bases-backed task list, kanban, Fizzy, Fizzy Calendar, mini calendar, and generated default .base templates are now implemented. The Fizzy board now uses frontmatter-backed pins and golden tickets, property-driven column grouping with persisted column-property and Maybe/Not Now value config in the generated .base, persisted per-column title/color overrides, drag writes against the configured note property, detail-screen editable markdown plus inline title editing with a footer Edit action and e shortcut that enter body-edit mode, Done and Not Now stamps, entropy countdown copy, full-screen detail and grid views, and demo-faithful layout/interactions. The Fizzy Calendar view now adds an activity timeline grouped into Added, Updated, and Done columns, keeps the page root height-locked with its own vertical scrolling surface, reuses the shared task-card body inside each calendar card, uses a dedicated day-window slider for its recent activity range, and still derives that activity from current task metadata instead of a durable historical event stream. Remaining Fizzy work includes comments, boosts, richer task-card overflow-menu reuse, manual card ordering within lanes, and deeper activity-history parity. Task IDs: TASK-PLUGIN-010, TASK-PLUGIN-015, TASK-PLUGIN-016, TASK-PLUGIN-017.
  • The Things-like planner workflow is now implemented as a dedicated Tasks planner view plus a generated Planner Base companion. The dedicated view owns the refined Things-style interaction model, including the resizable planner sidebar, compact expandable rows, inline body editing, Areas and Projects side rails, review projections, calendar-like Upcoming grouping, and sparse ordering. Current limitations are intentional: the generated Planner Base exposes the closest safe query views Bases can express, while runtime-only bucketing, review projections, inline row editing, and sparse ordering still live in the planner view itself.
  • Recurrence now has preset rule selection plus rolling completion or skip-forward actions for the managed due or scheduled field, and the browse/task-row surfaces now show the latest recurring completion or skip date, mapped reminder metadata, explicit due-date, day-before-due, scheduled-date, and picked reminder actions, a note-widget bell reminder indicator with tooltip, lightweight dependency readiness state, and collapsible note-widget relationship stacks, but custom rules, richer skip-state UX, broader reminder automation semantics, broader relationship widgets, richer link semantics, and the extended TaskNotes conformance profiles remain unimplemented. Task IDs: TASK-PLUGIN-006, TASK-PLUGIN-011.
  • Time tracking now has an initial task-card start/stop timer surface backed by timeEntries, but calendar editing, richer auto-stop policy controls, Pomodoro views, calendar integrations, ICS subscriptions, and automation surfaces are still missing or blocked on host-capability decisions. Task IDs: TASK-PLUGIN-012, TASK-PLUGIN-013, TASK-PLUGIN-014.
  • Any intentional divergence from upstream TaskNotes plugin behavior for browser-host or package-boundary reasons must be recorded here before implementation is treated as complete.