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:
- Keep the current first-party Lapis plugin shell, workspace boot wiring, and
@lapis-notes/ui-based Tasks view. - Unwind the current non-conforming primary model by removing JSON-backed manual tasks and generic checklist aggregation from the main Tasks dataset.
- Replace transitional storage with markdown-first TaskNotes task-note writes and task-folder indexing.
- Add TaskNotes semantic field mapping, browser-safe configuration handling, and strict validation for the supported core behavior.
- 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, andtasks: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:
titlestatuspriorityduescheduledtagsprojectsblockedByrecurrencerecurrenceAnchorcompleteInstancesskippedInstancestimeEntriesdateCreateddateModifiedcompletedDate
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/falserather 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 overflowSchedulesubmenu both driven by an upstream-style popup menu with increment/basic/weekday sections plusPick date & time...andClear date, wherePick date & time...opens a shared@lapis-notes/uidate-time picker dialog, YAML tag metadata from the mapped notetagsfield 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, prioritynone, preset recurrence actions that write mapped recurrence fields, recurrence-aware completion that rolls the next due or scheduled date forward while recordingcompleteInstances, aSkip next occurrencerecurrence action that advances the current recurring instance while recordingskippedInstances, 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 bytimeEntries, 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/uicommand 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 mappedreminders, 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
projectsandblockedBy, 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
.basefiles under the managed task views folder, defaulting toTaskNotes/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 theBasesQueryResultsupplied byplugin-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 emitstasks-changedso late query refreshes, task-index rebuilds, and frontmatter mutations repopulate open task Bases views; Task List and Kanban Board rows now use the fullnote-widgettask-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 throughNoteLinkwhere a task note target exists, plus Bases-provided extra properties, instead of compact rows or an embedded task card, while the generated Fizzy.basenow 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.baseadds an activity timeline that derives Added, Updated, and Done lanes from each task note’s currentdateCreated,dateModified, andcompletedDatemetadata rather than a durable event log, collapsing consecutive empty visible days into a single gap row whenShow empty daysis 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.cssandstyles.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/uicontrols 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
| Column | Behavior |
|---|---|
| Complete | Checkbox → plugin.setTaskCompleted() |
| Title | Sortable; NoteLink hover preview and click-to-open when the task has a note path; path as muted subtitle |
| Status | plugin.getTaskStatusLabel(); faceted filter |
| Priority | Dot + label; faceted filter |
| Due | getTaskDueLabel() / tone classes |
| Tags | Badge with tasks-view__meta-pill tasks-view__meta-pill--tag, #tag format |
| Meta (hideable) | Reminder, recurrence, dependency badges from existing helpers |
| Actions | Full 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:
| Bucket | Runtime semantics |
|---|---|
| Inbox | Active tasks that still need triage: no scheduled date, no due date, no project links, no area links, and no explicit when. |
| Today | Tasks intentionally selected for today through today’s scheduled date or explicit planner placement, ordered by todayOrder. |
| This Evening | A lower-emphasis section for tasks planned for today but deferred to evening, persisted with today’s scheduled date plus when. |
| Upcoming | Active 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. |
| Anytime | Active tasks available now but not committed to Today, not parked in Someday, and not still untriaged in Inbox. |
| Someday | Intentionally parked active work, represented explicitly by planner metadata rather than by the absence of a date. |
| Logbook | Completed 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
.basetemplates 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 footerEditaction andeshortcut 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.