Skip to content

refactor: task breadcrumbs follow-ups (shared codec, module extraction, fixtures)#713

Merged
maccman merged 2 commits into
nextfrom
refactor/task-breadcrumbs-followups
Jul 10, 2026
Merged

refactor: task breadcrumbs follow-ups (shared codec, module extraction, fixtures)#713
maccman merged 2 commits into
nextfrom
refactor/task-breadcrumbs-followups

Conversation

@maccman

@maccman maccman commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Problem

#685 landed task context breadcrumbs with a few structural loose ends, identified while comparing it against the competing #686:

  • The tasks.breadcrumbs JSON column format was hand-rolled in three places (Rust writer, dev-index writer, query boundary) with nothing marking them as one contract.
  • toTaskRow spread the raw SQL row and overwrote fields, so the stored breadcrumbs: string and the domain readonly string[] shared a name across the boundary, and both callers double-spread the result.
  • The ancestor-list walk lived inside extract.ts, which was closing in on the repo's 500-line lint ceiling.
  • Eight test files carried near-identical OpenTask fixture helpers — Add task context breadcrumbs #685 itself had to touch all of them just to add one field.
  • Generic-label suppression ran inside the TaskBreadcrumbs component at render time, while the rule itself lives in core.
  • The breadcrumb semantics existed only as scattered doc comments.

Changes

  1. One codec for the breadcrumbs column. encodeTaskBreadcrumbs / decodeTaskBreadcrumbs live next to indexedTaskSchema in core and are the only way the TS side touches the column (dev-index writer + toTaskRow). Rust's write.rs mirror stays pinned by its existing serialization test.
  2. toTaskRow maps raw → domain explicitly. Raw fields are destructured away; getOpenTasks/getCompletedTasks are now rows.map(toTaskRow).
  3. markdown/task-breadcrumbs.ts. The walk (taskBreadcrumbs + label helpers) moves out of extract.ts (−52 lines) into its own module with a header comment stating the semantics. No behavior change; the dead !== undefined arm in the ancestor loop is dropped.
  4. makeOpenTask shared fixture. One helper in lib/tasks/open-task-fixture.ts replaces the eight local copies; task-navigation and use-task-sheet-finalizer keep one-line wrappers for their differing default text.
  5. TaskContext.visibleBreadcrumbs. groupTaskContexts precomputes the display labels, the TaskBreadcrumbs component becomes purely presentational, and visibleTaskBreadcrumbs leaves the public core API (it was only exported for the component).
  6. Plan 18 doc. A canonical bullet under Key decisions / contracts states the full breadcrumb contract: ancestor-list-only labels, lead-textblock rendering, generic-parent suppression, codec-only column access, search scope, and the desktop-only context row.

Net −40 lines. No behavior, schema, or migration changes — pure structure.

Tests

  • Core: full suite, 1,204 passed (the one language-model.test.ts failure is the known pre-existing local env drift, untouched by this diff).
  • Desktop: all task-related suites (lib/tasks, tasks screens, mobile tasks, sheet finalizer, dev-index-db, selection) — 203 passed.
  • New coverage: groupTaskContexts labels contexts with visibleBreadcrumbs (trimmed real label vs suppressed generic).
  • pnpm check clean; the two max-lines warnings (indexer.ts, graph-provider.tsx) are pre-existing files this PR doesn't touch.

Risk / Rollout

Refactor-only: no schema, projection, or parsing behavior changes, so no reindex is triggered. The public core API shrinks by one export (visibleTaskBreadcrumbs), which nothing outside core consumed.

🤖 Generated with Claude Code


Note

Low Risk
Refactor-only with no migration or projection bump; the only API shrink is dropping the unused visibleTaskBreadcrumbs export from core.

Overview
Structural follow-ups to task context breadcrumbs (#685): no schema, parsing, or user-visible behavior changes.

Core: encodeTaskBreadcrumbs / decodeTaskBreadcrumbs centralize the tasks.breadcrumbs JSON column; toTaskRow decodes at the query boundary so the stored string type never leaks. Ancestor-list walking moves from extract.ts into markdown/task-breadcrumbs.ts. groupTaskContexts now exposes visibleBreadcrumbs (generic-parent suppression stays in core); visibleTaskBreadcrumbs is no longer a public export.

Desktop: TaskBreadcrumbs only renders precomputed labels; TaskGroupSection passes context.visibleBreadcrumbs. Dev index writes use the codec. Eight test files share makeOpenTask from open-task-fixture.ts.

Docs: Plan 18 documents the full breadcrumb contract.

Reviewed by Cursor Bugbot for commit 0ce7bac. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features

    • Task breadcrumbs now reflect the full list hierarchy, with clearer labels and consistent ordering.
    • Breadcrumbs can be used to identify and select the tasks associated with a context.
    • Search behavior now supports task context breadcrumb labels.
  • Bug Fixes

    • Improved handling of generic or redundant parent labels so unnecessary breadcrumb text is hidden.
    • Improved consistency when displaying task contexts across desktop and mobile.
  • Documentation

    • Documented breadcrumb behavior, storage, search, and interaction rules.

- One codec (encode/decodeTaskBreadcrumbs) for the tasks.breadcrumbs
  column, used by the dev-index writer and the query boundary
- toTaskRow destructures raw fields instead of spread-overwriting
- The ancestor-list walk moves out of extract.ts into
  markdown/task-breadcrumbs.ts
- One shared makeOpenTask test fixture replaces eight local copies
- groupTaskContexts precomputes visibleBreadcrumbs; the TaskBreadcrumbs
  component is purely presentational and visibleTaskBreadcrumbs leaves
  the public API
- Plan 18 doc gains the canonical breadcrumb-semantics bullet

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@maccman maccman changed the title Task breadcrumbs follow-ups: shared codec, module extraction, fixture consolidation refactor: task breadcrumbs follow-ups (shared codec, module extraction, fixtures) Jul 10, 2026
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Task breadcrumbs are now derived from list ancestry, encoded and decoded through shared indexing helpers, filtered into visible context labels, and rendered directly by desktop task groups. Multiple task tests now use a shared OpenTask fixture.

Changes

Task breadcrumb flow

Layer / File(s) Summary
Markdown breadcrumb derivation
packages/core/src/markdown/task-breadcrumbs.ts, packages/core/src/markdown/extract.ts, docs/plans/18-tasks.md
Ancestor list-item labels are extracted as plain-text breadcrumbs in outermost-first order, with the behavior documented and tested through the task grouping contract.
Breadcrumb storage and query boundaries
packages/core/src/indexing/indexed-note.ts, packages/core/src/indexing/queries-tasks.ts, apps/desktop/src/dev/dev-index-db.ts, packages/core/src/indexing/index.ts, packages/core/src/exports/sync-markdown-indexing.ts
Shared JSON encoding and decoding helpers replace duplicated breadcrumb serialization and parsing logic for indexed task rows.
Visible context rendering
packages/core/src/indexing/group-tasks.ts, packages/core/src/indexing/group-tasks.test.ts, apps/desktop/src/components/tasks/task-group-section.tsx, apps/desktop/src/components/tasks/task-breadcrumbs.tsx
Task contexts expose visibleBreadcrumbs, and desktop rendering joins the supplied visible labels without applying a second filter.
Shared task test fixtures
apps/desktop/src/lib/tasks/open-task-fixture.ts, apps/desktop/src/lib/tasks/*.test.ts, apps/desktop/src/components/tasks/tasks-screen.test.tsx, apps/desktop/src/mobile/**/*.test.tsx
Repeated local OpenTask builders are replaced with the shared makeOpenTask fixture and scenario-specific overrides.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant MarkdownParser
  participant TaskBreadcrumbs
  participant IndexWriter
  participant TasksTable
  participant TaskQueries
  participant TaskContext
  participant DesktopTaskGroup
  MarkdownParser->>TaskBreadcrumbs: derive ancestor labels
  TaskBreadcrumbs-->>IndexWriter: provide breadcrumbs
  IndexWriter->>TasksTable: store encoded breadcrumbs
  TasksTable-->>TaskQueries: return task row
  TaskQueries->>TaskContext: decode breadcrumbs and group tasks
  TaskContext-->>DesktopTaskGroup: provide visibleBreadcrumbs
  DesktopTaskGroup->>TaskBreadcrumbs: render visible labels
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 65.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main refactor theme and mentions key changes: shared codecs, module extraction, and fixture consolidation.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/task-breadcrumbs-followups

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/desktop/src/lib/tasks/open-task-fixture.ts`:
- Around line 9-15: Update the fixture factory’s default raw-line construction
to derive the marker from the resolved checked value, so makeOpenTask({ checked:
true }) produces a checked marker while preserving any explicit raw override;
use the checked variable and raw field in makeOpenTask.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 117c9fe2-4a02-418c-acff-1b32de032197

📥 Commits

Reviewing files that changed from the base of the PR and between 24a8df9 and a8d8812.

📒 Files selected for processing (21)
  • apps/desktop/src/components/tasks/task-breadcrumbs.tsx
  • apps/desktop/src/components/tasks/task-group-section.tsx
  • apps/desktop/src/components/tasks/tasks-screen.test.tsx
  • apps/desktop/src/dev/dev-index-db.ts
  • apps/desktop/src/lib/tasks/open-task-fixture.ts
  • apps/desktop/src/lib/tasks/recently-completed.test.ts
  • apps/desktop/src/lib/tasks/task-cache.test.ts
  • apps/desktop/src/lib/tasks/task-navigation.test.ts
  • apps/desktop/src/lib/tasks/task-visibility.test.ts
  • apps/desktop/src/lib/tasks/use-task-keyboard.test.ts
  • apps/desktop/src/mobile/screens/tasks.test.tsx
  • apps/desktop/src/mobile/use-task-sheet-finalizer.test.ts
  • docs/plans/18-tasks.md
  • packages/core/src/exports/sync-markdown-indexing.ts
  • packages/core/src/indexing/group-tasks.test.ts
  • packages/core/src/indexing/group-tasks.ts
  • packages/core/src/indexing/index.ts
  • packages/core/src/indexing/indexed-note.ts
  • packages/core/src/indexing/queries-tasks.ts
  • packages/core/src/markdown/extract.ts
  • packages/core/src/markdown/task-breadcrumbs.ts

Comment thread apps/desktop/src/lib/tasks/open-task-fixture.ts
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@maccman maccman merged commit 31b1b7b into next Jul 10, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant