Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 14 additions & 13 deletions .claude/rules/worktrees.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ the *shape* of the work, not on the strand boundary.

That switches the current worktree to `feature/q2-preview-command`,
fast-forward-pulls (so any sibling sub-tasks that merged in the
meantime show up), creates a fresh `beads/bd-yxqt-<slug>` topic
meantime show up), creates a fresh `braid/bd-yxqt-<slug>` topic
branch off the new tip, marks the braid strand `in_progress` (via
`braid update`), and rewrites the `CLAUDE.local.md` context block.
Omit `--from` to branch off the current HEAD.
Expand All @@ -53,7 +53,7 @@ Each sub-task lives on its own topic branch. When a sub-task closes:

```bash
git switch feature/q2-preview-command
git merge --no-ff beads/<id>-<slug>
git merge --no-ff braid/<id>-<slug>
git push origin feature/q2-preview-command
```

Expand All @@ -70,17 +70,18 @@ All worktrees live in `.worktrees/` at the project root. This directory is git-i
## Branch naming

- **GH issue triage worktree** → branch `issue-<N>` at `.worktrees/issue-<N>/`. Local branch stays bare; only the remote uses a prefix (see § Pushing for PR).
- **Braid strand investigation worktree** → branch `beads/<id>-<slug>` at `.worktrees/<id>-<slug>/`, where `<slug>` is a short kebab-case form of the strand title (3–5 words, lowercase).
- **In-place sub-task branch (via `switch-task`)** → branch `beads/<id>-<slug>` *without* a corresponding `.worktrees/` directory; the branch lives wherever the caller's worktree is checked out.
- **Braid strand investigation worktree** → branch `braid/<id>-<slug>` at `.worktrees/<id>-<slug>/`, where `<slug>` is a short kebab-case form of the strand title (3–5 words, lowercase).
- **In-place sub-task branch (via `switch-task`)** → branch `braid/<id>-<slug>` *without* a corresponding `.worktrees/` directory; the branch lives wherever the caller's worktree is checked out.

The directory mirrors the leaf of the branch name. The conventions are stable so colleagues and tooling can recognize a worktree's origin from the path alone.

> **Note on the `beads/` branch prefix.** It is a *historical* git
> namespace, kept after the braid migration because the xtask code emits
> it and tooling/muscle-memory recognize it. It does not imply beads is
> involved — the strand lives in the braid skein. Renaming the prefix to
> `braid/` is a separable future cleanup (it would touch
> `create_worktree.rs`, `switch_task.rs`, and this convention together).
> **Note on the `braid/` branch prefix.** It is a plain git namespace —
> the strand lives in the braid skein, and the branch name just mirrors
> its id. It was renamed from the historical `beads/` prefix (bd-yjh1y117)
> after the beads→braid migration; the emitter is `strand_branch()` in
> `create_worktree.rs`, shared by `create-worktree` and `switch-task`.
> Pre-rename branches/worktrees may still carry `beads/` locally; that is
> harmless.

## Fresh worktree bootstrap

Expand Down Expand Up @@ -170,14 +171,14 @@ which is regenerated from the skein and never hand-edited or re-imported.

## Pushing for PR

Local branch names stay bare (`issue-<N>`, `beads/<id>-<slug>`). The remote branch name uses a prefix that reflects the work type — `bugfix/`, `feature/`, etc.:
Local branch names stay bare (`issue-<N>`, `braid/<id>-<slug>`). The remote branch name uses a prefix that reflects the work type — `bugfix/`, `feature/`, etc.:

```bash
# GH issue, bug fix
git push -u origin issue-<N>:bugfix/issue-<N>

# Braid strand, feature work
git push -u origin beads/<id>-<slug>:feature/<id>-<slug>
git push -u origin braid/<id>-<slug>:feature/<id>-<slug>
```

This keeps local branches short and consistent while remote refs are self-describing in PR lists.
Expand All @@ -188,7 +189,7 @@ If `cargo xtask create-worktree` is unavailable (fresh clone before first build,
the xtask binary is broken on the current branch), fall back to manual setup:

```bash
git worktree add -b beads/<id>-<slug> .worktrees/<id>-<slug> main
git worktree add -b braid/<id>-<slug> .worktrees/<id>-<slug> main
```

No redirect step is needed (see § Braid skein resolution above). Verify with
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Copy the body below into `claude-notes/plans/YYYY-MM-DD-<slug>.md` and fill it i

**Date:** YYYY-MM-DD
**Beads:** bd-XXXX
**Worktree:** `.worktrees/<id>-<slug>` (branch `beads/<id>-<slug>`, based on `main` @ `<short-sha>`)
**Worktree:** `.worktrees/<id>-<slug>` (branch `braid/<id>-<slug>`, based on `main` @ `<short-sha>`)
**Status:** Investigation — pending design alignment with user. **Do not start implementation until the user gives the go-ahead.**

## Triage verdict
Expand Down
6 changes: 3 additions & 3 deletions .claude/skills/preview-render-parity/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,10 @@ EOF
)"
# braid prints the new strand id on stdout. Capture it as <id>.
braid update <id> --status in_progress
git switch -c beads/<id>-<short-slug>
git switch -c braid/<id>-<short-slug>
```

bd-kw93 is the q2-preview epic; every parity sub-strand is parent-child to it. (The git branch prefix stays `beads/` — a stable historical namespace.)
bd-kw93 is the q2-preview epic; every parity sub-strand is parent-child to it. (The git branch prefix is `braid/` — a plain git namespace, renamed from the historical `beads/` in bd-yjh1y117.)

### Write the failing test FIRST

Expand Down Expand Up @@ -222,7 +222,7 @@ git commit -m "...(bd-<id>)"

# Merge --no-ff into the integration branch
git switch feature/q2-preview-command
git merge --no-ff beads/<id>-<slug> -m "Merge bd-<id>: <one-line>"
git merge --no-ff braid/<id>-<slug> -m "Merge bd-<id>: <one-line>"

# Push (only after explicit user OK, per CLAUDE.md GIT PUSH POLICY)
git push origin feature/q2-preview-command
Expand Down
28 changes: 27 additions & 1 deletion crates/xtask/src/create_worktree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,15 @@ pub fn validate_slug(slug: &str) -> Result<()> {
Ok(())
}

/// Local git branch name for a braid strand's worktree / topic branch:
/// `braid/<leaf>`, where `<leaf>` is `<id>-<slug>`. The `braid/` prefix is a
/// plain git namespace (renamed from the historical `beads/` — bd-yjh1y117); it
/// does not imply beads involvement. Remote refs use a work-type prefix
/// (`bugfix/`, `feature/`) chosen at push time, not here.
pub fn strand_branch(leaf: &str) -> String {
format!("braid/{leaf}")
}

#[derive(clap::Args)]
#[command(group(clap::ArgGroup::new("mode").required(true).multiple(false)))]
pub struct Args {
Expand Down Expand Up @@ -742,7 +751,7 @@ fn plan_braid(id: &str, slug_override: Option<&str>, base: &str, repo_root: &Pat
eprintln!("note: external_ref {other:?} is not a `gh-` reference; omitting GitHub line");
}
Ok(Plan {
branch: format!("beads/{leaf}"),
branch: strand_branch(&leaf),
dir: repo_root.join(".worktrees").join(&leaf),
base: base.to_string(),
kind: SectionKind::Braid {
Expand Down Expand Up @@ -1035,6 +1044,23 @@ mod tests {
);
}

#[test]
fn strand_branch_uses_the_braid_prefix() {
assert_eq!(
strand_branch("bd-abcd-some-slug"),
"braid/bd-abcd-some-slug"
);
let b = strand_branch("bd-x");
assert!(
b.starts_with("braid/"),
"strand branch must use the braid/ prefix: {b}"
);
assert!(
!b.starts_with("beads/"),
"historical beads/ prefix must be gone: {b}"
);
}

#[test]
fn repo_root_returns_absolute_directory_with_dot_git() {
// Test runs inside this checkout, so repo_root() must succeed and
Expand Down
6 changes: 3 additions & 3 deletions crates/xtask/src/switch_task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
//! That:
//! 1. switches the current worktree to `feature/q2-preview-command`
//! and runs `git pull --ff-only` so it picks up siblings' merges,
//! 2. creates a new topic branch `beads/<id>-<slug>` off the new
//! 2. creates a new topic branch `braid/<id>-<slug>` off the new
//! tip,
//! 3. marks the braid strand `in_progress`,
//! 4. rewrites the `<!-- BEGIN/END WORKTREE CONTEXT -->` block in
Expand All @@ -33,7 +33,7 @@ use std::process::Command;

use crate::create_worktree::{
IssueMetadata, SectionKind, build_section, derive_slug, fetch_issue_metadata,
parse_external_ref_to_github_url, update_claude_local_md, validate_slug,
parse_external_ref_to_github_url, strand_branch, update_claude_local_md, validate_slug,
};

/// Find the *current worktree's* root via `git rev-parse --show-toplevel`.
Expand Down Expand Up @@ -84,7 +84,7 @@ pub fn run(args: Args) -> Result<()> {
}
None => derive_slug(&meta.title)?,
};
let branch = format!("beads/{}-{}", args.beads_id, slug);
let branch = strand_branch(&format!("{}-{}", args.beads_id, slug));

if let Some(from) = args.from.as_deref() {
// Best-effort fetch so origin/<from> reflects the latest tip.
Expand Down
Loading