feat(diff): disallow editing done tasks by default

Problem: Done tasks could be freely edited in the buffer, leading to
accidental modifications of completed work.

Solution: Add a `lock_done` config option (default `true`) and a guard
in `diff.apply()` that rejects field changes to done tasks unless the
user toggles the checkbox back to pending first.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Barrett Ruth 2026-03-10 22:19:15 -04:00
parent e62f2f818c
commit ea8ba7f44c
3 changed files with 148 additions and 76 deletions

View file

@ -287,5 +287,66 @@ describe('diff', function()
local task = s:get(1)
assert.are.equal(0, task.priority)
end)
it('rejects editing description of a done task', function()
local t = s:add({ description = 'Finished work', status = 'done' })
t['end'] = '2026-03-01T00:00:00Z'
s:save()
local lines = {
'# Todo',
'/1/- [x] Changed description',
}
diff.apply(lines, s)
s:load()
local task = s:get(1)
assert.are.equal('Finished work', task.description)
assert.are.equal('done', task.status)
end)
it('allows toggling done task back to pending', function()
local t = s:add({ description = 'Finished work', status = 'done' })
t['end'] = '2026-03-01T00:00:00Z'
s:save()
local lines = {
'# Todo',
'/1/- [ ] Finished work',
}
diff.apply(lines, s)
s:load()
local task = s:get(1)
assert.are.equal('pending', task.status)
end)
it('allows editing done task when lock_done is false', function()
local cfg = require('pending.config')
vim.g.pending = { lock_done = false }
cfg.reset()
local t = s:add({ description = 'Finished work', status = 'done' })
t['end'] = '2026-03-01T00:00:00Z'
s:save()
local lines = {
'# Todo',
'/1/- [x] Changed description',
}
diff.apply(lines, s)
s:load()
local task = s:get(1)
assert.are.equal('Changed description', task.description)
vim.g.pending = {}
cfg.reset()
end)
it('does not affect editing of pending tasks', function()
s:add({ description = 'Active task' })
s:save()
local lines = {
'# Todo',
'/1/- [ ] Updated active task',
}
diff.apply(lines, s)
s:load()
local task = s:get(1)
assert.are.equal('Updated active task', task.description)
end)
end)
end)