fix: Kanban helper syncs only the card's leading link, not trailing date/reference links - #126
Merged
Conversation
The Kanban helper iterated over every wikilink in a board file and wrote the card's lane into each linked note's tracked property. Trailing links on a card line - Kanban "@[[date]]" links and in-text references like "see [[Note]]" - were therefore clobbered with a lane name (or raised a spurious "property not found" notice when they lacked the property, the root of #45). A Kanban card is a top-level task whose content begins with its link ("- [ ] [[Note]] ..."); only that leading link identifies the note to sync. - Treat a link as a card link only when it is the leading link of a top-level task line, verified against the freshly-read board content (which also guards against the metadata cache lagging the edit: drift -> skip, never a wrong write). - Derive lanes from the metadata cache's headings instead of a substring search, so ATX-closed ("## Done ##") and setext lane names resolve correctly. - Keep iterating after an unresolvable card link (#80 fault 1) and keep the no-op guard when the property already matches. - Make the missing-property notice name the linked file and board. Adds regression coverage for the date/reference clobbering, prose-then-link and indented sub-items, heading links, ATX-closed/setext lanes, stale-cache drift, and multi-lane boards, with a fixture builder asserted against the live cache.
Drives the real vault modify-event pipeline in an isolated Obsidian instance: moving a card updates the leading link's note to the new lane while leaving the card's "@[[date]]" and "see [[ref]]" links untouched, and an unresolvable card link no longer aborts updates to later cards.
…e board (#80) Adversarial review found issue #80's fault 1 still reachable through the throw path: getPropertiesInFile -> parseFrontmatter -> parseYaml throws on a linked note with malformed YAML (e.g. a cache/content race), which aborted onFileModify and skipped every later card. Each card is now processed in its own try/catch and logged via logMessage (logError re-throws and would re-break this), so a single failing card never blocks the rest. Also: drop the unreachable `!fileProperties` branch (getPropertiesInFile always returns an array), type the file cache as `CachedMetadata | null`, and scope the card-link guard comment to what it actually guarantees (link identity, not lane heading drift). Adds a regression test for the throwing-card case.
github-actions Bot
pushed a commit
that referenced
this pull request
Jul 1, 2026
# [1.9.0](1.8.4...1.9.0) (2026-07-01) ### Bug Fixes * address review findings from PRs [#119](https://github.com/chhoumann/MetaEdit/issues/119)-[#128](https://github.com/chhoumann/MetaEdit/issues/128) ([adf0b57](adf0b57)) * **api:** preserve reserved keys when cloning values ([#162](#162)) ([cff6076](cff6076)) * **automators:** count only [x]/[X] tasks complete; null-guard Kanban lane display ([#145](#145)) ([21da53a](21da53a)) * **bulk:** reject __proto__/constructor as a bulk property key ([#148](#148)) ([f03eacc](f03eacc)) * **bulk:** serialize bulk frontmatter writes through the controller write queue ([#147](#147)) ([3eb8236](3eb8236)) * **controller:** guard __proto__/constructor in all frontmatter writes ([#159](#159)) ([9d99fae](9d99fae)) * **controller:** make inline-field writes fence-aware ([5f8e713](5f8e713)) * **core,api:** safe command no-op, block-list deletion, presence-based property lookups ([#143](#143)) ([1702d08](1702d08)) * edit YAML lists (incl. tags) as native lists instead of collapsing them to a string ([#94](#94)) ([#128](#128)) ([79f6ee0](79f6ee0)), closes [#51](#51) [#36](#36) * harden frontmatter metadata writes ([add2e90](add2e90)) * Kanban helper syncs only the card's leading link, not trailing date/reference links ([#126](#126)) ([52aec1e](52aec1e)) * **kanban:** don't write to an ambiguous same-named note ([#158](#158)) ([7f9655b](7f9655b)) * **kanban:** single notice for a card missing the board property ([9b1c88a](9b1c88a)) * parse inline fields behind list/quote markers and brackets ([#122](#122)) ([a62ef21](a62ef21)), closes [#119](#119) [#18](#18) [#121](#121) [#78](#78) [#84](#84) * **parser:** preserve [[wikilinks]] in multi-value inline edits ([c331adb](c331adb)) * **settings:** serialize Auto Property choice persistence to prevent lost updates ([#154](#154)) ([2066b3e](2066b3e)) * **settings:** settings tab no longer clobbers concurrently-added Auto Property choices ([5759534](5759534)) * **settings:** validate auto-properties before queueing and make rollbacks compare-and-restore ([#156](#156)) ([8cbacdc](8cbacdc)), closes [#154](#154) * stop inline-field updates appending a stray bracket ([#127](#127)) ([d2617f5](d2617f5)), closes [#67](#67) [#121](#121) * **suggester:** center row action icons flush-right ([#166](#166)) ([c00795e](c00795e)) * **suggester:** use native icons + tooltips for row actions ([70903cc](70903cc)) * **suggester:** well-formed duplicate Notice, robust modal close, cleaner name suggestions ([#144](#144)) ([915dd6b](915dd6b)), closes [#143](#143) * **tags:** correct and clarify tag editing ([#142](#142)) ([b837899](b837899)), closes [#49](#49) * tolerate malformed YAML frontmatter when parsing note metadata ([#132](#132)) ([b835f97](b835f97)), closes [#130](#130) ### Features * adopt modern Obsidian APIs and raise baseline ([5131664](5131664)) * **api:** append Dataview field instances without replacing ([42c78a8](42c78a8)), closes [#91](#91) * **api:** expand public integration surface ([#120](#120)) ([bbf0a7a](bbf0a7a)) * assist property-value entry with autocomplete and a native date picker ([#125](#125)) ([cd86235](cd86235)), closes [#61](#61) [#74](#74) [#61](#61) [#61](#61) * **auto-properties:** description, multi-select, and learn-as-you-go values ([#123](#123)) ([4b24296](4b24296)), closes [#59](#59) [#40](#40) [#59](#59) [#40](#40) [#59](#59) [#40](#40) [#43](#43) [#30](#30) * **auto-properties:** paste a list to split into choices ([#139](#139)) ([0245f7a](0245f7a)) * bulk edit metadata across folders and selected notes ([#124](#124)) ([c8d91e2](c8d91e2)), closes [#64](#64) [#20](#20) * **create:** fluid, type-aware native YAML property creation ([#170](#170)) ([59b4c5d](59b4c5d)) * **editor:** edit properties with Obsidian's native widgets; raise minAppVersion to 1.12.7 ([#168](#168)) ([73b37e0](73b37e0)) * hide file tags from the Edit Meta menu ([#46](#46), [#90](#90)) ([#131](#131)) ([2c07937](2c07937)), closes [#tag](https://github.com/chhoumann/MetaEdit/issues/tag) [#tags](https://github.com/chhoumann/MetaEdit/issues/tags) * support nested YAML path editing ([e9fce98](e9fce98))
|
🎉 This PR is included in version 1.9.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #80 ("Kanban board faulty behavior"). When a Kanban card moves lanes, the
helper updates the linked note's tracked property (e.g.
status) to the new lane.The bug: the helper iterated over every wikilink in the board file and wrote
the card's lane into each linked note. A card line like
therefore clobbered the date note (
@[[2026-06-01]]) and the reference note withthe lane name - or raised a spurious
'status' not found in <board>notice whenthose notes lacked the property (the root of the long-running #45 noise).
A Kanban card is a top-level task whose content begins with its link; only
that leading link identifies the note to sync. The fix scopes updates to that
leading link.
Root cause (restated)
The card's identity was never modeled.
updateFilesInBoardlooped overcache.links(the whole file's links) andgetTaskHeadingreverse-mapped eachlink to a lane via a fragile substring search (
taskContent.includes(link.original)).Trailing links and in-text references were indistinguishable from the card itself.
What changed (
src/automators/onFileModifyAutomators/kanbanHelper.ts)leading link of a top-level
- [ ]task line (only the checkbox + whitespaceprecede it). This excludes
@[[date]]links, mid-text references, indentedsub-checklist items, timestamp-prefixed archive entries, and links inside lane
headings.
ATX-closed (
## Done ##→Done) and setext lane names resolve correctly(verified live).
freshly-read board content (the cached link must still sit at its recorded
position with its recorded text); on a mismatch the link is skipped rather than
acted on with stale data.
try/catch; an unresolvable link or a throwing property read (e.g. malformedYAML in a linked note) no longer aborts syncing of the remaining cards.
board, and only fires for genuine card notes.
Contract note
A card syncs a note only when the card starts with the link (
- [ ] [[Note]] …).This matches the reporter's explicit intent in #80 ("…the
[[Thing]]link isobviously not meant to be updated" for prose cards) and is the only contract that
fixes #80 without silently clobbering incidental links. A purely descriptive card
like
- [ ] Read [[Book]]is intentionally not synced.Validation
Reproduced-then-fixed live in an isolated Obsidian instance (the
80-kanbanworktree vault), driving the real vault modify-event pipeline.
Before the fix (on today's
master, post-#119): movingProject Aclobbered2026-06-01andReference NotetoIn Progress.After the fix:
Project A → In Progress;2026-06-01andReference Noteunchanged.
Generalization proven live (not just the reporter's setup):
## Done ##Done(notDone ##)Shipping → Review → Live(within debounce)Livephase)Commands run:
Tests
__tests__/kanbanHelper.test.ts: regression coverage for the date/referenceclobbering, prose-then-link and indented sub-items, heading links,
ATX-closed/setext lanes, stale-cache drift, the throwing-card loop, and
multi-lane boards - with a fixture builder asserted against the live cache shape.
tests/e2e/kanban-helper.test.ts(new): live modify-pipeline regression for theno-clobber behavior and the unresolvable-card-doesn't-abort behavior.
Review
A 3-lens adversarial design review ran before coding (folded into the
cache-headings + drift-guard design) and a 3-lens adversarial review ran on the
committed diff. The diff review's one blocking finding - fault 1 still
reachable via a throwing property read - is fixed in commit
fae4d5awith liveproof and a regression test.
Out of scope / follow-ups
in place while the cache lags (a transient, self-healing state the 5s modify
debounce makes negligible). Deriving lanes fully from freshly-read content is a
reasonable follow-up but would drop the cache's free ATX-closed/setext handling.
automator concern, not addressed here.
Closes #80.