Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
317ebbf
feat(status): add lifecycle category to StatusConfig
renatomen Jul 23, 2026
94fd16b
feat(status): category dropdown and lifecycle pill in status settings
renatomen Jul 23, 2026
ec42464
fix(review): address status-lifecycle review findings
renatomen Jul 23, 2026
0717329
refactor(status): three always-on categories (Not started / Started /…
renatomen Jul 23, 2026
a2e4670
feat(deps): per-endpoint start/finish blocked computation in Dependen…
renatomen Jul 23, 2026
3bada02
feat(deps): thread per-endpoint blocked state onto TaskInfo
renatomen Jul 23, 2026
ad0cfb0
test(deps): extend issue-1100 dependencyCache mock with per-endpoint …
renatomen Jul 23, 2026
513f421
feat(dependencies): show per-endpoint blocked state on card surfaces
renatomen Jul 23, 2026
6c7a3b2
feat(dependencies): author reltype + lag from both sides of the edit …
renatomen Jul 23, 2026
5ea7fbe
feat(settings): add the advanced dependency types opt-in to Features
renatomen Jul 23, 2026
3c112e8
feat(bases): reflect per-endpoint blocking in rendered views; documen…
renatomen Jul 23, 2026
5caf3d2
fix(review): harden dependency edge cases from the branch review
renatomen Jul 23, 2026
ee33f38
fix(task-card): persist blocked-by / blocking expansion across re-ren…
renatomen Jul 23, 2026
8eb7de5
feat(dependencies): status-readiness guidance for advanced dependency…
renatomen Jul 23, 2026
0b8bb20
feat(task-card): break the blocking tooltip down by endpoint
renatomen Jul 23, 2026
7970cb2
feat(task-card): stack the blocking tooltip breakdown on its own lines
renatomen Jul 23, 2026
9206179
feat(i18n): add context-menu relationship-type labels for the depende…
renatomen Jul 24, 2026
7b9ad5e
feat(dependencies): choose the relationship type from the context-men…
renatomen Jul 24, 2026
3004cfd
test: complete task-card expandedProjectsService mocks with blocking …
renatomen Jul 24, 2026
0c21578
refactor(dependencies): move the reltype menu builder into the tested…
renatomen Jul 24, 2026
47c0f79
test(dependencies): cover forward blocking-predecessor accessors and …
renatomen Jul 24, 2026
35656c5
fix(task-card): stop re-expanding relationship sub-lists on every render
renatomen Jul 24, 2026
101ca25
refactor(task-card): drop now-unused blocked/blocking expansion persi…
renatomen Jul 24, 2026
9d8be16
fix(bases): skip the data-update re-render when the data is unchanged
renatomen Jul 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion docs/features/task-management.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,11 @@ Whenever a dependency is added, TaskNotes updates the upstream note’s `blockin
- The task context menu provides the same selector, enabling dependency management directly from the Task List, Kanban, and calendar views.
- Task cards show a fork icon whenever a task blocks other work. Clicking it expands an inline list of downstream tasks without triggering the parent card’s modal, so you can inspect dependents in place.

These controls currently create and manage finish-to-start style blockers. Advanced `reltype` values and `gap` data are preserved in frontmatter, but blocking evaluation is currently based on whether unresolved dependencies exist rather than relationship-type-specific scheduling rules.
By default, dependencies use finish-to-start. Enable **Features → Dependencies → Advanced dependency types** to choose a relationship type and an optional lag per dependency from both the "Blocked by" and "Blocking" lists in the edit modal.

Blocking is evaluated per endpoint: finish-to-start and start-to-start gate a task's *start*, while finish-to-finish and start-to-finish gate its *finish*. An edge releases as soon as the predecessor reaches the point the relationship requires — started for a start-to-\* edge, completed for a finish-to-\* edge — so a task reads "Blocked · start" or "Blocked · finish" only while it is genuinely constrained.

TaskNotes-rendered views (Task List, Kanban, cards) reflect this computed state. A native `.base` filter on "blocked by", however, matches by existence only: a Bases filter formula evaluates a single note's frontmatter and cannot read a predecessor's status, so it cannot distinguish a released edge from a live one. Use a TaskNotes-rendered view when you need constraint-aware blocking.

![Task context menu](../assets/feature-task-context-menu.png)

Expand Down
9 changes: 9 additions & 0 deletions docs/releases/unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,12 @@ When a change has user-facing documentation, include a canonical tasknotes.dev l
```

-->

## Added

- Dependency blocking now distinguishes a task's start from its finish, following the predecessor relationship type (finish-to-start, start-to-start, finish-to-finish, start-to-finish). A task shows "Blocked · start" when it cannot begin yet and "Blocked · finish" when it can begin but cannot complete; the signal clears the moment the predecessor reaches the point the relationship requires — started for a start-to-* edge, completed for a finish-to-* edge. A satisfied dependency stays listed under the task but no longer counts toward the blocked signal.
- The task edit modal can set each dependency's relationship type and an optional lag from both the "Blocked by" and "Blocking" lists, with a plain-language summary that names both tasks so the direction is never ambiguous. Editing a "Blocking" edge writes the relationship to the blocked task's own frontmatter. Advanced relationship types are off by default.

## Changed

- Task statuses now have a lifecycle category — Not started, Started, or Completed — shown as a pill in the status settings, replacing the previous "Completed" toggle. Existing completed statuses stay Completed; the rest default to Not started. If you keep a custom "in progress" status, set its category to **Started** in Settings → Task Properties so that start-based dependencies (start-to-start / start-to-finish) release when it begins — until then it is treated as Not started.
49 changes: 47 additions & 2 deletions i18n.manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,14 @@
"settings.tabs.appearance": "1576acbe8d999f289f587cca610d867affd66953",
"settings.tabs.features": "fc338f87a058158eb824b53705961801516a9460",
"settings.tabs.integrations": "a7881cac6e64abca5eafd172df6eb31fe0b84c88",
"settings.features.dependencies.header": "0562f32dc56f5c702810cbe010068ddd38dbd69a",
"settings.features.dependencies.description": "0d9169b5400763b70fbf5d6d6e353ea379b03255",
"settings.features.dependencies.advancedTypes.name": "f66818c3d60bc0e0af07f76a294316490648fdd8",
"settings.features.dependencies.advancedTypes.description": "c47eb9e8b41785e03257c949975b9ce7c66d9ca8",
"settings.features.dependencies.readiness.name": "3c1caea99da6c9c2c75a4d39d243c109e4fac509",
"settings.features.dependencies.readiness.counts": "91f28f33f798573daafbf09d285a721cee8b5bae",
"settings.features.dependencies.readiness.ready": "834a072164f4cf15f133437b0c87011be5922007",
"settings.features.dependencies.readiness.notReady": "06a54db32352cd734c1cdc1cac1530dcff8b2a2b",
"settings.features.inlineTasks.header": "a0f498bf59b33369a6a0aca916b487fd04ea40a7",
"settings.features.inlineTasks.description": "041baf632682261876d68fdfb557dcb820eeb505",
"settings.features.taskCreation.header": "ec5845a572a9d5ae23130b55f1113f7bc2854e96",
Expand Down Expand Up @@ -704,7 +712,7 @@
"settings.taskProperties.taskStatuses.howTheyWork.label": "c601b207de14ad4111101e2639e1ddb4d2c58d73",
"settings.taskProperties.taskStatuses.howTheyWork.color": "b3a4e0aed552d59293608963c489a5ab0e627c33",
"settings.taskProperties.taskStatuses.howTheyWork.icon": "990a304e39a65c9cab8405d690b593f3b01008f0",
"settings.taskProperties.taskStatuses.howTheyWork.completed": "e6bd6dc7043b1d939ae805d795e5f3b6c2d4470b",
"settings.taskProperties.taskStatuses.howTheyWork.category": "2b8da0273c7362094590a0758422ecf689b8fe6c",
"settings.taskProperties.taskStatuses.howTheyWork.autoArchive": "bd84a52c7f3268c53cbd87f48ca89f2224a7ac31",
"settings.taskProperties.taskStatuses.howTheyWork.orderNote": "622251b5df80b62ec75e854fb074594cf7cee6cb",
"settings.taskProperties.taskStatuses.addNew.name": "d8f65cf551e5eeb9b07f3a1279ba4ed8b0172a46",
Expand All @@ -717,7 +725,7 @@
"settings.taskProperties.taskStatuses.fields.label": "f70a9228e736a5c3a698e6037eed2dda9de1b40f",
"settings.taskProperties.taskStatuses.fields.color": "511a000614ad52294121be47cb86170db16ba777",
"settings.taskProperties.taskStatuses.fields.icon": "b6d7019b1817040a55577652ed26649af8ca0183",
"settings.taskProperties.taskStatuses.fields.completed": "208409ffed559a03204711e8976b06e3710deca5",
"settings.taskProperties.taskStatuses.fields.category": "61b9204fa30ab100d2a82ad42f62e455b1d2df3a",
"settings.taskProperties.taskStatuses.fields.excludeFromCycle": "6e3d4319d8e9bc72452a8ea748a148aace623f36",
"settings.taskProperties.taskStatuses.fields.nextStatus": "b8d1a252e8580a447b2108ebb362443b15ba73f7",
"settings.taskProperties.taskStatuses.fields.autoArchive": "ebba9937a4826ac159c5c5fd87a98562f3aff675",
Expand All @@ -727,6 +735,9 @@
"settings.taskProperties.taskStatuses.placeholders.icon": "6c7a4a074ff62754681360bda7c3994c8029742b",
"settings.taskProperties.taskStatuses.placeholders.nextStatusDefault": "0516a99c523425cc4a3eee70cab344e056e41db6",
"settings.taskProperties.taskStatuses.badges.completed": "1798b3ba42ee08ea09d9720b2d9c0181abbfe3e4",
"settings.taskProperties.taskStatuses.badges.planned": "db2c45d5579367438b625f4cf40cad184e39bd54",
"settings.taskProperties.taskStatuses.badges.inProgress": "faa9e7e7ef5a264c58c68a4a0b9c8bd54241450a",
"settings.taskProperties.taskStatuses.categoryAdvisory": "20a7cd3e531f6642a97afe38d62a434b9b43639f",
"settings.taskProperties.taskStatuses.deleteConfirm": "179626d7a4d216da031ac7ca2ec87e0ed97bc5fc",
"settings.taskProperties.taskPriorities.header": "44c22d1630a67a7d465d56ddea064d62259dc9dc",
"settings.taskProperties.taskPriorities.description": "27e335b697e148e2ff9d76108bbb76d7081f0836",
Expand Down Expand Up @@ -1561,6 +1572,26 @@
"modals.task.dependencies.addTaskButton": "24700e60fedcf00a741c5adb1d9f15aee05f95d8",
"modals.task.dependencies.selectTaskTooltip": "752b3be46866220ce17567bede45bdac374d4a4f",
"modals.task.dependencies.removeTaskTooltip": "5be1bc9e1837b131abac53534235a44b4bca541e",
"modals.task.dependencies.thisTask": "fe4214812fd30d511c46fd8805552084ff0df47f",
"modals.task.dependencies.reltype.label": "9b4a86cba424a8ab70b35d9d1c129276324d7c03",
"modals.task.dependencies.reltype.finishToStart": "8ec81a8c3b9d0cd71c2c623edbfe897ed49cfacc",
"modals.task.dependencies.reltype.startToStart": "e6a33a3b7ad97040d82ca2a561515b93ea9ffc39",
"modals.task.dependencies.reltype.finishToFinish": "56f12e78d355d33960914e3bb28a42e9963f033c",
"modals.task.dependencies.reltype.startToFinish": "ef85558baac50380d1f6702fc3cd47dc6cd1d4ff",
"modals.task.dependencies.gap.label": "215953ae73cacbac55a17936f31b68796d1d5925",
"modals.task.dependencies.gap.placeholder": "b6589fc6ab0dc82cf12099d1c2d40ab994e8410c",
"modals.task.dependencies.gap.exotic": "bc073badb3924dd5322839e2338ce1afc7fbd7c5",
"modals.task.dependencies.gap.unit.hours": "9e25a34e635a123f8958bbe26e7c4843278597fb",
"modals.task.dependencies.gap.unit.days": "f6bb0f468a8569c67b3d6826e57e62c5500c3681",
"modals.task.dependencies.gap.unit.weeks": "7d75266a53b99ce4d80d337862ea1edd8ba1b1a1",
"modals.task.dependencies.summary.blockedBy.finishToStart": "0b13c4311f6709b43cf5df5cd25d9d8dbfa8611e",
"modals.task.dependencies.summary.blockedBy.startToStart": "e57a142e612010370d8dd5091aa7b66054982087",
"modals.task.dependencies.summary.blockedBy.finishToFinish": "c61e04f8588563575214b07c7cc407bb7e5fbefb",
"modals.task.dependencies.summary.blockedBy.startToFinish": "7623bbd63cfcac4ee412e388ebe8719fb09c1915",
"modals.task.dependencies.summary.blocking.finishToStart": "d3cb1ebbb1993329342312baea76b7d632244cf3",
"modals.task.dependencies.summary.blocking.startToStart": "2993b292dbefb6a76e3ffa2ec2ff920ecda51df7",
"modals.task.dependencies.summary.blocking.finishToFinish": "2881523ca1692b932537465a83ae16692941f6e3",
"modals.task.dependencies.summary.blocking.startToFinish": "37a73cf6cbd1e9f86eabbee297e4a75048c5f399",
"modals.task.organization.projects": "53e890d5f0fffe09587c55dce74e9a6febf59b5c",
"modals.task.organization.subtasks": "173312c6e2592de729610a4d319877c9aa8d8b67",
"modals.task.organization.addToProject": "85be7d2ce90b02bd410c4deb918f46e112efd677",
Expand Down Expand Up @@ -1804,6 +1835,14 @@
"contextMenus.task.dependencies.removeBlockedBy": "7d38375d41dfda37e2adcdaea68e95312a792312",
"contextMenus.task.dependencies.removeBlocking": "29f784e16f2ca0df6d37a9fb6f29c3a186937738",
"contextMenus.task.dependencies.unknownDependency": "bc7819b34ff87570745fbe461e36a16f80e562ce",
"contextMenus.task.dependencies.reltype.blocking.finishToStart": "b50cfe466b096494591205ea9cfab3526cba9054",
"contextMenus.task.dependencies.reltype.blocking.startToStart": "25eb197f4962b676253b09c8aa866c26bd3bc642",
"contextMenus.task.dependencies.reltype.blocking.finishToFinish": "4c05dbcb794856b1af7968e4b10a986a7c662b42",
"contextMenus.task.dependencies.reltype.blocking.startToFinish": "8635c71ae358909a9d8db530e18b9920be387a64",
"contextMenus.task.dependencies.reltype.blockedBy.finishToStart": "96d8d50fbcc29b664f7880e1ad48b6fb9a5da51f",
"contextMenus.task.dependencies.reltype.blockedBy.startToStart": "aaf413f633282c6874dc3b04f2c701803acaa67b",
"contextMenus.task.dependencies.reltype.blockedBy.finishToFinish": "687b6b600b1e26e581f09e9f7df0192f740a7112",
"contextMenus.task.dependencies.reltype.blockedBy.startToFinish": "07bc71f9865dcde8b4303e9d5b2f74674704e284",
"contextMenus.task.dependencies.inputPlaceholder": "67c2a027f7b139a8b9103081eb4fb418e135cd38",
"contextMenus.task.dependencies.notices.noEntries": "e5145350fdd7dee5b4a532bea740c844b64d938e",
"contextMenus.task.dependencies.notices.blockedByAdded": "5b40b08d56beaf43181cea5aeb55474c47a3e347",
Expand Down Expand Up @@ -1986,9 +2025,15 @@
"ui.taskCard.labels.blocking": "d785c0d4b3b9c24878b62f64a7bcf78e9506ab27",
"ui.taskCard.blockedBadge": "99613c74ce010d98ed5501785f3591344a19bc17",
"ui.taskCard.blockedBadgeTooltip": "5c34a82e776374bf83ad16d8d8ffb1edad391579",
"ui.taskCard.blockedStart": "ce05f765ef58d17a4aac4bd45f8d453b658ab366",
"ui.taskCard.blockedStartTooltip": "84d827e46930216b0fba2ec6372e5cb5e321a659",
"ui.taskCard.blockedFinish": "c49a38ad19c43f66093f5853a9429978ba2cbdd9",
"ui.taskCard.blockedFinishTooltip": "a2760fee6e842c197bc753eb704c2e3c0decfdbb",
"ui.taskCard.dependenciesBadge": "0562f32dc56f5c702810cbe010068ddd38dbd69a",
"ui.taskCard.blockingBadge": "d785c0d4b3b9c24878b62f64a7bcf78e9506ab27",
"ui.taskCard.blockingBadgeTooltip": "949888e3fc7f208a3c9a867b79a1abf4f15aa90a",
"ui.taskCard.blockingToggle": "17e5c29b584df3fa8161559141c209308994dccb",
"ui.taskCard.blockingToggleBreakdown": "57d886e2f4236976638cb06097f510606848015b",
"ui.taskCard.priorityAriaLabel": "28f478cb8ee60d0167b0507b87fa966e52061d81",
"ui.taskCard.taskOptions": "d7788a93bb9a5f6b6770830ead3075c0b91cc9a3",
"ui.taskCard.recurrenceTooltip": "468ddecacd77613fb8597819d97008bc336a76e8",
Expand Down
Loading