1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
# Multi-session: several sessions in one project
Approved 2026-10-04. Problem: one work tree + `master` shared by sessions → a commit sweeps the
other's edits (`git add -A`), half-done code breaks the other's tests, two sessions of a lane pick
the same task.
## 1. Claims
- `wf status ID progress …` writes `.wf/claims/ID.json` (who: socket, pid, lane, model); details in
`lanes.md` §4. `wf next` skips a task claimed by another live session.
- A second live session of a lane: `wf next` warns on its first line; the registry keeps the first one.
- Task line `Sessions: solo` → picked only while no other session is live; while it is in progress
(claimed) every other session's `wf next` picks nothing (exit 1, names the holder); its `wf done`
prints `notify <lane> uds:…: solo <id> done, run wf next` for each other live session.
`Sessions: owner` → picked only by `wf next --owner` (owner present).
## 2. Worktree mode (only while > 1 session is live, git projects)
- `wf next` prints `===== Multi-session =====`: from the main tree
`git worktree add .worktrees/<lane> -b <lane>/<task> master` (or `cd .worktrees/<lane> && git switch -c <lane>/<task> master`
when it exists), `&& wf setup` appended when workflow.toml has `worktree_setup`; inside a worktree a
reminder of where you are.
- `wf setup` (in a worktree) runs `worktree_setup` (cwd = worktree, env `WF_MAIN` = main tree): links /
copies git-ignored inputs (`out/…`). Idempotent; run after every worktree create/reuse.
- wf run inside a linked git worktree uses the main tree's project (same relative folder, when it
has `workflow.toml`): TASKS.md, archive, docs, `.wf/` are the main tree's. Bookkeeping never
conflicts; branches never touch TASKS.md. `wf check` there checks the main tree.
- One session alone: as before, on `master`.
## 3. Done in worktree mode
`wf done` run inside a linked worktree prints, after verify/checklist: commit code (explicit paths), then
`wf merge`. `wf merge` (under the project lock, `.wf/lock`): worktree must be clean → `git rebase master`
(conflict → abort, branch untouched: rebase by hand, resolve, verify, `wf merge` again) → `merge --ff-only`
into the main tree → commit TASKS.md + archive there (`<id> done`, id from the branch `<lane>/<id>`) →
detach the worktree, delete the branch → push home if the remote exists (`--no-push` skips).
The ff-merge of one's own task branch is a standing owner permission (shared CLAUDE.md); never other branches.
`wf finish <id> -m ENTRY [--commit MSG PATH…]` does it in one call (workers): refuses first if files outside
PATHS are uncommitted or quick_gate is red (task stays open) → `wf done` → commit PATHS → `wf merge`. In a main tree
(no worktree) TASKS.md + archive join that commit and nothing is merged. Verify runs before it (`wf ctx` prints it).
Next task: new branch from master in the same worktree.
## 3a. Project lock
Every wf write command and `wf merge` run under an exclusive flock on `.wf/lock` (main tree), so parallel
sessions/workers never lose a TASKS.md edit or race a merge-back.
## 4. Commits
Shared rule: stage explicit paths, never `git add -A` / `git commit -a`.
## Split projects
Code worktrees come from `wf start <id> --worktree <path> --branch <b>` run in the private project: it creates them in the
code repo (`code_root`) and writes `.wf-home` there. Inside such a worktree wf resolves the private project via `.wf-home`.
|