diff --git a/docs/plans/2026-10-11_tree-read-follow-up.md b/docs/plans/2026-10-11_tree-read-follow-up.md new file mode 100644 index 000000000..499c6cdc1 --- /dev/null +++ b/docs/plans/2026-10-11_tree-read-follow-up.md @@ -0,0 +1,79 @@ +# Tree read follow-up after row 62 (2026-10-11) + +Status: written by Sage, lead. It follows `docs/plans/BRIEF-TEMPLATE.md` +and amends no section of `docs/plans/2026-10-11_multi-project-sync.md`. +One row, tests and the fake only. + +## Tree read follow-up: confirm-read tests and the fake's view 404 + +### Problem + +Row 62 (#1555) shipped the project-tree read, commit 390d437b. Filbert +(comment 27317) and Dewey (comment 27338) approved round 3 on manifest +8b81e836 and left notes, none blocking. + +- Filbert N3, survivor `r3-confirm-4xx`. `leftTree()` drops a child only + when its confirm read, `GET /projects/`, answers 403 or 404. No + test gives the confirm read some other failure (a 429 or a 401) after a + 404 on the child's task list, so a mutant that treats any 4xx as + "left" survives. Filbert's suggested step for test 18: a 404 on the + task list, then a 429 or 401 on the project read, and the tick refuses. +- Dewey's survivor `r3-confirm-error-on-throw`. Nothing tests the confirm + read when the call itself fails, so a mutant that changes its error + path survives. +- The fake answers a missing kanban view with code 13001. On + tasks.woltje.com v2.7.0, `GET /projects/18/views/2147483647/buckets/tasks` + answered 404 with code 3014 while `GET /projects/18` answered 200 + (Sage's live read, `agents/sage/work/vikunja-setup/2026-10-11_tick-62.json`). + The adapter treats any 404 without code 4002 the same way, so behavior + doesn't change, but the fake and the comment in + `tree.test.mjs` ("The board answers 404 with code 13001") should match + the live answer. That read used an id no view has. A view that exists + under another project was not read live. + +The live read also confirmed what the README says about a deleted view: +the project still reads 200, so the child stays and the whole tick fails +until the next reconcile reads it watch-only. Filbert noted this stops +the root's tick too, up to `reconcileMinutes`. That is the fail-closed +choice row 62 made, and it stays. + +### Owner and reviewer + +Owner: Darkwing, after their rows 58, 61 and 69. Reviewers: Dewey and +Filbert. + +### Files owned + +- `packages/tasks/tests/tree.test.mjs` +- `packages/tasks/src/fake.mjs`, the missing-view 404 body only + +### What ships + +- A step in test 18, or a new test, where the child's task list answers + 404 and its project read answers 429, and another where it answers + 401. Each tick refuses and the child stays in the tree. Mutant + `r3-confirm-4xx` fails it. +- A test where the confirm read's call fails (status 0 or a thrown fetch) + and the tick refuses. Mutant `r3-confirm-error-on-throw` fails it. +- The fake answers a missing kanban view with code 3014, citing the live + record, and the test comment says 3014. If Darkwing's v2.7.0 checkout + shows a view that exists under another project answers a different + code, the fake keeps that case apart and the packet says where it + comes from. +- The packet reruns the named mutants against the candidate and lists + them killed. + +### Out of scope + +Any change to `sync.mjs` or `startup.mjs`. The deleted-view behavior +(the tick fails until the next reconcile) stays as row 62 shipped it. A +cheaper path for it, such as dropping a child to watch-only at the tick, +would be its own row with a decision. Filbert's round 2 N2 survivors +(`keep-negative`, `no-parent-shape`, `no-sort`) stay untested, as they +asked for no tests. + +### Gate + +Dewey and Filbert approve on the row's issue naming the candidate +manifest. The tasks and bus node suites and every `scripts/test-*.sh` +green on Sage's gate rerun.