aboutsummaryrefslogtreecommitdiff
path: root/tests/test-pearl-mapping.el
Commit message (Collapse)AuthorAgeFilesLines
* refactor: remove the dead state-to-todo mapping subsystemCraig Jennings2026-05-261-45/+6
| | | | | | `pearl-state-to-todo-mapping` and its derived regex stopped doing real work once keyword rendering moved to slugifying the Linear state name (`pearl--state-name-to-keyword`) and the keyword-to-state direction moved to resolving through the team's workflow states. The defcustom fed only `pearl--get-todo-states-pattern`, which had no caller left, and the two cache vars existed only to serve that dead function. State extraction reads `org-get-todo-state` off the buffer's `#+TODO` line, so nothing live touched the mapping. I removed the defcustom, both cache vars, and the dead function, and dropped the three pattern tests that exercised it. Removing the defcustom orphaned the mapping bindings that ~12 test setup macros still carried. They were passing through slugification rather than the map, so I stripped them too and kept the `org-todo-keywords` bindings the temp buffers actually need. Also dropped the stale README config row.
* feat: resolve a cycled TODO keyword to its Linear state at saveCraig Jennings2026-05-261-21/+7
| | | | | | Cycling a ticket's TODO keyword (C-c C-t) now counts as a state edit. The dirty scan gains a keyword-cycle arm: state is dirty when the explicit id moved off its baseline (the picker arm, as before) or when the keyword diverged from the synced state name's slug. At save, the picker arm pushes the explicit id; the keyword-cycle arm resolves the keyword to a team state id by slug match, first by position, and pushes that. A keyword no team state matches is reported skipped rather than guessed. set-heading-state now slugifies the keyword instead of the static-map lookup, so the picker writes the same keyword the renderer derives. Without that, a picker edit to a non-standard state would read as permanently cycled. That retires pearl--map-linear-state-to-org, whose only caller this was, and its tests.
* refactor(save): remove the immediate-state-push org-sync machineryCraig Jennings2026-05-251-16/+4
| | | | | | | | The opt-in org-sync mode pushed Linear state immediately — on every TODO-keyword cycle (the org-after-todo-state-change hook) and on every buffer save (the after-save hook scanning the whole file). That's the last immediate-push path, and it contradicts the one-write-path model the rest of v2 builds, so I removed it: pearl-enable-org-sync / -disable-org-sync, pearl-org-hook-function, pearl-sync-org-to-linear, pearl-sync-current-heading-to-linear, and the now-orphaned pearl--process-heading-at-point, pearl--map-org-state-to-linear, and pearl--update-issue-state-async. This finishes the "make org-sync private" task — there was nothing left to make private. Cycling a TODO keyword now marks state dirty (reconciled at the next save) instead of pushing. Saving the buffer pushes nothing. Re-introducing an auto-push on save is the separate "Automatic sync on save" task, which would call the save engine rather than this whole-file scanner. I kept pearl--extract-org-heading-properties and pearl--get-todo-states-pattern. They're general heading/keyword readers, not org-sync-specific, and the keyword-cycle save (the keyword-derivation follow-up) needs exactly them. The obsolete sync tests are replaced by two that assert the contract: the sync commands are gone, and a keyword cycle pushes nothing.
* feat(save): add the priority, state, and labels saversCraig Jennings2026-05-251-5/+5
| | | | | | | | | | These are three more savers on the atomic engine, each the same spec shape the assignee saver proved, with its own field handling. Priority reads the cookie's number, diffs it against LINEAR-PRIORITY, and pushes priority. State is the picker arm — the explicit LINEAR-STATE-ID against LINEAR-STATE-ID-SYNCED, pushing stateId, with use-remote rewriting the keyword and name from the fetched node (the keyword-cycle arm stays gated on the derivation task). Labels canonicalize the id set to a sorted space-joined string so the diff is order-insensitive, and push labelIds. Canonicalizing labels to a string also keeps the missing-baseline check honest: an issue with no labels has a present-but-empty baseline, which a nil-vs-empty-list comparison would misread as a legacy file. A shared set of pearl--node-* helpers pulls each field out of the raw issue node. I also fixed pearl--get-linear-priority-name, which mapped None to "Medium" — it now reads "None", so the conflict prompt names the priority honestly. It's still not wired into save-issue — the next commit does that.
* feat(save): detect dirty structured fields against synced baselinesCraig Jennings2026-05-251-8/+8
| | | | | | The save scan now flags priority, state, assignee, and labels as dirty when their live value differs from the synced baseline, so structured fields ride the same reconcile-at-save path as title and description. Each check is id/scalar-only and runs with no network: the priority cookie's number against LINEAR-PRIORITY, the explicit state id against LINEAR-STATE-ID-SYNCED (the picker arm — keyword cycling lands later), the assignee id against its baseline, and the label id set against its baseline (order-insensitive, since Linear label order isn't meaningful). A missing baseline on a legacy file reads as not-dirty; the saver's missing-property guard covers that edge. This also makes the priority cookie faithful. The renderer mapped both None and Medium to [#C], so a None issue couldn't be told apart from a Medium one and would have read dirty the moment its baseline said 0. None now renders with no cookie, 1:1 with the four cookie levels — matching what the priority setter already did.
* feat: pearl — manage Linear issues from org-modeCraig Jennings2026-05-241-0/+145
Pearl fetches Linear issues into an org file and syncs edits back. It covers list / custom views / saved queries, per-issue and bulk rendering with comments inline, conflict-aware sync of descriptions, titles, and comments, field commands for priority / state / assignee / labels, and a transient dispatch menu. The render folds to a scannable outline and nests issues under a sortable parent. Based on and inspired by Gael Blanchemain's linear-emacs.