Skip to content

feat(workspace): opt-in worktree file provisioning for gitignored-but-required files - #18

Open
gregberns wants to merge 2 commits into
mainfrom
feat/worktree-provision-files
Open

feat(workspace): opt-in worktree file provisioning for gitignored-but-required files#18
gregberns wants to merge 2 commits into
mainfrom
feat/worktree-provision-files

Conversation

@gregberns

Copy link
Copy Markdown
Owner

Motivation

The daemon cuts a fresh git worktree per bead. git worktree add checks out only tracked files, so a gitignored-but-required .env (consumed by a docker compose --env-file ../.env test gate) is absent in the fresh worktree → the gate fails instantly (couldn't find env file) → the bead fails before any work runs.

This deadlocked an entire fleet in the omatic-system-plan project; the workaround forces serial execution against one shared stack. This PR is the opt-in, durable fix.

Design

  • New per-daemon config key daemon.worktree_provision_files (a list of repo-root-relative paths).
  • workspace.ProvisionWorktreeFiles(projectRoot, worktreePath, relPaths) copies each configured file from the canonical project root into the same relative path in the freshly created worktree (creating parent dirs, preserving mode).
  • Called immediately after a worktree is successfully created, LOCAL runs only (remote/SSH-worker worktrees live on another host and are skipped — a future bead may stream them over the SSHRunner).
  • Opt-in / backward-compatible: empty or absent worktree_provision_files = a no-op; existing behavior is unchanged.
  • Safety: absolute paths and ..-escaping paths are rejected; a missing source file is warn-skipped (optional input — only some developers may have it); a provision error at the call site is logged and non-fatal so a stray config entry never wedges dispatch.

What this PR adds

The ProvisionWorktreeFiles function + config field were banked in a prior WIP commit on this branch. This completes the wiring:

  • internal/daemon/projectconfig.go — map raw.Daemon.WorktreeProvisionFilesDaemonConfig.WorktreeProvisionFiles (mirrors AllowedRepos / RemoteControlPrefix).
  • internal/daemon/workloop.go — add a worktreeProvisionFiles deps field (sourced from cfg.ProjectCfg.Daemon.WorktreeProvisionFiles, mirroring allowedRepos) and call ProvisionWorktreeFiles after worktree creation, gated on rbc == nil (local only).
  • internal/workspace/provisionfiles_test.go — focused unit test.

Testing

  • go build ./... — clean (0 errors).
  • go test ./internal/workspace/...ok (7 new ProvisionWorktreeFiles subtests pass: empty-list no-op; copy preserving content+mode incl. nested parent-dir creation; missing-source warn-skip with sibling still copied; absolute / .. / bare-.. rejection).
  • The pre-existing internal/daemon integration/scenario failures (T3/T6/ReviewLoop/OrphanSweep/Reap — br --version handshake failed / claim-timeout) were verified to fail identically on the parent commit without these changes; they are environmental and unrelated to this work.

Does NOT touch BeadsVersion / internal/release/manifest.go (deliberately excluded).

🤖 Generated with Claude Code

Greg Berns and others added 2 commits June 25, 2026 07:38
Completes the worktree-file-provisioning feature: maps the new
worktree_provision_files config into DaemonConfig, calls
ProvisionWorktreeFiles at the local worktree-creation site, and adds a
focused unit test for the provisioning function.

- projectconfig.go: copy raw.WorktreeProvisionFiles into
  DaemonConfig.WorktreeProvisionFiles (mirrors AllowedRepos /
  RemoteControlPrefix). Without this the config field was dead.
- workloop.go: add a worktreeProvisionFiles field on the work-loop deps
  (sourced from cfg.ProjectCfg.Daemon.WorktreeProvisionFiles, mirroring
  allowedRepos) and call workspace.ProvisionWorktreeFiles(activeRepo,
  wtPath, ...) immediately after the worktree is created, LOCAL runs only
  (rbc == nil). Remote/SSH-worker worktrees live on another host and are
  skipped. A provision error is logged and non-fatal so a stray config
  entry never wedges dispatch.
- provisionfiles_test.go: covers empty-list no-op, copy preserving
  content+mode (incl. nested parent-dir creation), missing-source
  warn-skip (no error, sibling still copied), and absolute / .. / bare-..
  path rejection.

Backward-compatible: empty/absent worktree_provision_files = current
behavior, zero change. go build ./... and go test ./internal/workspace/...
pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

1 participant