From 1137090626b1ad74c5a3472186dec97563961377 Mon Sep 17 00:00:00 2001 From: Yaojia Wang Date: Wed, 29 Jul 2026 11:13:26 +0200 Subject: [PATCH] chore: adopt one-worktree-per-session workflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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-`, 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. --- .gitignore | 3 +++ CLAUDE.md | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/.gitignore b/.gitignore index 747972f..1b961ad 100644 --- a/.gitignore +++ b/.gitignore @@ -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* diff --git a/CLAUDE.md b/CLAUDE.md index b42695f..45644c7 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -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//` on branch **`worktree-`** (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- # 2. from the main checkout, on develop + git worktree remove .claude/worktrees/ && git branch -d worktree- # 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: