chore: adopt one-worktree-per-session workflow

Sessions that change files now work in their own git worktree and merge back to
`develop`, instead of developing directly in the main checkout. Documents the
tool's actual behaviour rather than the assumed one: `EnterWorktree` prefixes the
branch as `worktree-<name>`, branches from the last commit (so uncommitted edits
do not carry over), and `ExitWorktree({action: "remove"})` deletes the branch
with the directory — hence the merge must happen before the cleanup.

Base ref is pinned to `head` in `.claude/settings.json` because `develop` runs
well ahead of `origin/main`, and the default `fresh` would branch from the stale
release trunk.

Also ignores `.claude/worktrees/`, which lives on disk per session and is never
committed.
This commit is contained in:
Yaojia Wang
2026-07-29 11:13:26 +02:00
parent 553a00c32f
commit 1137090626
2 changed files with 23 additions and 0 deletions

3
.gitignore vendored
View File

@@ -17,6 +17,9 @@ desktop/dist-app/
# local Claude Code settings (not shared)
.claude/settings.local.json
# per-session git worktrees (EnterWorktree) — live on disk, never committed
.claude/worktrees/
# logs / OS cruft
*.log
npm-debug.log*

View File

@@ -16,6 +16,26 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
**Language decision: TypeScript (`.ts`), not `.js`** — ARCHITECTURE §0 records this divergence from TECH_DOC's original `.js` filenames. Wherever the two docs conflict, ARCHITECTURE wins on *how* (it was cross-validated and corrected); TECH_DOC wins on *why/scope*.
## Session Workflow: One Worktree per Session (MANDATORY)
**Every session that changes files works in its own git worktree, and merges back to `develop` when the work is done.** Don't develop directly on `develop` in the main checkout (the one exception is a change to this workflow itself — the rule can't bootstrap inside its own worktree).
1. **Start of session** — before touching any file, call the `EnterWorktree` tool with a task-descriptive name (e.g. `EnterWorktree({name: "fix-cjk-locale"})`). It creates `.claude/worktrees/<name>/` on branch **`worktree-<name>`** (the tool prefixes it — the name you pass is *not* the branch name) and moves the session's cwd into it. Do all work there.
- Base ref is `head` (configured in `.claude/settings.json``worktree.baseRef`), so the worktree branches from the **current `develop` HEAD**, not `origin/main`. This matters: `develop` runs ~75 commits ahead of `origin/main`, so the default `fresh` base ref would silently produce a badly stale worktree. `develop` is the working trunk; `main` is the release branch.
- It branches from the last **commit**, so uncommitted edits sitting in the main checkout do **not** carry over. Commit or stash them first if the task needs them.
- Read-only sessions (answering a question, inspecting a remote host) don't need a worktree — only create one when files will change.
2. **During the session** — commit inside the worktree as normal (conventional-commit format, see the global git-workflow rule). Tests/`tsc` run against the worktree copy, so concurrent sessions never collide on the working tree; each holds a `locked` worktree of its own, so never `git worktree remove` a directory this session didn't create.
3. **End of session — merge back.** Commit everything in the worktree first, then, **in this order**:
```bash
# 1. ExitWorktree({action: "keep"}) → cwd returns to the main checkout, branch survives
git merge --no-ff worktree-<name> # 2. from the main checkout, on develop
git worktree remove .claude/worktrees/<name> && git branch -d worktree-<name> # 3. clean up
```
**Order matters:** `ExitWorktree({action: "remove"})` deletes the branch along with the directory, so calling it before the merge throws the work away. (It does refuse when commits aren't yet on `develop` — a safety net, not a plan.) `keep` is also the right call whenever the work is unfinished and the session should be resumable.
4. **Do not merge to `main`** as part of this flow — `main` is promoted from `develop` separately.
Subagents dispatched with `isolation: worktree` (PLAN §4) get their own throwaway worktrees on top of this — that is a separate, nested mechanism and does not replace the session-level worktree.
## Development Workflow: Plan & Progress Log (MANDATORY)
Work proceeds against a **phased plan** and is tracked in a **progress log that acts as cross-session memory**. A new Claude instance must be able to read the log and know exactly where things stand. Follow these rules: