# Row 145: the stacked and conflicting vikunja-19 merges, rebased Sage, 2026-10-15. Brief: `docs/plans/2026-10-15_vikunja-19-landings.md`, second section. Issue #1639. Reviewer: Filbert. Base: 193ae70c6 (row 144's last commit). Built in a detached worktree at `/mnt/storage/scratch/sage-r145/wt`. The five commits are in the canonical object store; `git show ` works from the canonical checkout. | Order | Task | Source diff | Landed commit | Verdict | Decision | |-------|------|-------------|---------------|---------|----------| | 1 | 306 | bbf61d6dd..3c80fea74 | 077f3a0fc | 8ee5be8b | 0eebf83f `all` | | 2 | 295 | 07c12b51b..813671596 (7 commits, includes 296) | 09af8a19b | 51c71b46 | 29ff6589 `all` | | 3 | 307 | 813671596..6219c5c8c | d268a4d94 | 84c9c4be | 17bb9efc `merge` | | 4 | 305 | 813671596..f4d7b91a9 | 90443879d | 57d7f0b7 | 0eebf83f `all` | | 5 | 309 | f4d7b91a9..0e7d1d8b8 | 4547869a6 | dfd44af2 | 12a20e47 `merge` | Each commit message names its source, verdict, decision and resolution. `diffs/-landed.diff` is `git show --stat --patch` of the landed commit. ## How each path was checked `check.sh FROM SOURCE BASE`, run on the staged tree before each commit: - `same-blob`: refactor didn't touch the path since FROM, and the staged blob equals the source commit's. - `merged`: refactor also changed the path, and the +/- lines of the staged diff against the new base equal the +/- lines of the source diff. - Anything else is printed as DIFFERS. Only the conflict paths below did. ## Conflicts and resolutions Each `conflicts/` file is the path with git's markers, as `git apply --3way` left it. "ours" is refactor plus the earlier tasks of this row; "theirs" is the task's source diff. The resolution is in the landed diff. 1. **295, `packages/harness/src/tools.mjs`** (`conflicts/295-tools.conflict.mjs`). Row 132 (0e947c216) and 295 both add a tool block after review_verdict. Kept row 132's end_run and change_organization block, then 295's web_search and web_fetch block, each closed with its own `}`. Seven other paths merged, twenty are the source blobs. 2. **307, `packages/harness/src/tools.mjs`** (`conflicts/307-tools.conflict.mjs`). Both add a constant after TASK_PAGE_MAX: row 132's ORGANIZATION_KEYS and 307's `WEB_QUERY_MAX = 400`. Kept both, row 132's first. Three paths merged, nine are the source blobs. 3. **305, `packages/bus/src/broker.mjs`** (`conflicts/305-broker.mjs.conflict`). Row 123 (89fd2d6fe) and 305 both extend the limits branch of `request()`. Row 123 adds organization.set with a role path, an actor and ORGANIZATION_KEYS; 305 adds plugins and plugins.set. Resolution: - The verb list is the union: limits, limits.set, organization.set, plugins, plugins.set. - The keys lines are 305's, with row 123's ORGANIZATION_KEYS in the last branch. - Row 123's role, human and actor lines are kept unchanged. Behavior check. `role` is true only for organization.set, so plugins and plugins.set still fail `human-required` for a non-human, take the human as actor, and reach the organization writer with their own verb, as in 305. organization.set takes the same path as before. 305's `invalid-plugins` and `unknown-plugin` catch line merged without conflict. 4. **305, `packages/plugins/tests/searxng.test.mjs`** (`conflicts/305-searxng.test.mjs.conflict`). 307 and 305 each add a test at the end of the file. Kept 307's AbortSignal test, then 305's hasModule test. 305 is stacked on 295, not on 307, so its diff meets 307's changes on the new base. That is why the searxng test conflicts. Three other 305 paths (runtime.mjs, cli.mjs, plugins/README.md) merged; six are the source blobs. 306 and 309 had no conflicts. 309's plugins/README.md merged; its other four paths are the source blobs. ## Tests run so far Single files only, from the worktree: - 305: bus plugins-verb, cli limits, every plugins test and business plugin-settings: 39 pass. bus broker and limits: 19 pass. bus chief-of-staff and harness tools (organization.set): 30 pass. 0 fail. - 309: bus plugins-verb, business plugin-settings and every cli test: 217 pass, 0 fail. The full gate runs on the final tip once the slot is free, before the push. ## Candidate `candidate-manifest.sha256` lists the 48 paths that change from 193ae70c6 to 4547869a6, with their sha256 at the tip. Round 1's tip was 0308c1fde, manifest c8272046...8a92; see "Round 2". Canonical has since moved to 8eae4eae6 (Dewey's packet and a SESSIONS line, no shared path). At landing the five commits are replayed onto refactor's HEAD. The manifest doesn't change unless a later commit touches one of its paths, and if one does I re-round. ## Round 2 Filbert's round 1 (#1639, comment 28623) blocked on `packages/bus/tests/csuite-messaging.test.mjs`. 306 added it as a source blob, and on the new base it gave 1 pass and 15 fail, all `thread-required`. Row 121 (2c16d6b93) made assistant a thread definition, and `bindLaunch` refuses an assistant run without a thread. 306's `setup()` bound every role without one. No text conflicted, so the path checks passed it, and my single-file runs didn't include it. Resolution, in the 306 commit: `setup()` binds the human first, the human creates a project and a thread, and the assistant's `bindLaunch` gets that thread. No assertion and no product code changed. The assistant's message to a C-suite role is still refused with `message-recipient-refused`. I read this as merging 306 with row 121, the same reading as Filbert's, so it stays inside the brief's conflict-resolution rule. The fix is folded into the 306 commit, and 295, 307, 305 and 309 are replayed unchanged on top. `git diff 0308c1fde 4547869a6` is only this file, 5 insertions and 3 deletions. Old to new commits: 81860fa12 to 077f3a0fc, e64f49d42 to 09af8a19b, 6f27e0ab6 to d268a4d94, 54a456b4c to 90443879d, 0308c1fde to 4547869a6. Only the manifest line for this test changed. `csuite-messaging.test.mjs` on the new 306 commit: 16 pass, 0 fail. Other unchanged tests may break the same way. The full gate on 4547869a6 covers that, and it runs before the push. Every test file the five commits add or change, 15 files, on 4547869a6: 162 pass, 0 fail. ## Landed Filbert approved round 2 (#1639, comment 28625, rev 1395) on candidate c65e1ada...157b. The five commits were replayed onto canonical df5bbfb82 as 5bcf6d80a, 2307d69fa, e2a13b5d7, 03b54bfb5 and 9357baac9. Nothing under packages, roles or scripts differs from 4547869a6. Gate on 9357baac9: the full template, every package suite except queue and every `scripts/test-*.sh`, from 22:45:55Z to 22:50:33Z, GATE_PASSED, exit 0, 24 steps rc 0, no flake. Canonical had moved to 5a5509839 (Filbert's SESSIONS line, docs only). The same five commits were cherry-picked onto it without conflict: | Task | Landed commit | |------|---------------| | 306 | 92938ab43 | | 295 | e9f4431ec | | 307 | ae74c25fd | | 305 | 467a313c7 | | 309 | fba879f6a | `git diff 9357baac9 fba879f6a` is only docs/SESSIONS.md. The manifest checks against the landed tree, and `queue review verify-commit 145 HEAD` gives "HEAD matches the manifest candidate (48 paths)".