a live task can be edited, a resolved one cannot (V-509)

SetTaskStatus was the only mutation on a task row, so a typo in a dictated
task was permanent and a deadline could not move. EditTask rewrites the three
fields capture set — text, due date and weight — and nothing else. Status
stays the one-way ladder SetTaskStatus owns.

Two things the task asked to settle.

A text edit re-normalises the dedupe key and can collide with another live
row. That is ErrTaskDuplicate, a refusal rather than a merge: two live rows
carry two provenances, two capture times and possibly two external
identities, and merging picks a winner for all three with nobody asked. The
surface names the row that holds the text.

A resolved task is refused outright (ErrTaskResolved). Its text is the record
of what was finished, and rewriting it rewrites history.

due nil clears the date, because clearing has to be sayable — an absent date
and "remove the date" cannot be one argument.
This commit is contained in:
2026-08-05 20:39:11 +04:00
parent 92949e886f
commit a6b17ada8b
10 changed files with 174 additions and 0 deletions
+3
View File
@@ -540,6 +540,9 @@ var methodTable = map[Method]handlerFunc{
MethodSetTaskStatus: withParamsVoid(func(ctx context.Context, api CoreAPI, p setTaskStatusReq) error {
return api.SetTaskStatus(ctx, p.ID, p.Status, p.Ts, p.By)
}),
MethodEditTask: withParamsVoid(func(ctx context.Context, api CoreAPI, p editTaskReq) error {
return api.EditTask(ctx, p.ID, p.Text, p.Due, p.Weight)
}),
MethodSetTaskFields: withParamsVoid(func(ctx context.Context, api CoreAPI, p setTaskFieldsReq) error {
return api.SetTaskFields(ctx, p.ID, p.DoneWhen, p.BlockedOn)
}),