Skip to content

fix(core): keep the recorded project name inside a git worktree - #60

Merged
joris-sevenlab merged 1 commit into
mainfrom
fix/worktree-project-name
Oct 5, 2026
Merged

joris-sevenlab merged 1 commit into
mainfrom
fix/worktree-project-name

Conversation

@joris-sevenlab

Copy link
Copy Markdown
Collaborator

What this changes

Inside a linked git worktree, battlestack now uses the project name recorded in .battlestack/manifest.json instead of the worktree's directory name. A rename of the main checkout is still detected and restamped as before.

Why

The project name came from path.basename(projectDir). Running any command in git worktree add ../my-app-feature was treated as a directory rename:

  • the committed manifest's projectName was overwritten and the real name moved into previousNames
  • pull, add and upgrade regenerated committed files with the worktree name: the package.json name, the compose name:, the AGENTS.md / README.md titles and the PWA manifest
  • runtime checks (describe, port diagnosis, compose detection) looked for containers under the worktree name while docker-compose.yml still said the real one, which caused duplicate containers and errors
  • cleanup in a worktree could list the main checkout's live containers and volumes as leftovers from a "previous name"

Type of change

  • Bug fix

AI assistance

  • Claude Code

Agent, service and model, if you know it: Claude Code, Opus 5.5

How much of this is agent-written?

  • Substantial parts, with my own edits on top

Feature versions

  • Not applicable

Testing

pnpm tsc
pnpm test   # 87 files, 990 passed, 1 skipped

packages/core/test/project-name.test.ts creates a real repo plus git worktree add in a tmp dir and checks:

  • the name resolves to the recorded one in the worktree, from resolveProjectName and from buildRunContext
  • neither reconcileProjectName nor writeManifest changes projectName or previousNames there
  • a renamed main checkout still restamps
  • a submodule-style .git file is not mistaken for a worktree

With the fix removed, the three worktree tests fail. The rename and detection tests keep passing.

  • pnpm tsc passes
  • pnpm test passes
  • I removed the behaviour each new assertion covers, watched the test fail, and put it back

Checklist

  • Scoped to one concern
  • Public-facing docs updated where behaviour changed (docs/troubleshooting.md)
  • No internal tracker numbers, post-mortem narrative, or internal infrastructure details in the diff
  • No secrets, tokens or real credentials

Anything else

  • A worktree now shares the compose project and hash-derived port defaults with the main checkout. That matches the name: already committed in docker-compose.yml. Fully isolated per-worktree stacks would be a separate feature.
  • A worktree that was already broken by the old behaviour keeps the wrong name in its manifest. Reset .battlestack/manifest.json from main (or fix projectName and previousNames by hand) before running battlestack pull.
  • A plain clone into a differently named folder still counts as a rename. That is unchanged.

The project name came from the directory name. In a linked worktree
(`git worktree add ../my-app-feature`) the first command treated the new
directory as a rename: it restamped `projectName` in the committed
manifest, pushed the real name into `previousNames`, and fed the worktree
directory name into everything derived from ctx.projectName, including
the package.json name, the compose `name:`, the AGENTS.md title and the
port hashes. Runtime checks then looked for containers under a compose
project that the committed docker-compose.yml did not use, and `cleanup`
in the worktree could offer to remove the main checkout's containers as
"detached" leftovers.

resolveProjectName returns the manifest's recorded name inside a linked
worktree and the directory name everywhere else. writeManifest,
buildRunContext, reconcileProjectName and the CLI's own context builders
(add/remove, upgrade, describe, cleanup) all go through it, so a rename
of the main checkout is still detected.

A worktree is told apart by a `commondir` file in the directory its
`.git` file points to. Checking for a `.git` file alone would also match
submodules.
@joris-sevenlab
joris-sevenlab merged commit 80f4235 into main Oct 5, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants