Skip to content

Commit 3f8bf59

Browse files
authored
feat: worktree-native workspace for parallel branch work (#22)
* feat: worktree-native workspace for parallel branch work Add four new abilities — workspace-worktree-add|list|remove|prune — and a matching "workspace worktree" CLI subcommand. The workspace now stores each branch in its own directory at <workspace>/<repo>@<branch-slug>, so multiple agent sessions can edit different branches of the same repo simultaneously without stepping on each other. All existing read/write/git abilities accept the new <repo>@<branch-slug> handle alongside bare repo names; resolution happens through Workspace:: parse_handle() and a single resolve_repo_path() call site. Mutating ops on the primary checkout (bare <repo>) now require allow_primary_mutation=true / --allow-primary-mutation. The default-deny codifies the "primary tracks the deployed branch, hands off" rule that lived as informal discipline before. Worktrees are always allowed. clone rejects @-suffixed names; remove refuses to delete a primary that has linked worktrees attached; git push only enforces fixed_branch on the primary, freeing worktrees to push any branch. Includes pure-PHP smoke test for handle parsing/slugify (tests/ smoke-worktree-handles.php, 32/32 passing) and a manual end-to-end test plan (tests/TESTING.md). AGENTS.md generator and README updated to teach the worktree-first workflow. * fix: live-test fixups from dogfooding on intelligence-chubes4 Found and fixed during end-to-end testing on the intelligence-chubes4 site (DATAMACHINE_WORKSPACE_PATH=~/Developer): - Ability callbacks now declare `array|WP_Error` return types so the primary-mutation guard (and other WP_Error returns) propagate cleanly instead of throwing a TypeError in WorkspaceAbilities::*. - Add `--allow-primary-mutation` to the `workspace git` CLI docblock so WP-CLI accepts the flag. - `workspace list` now surfaces `kind` (primary|worktree) and `repo` columns so the new on-disk model is visible. - `workspace-worktree-list` allows `branch_slug` and `branch` to be null in its output schema (primaries have no slug; detached heads have no branch). - New `external` field on worktree-list output. Worktrees outside the workspace path (e.g. /private/tmp/dm-worktrees/post-tracking from a manual `git worktree add`) now report their absolute path as the handle instead of a mangled relative slice. - New `Workspace::resolve_default_base()` helper. `worktree add` defaults to `origin/HEAD` when --from is omitted (per design), with a safe fallback to plain HEAD if origin/HEAD is unset. Live test summary on intelligence-chubes4: - ✓ workspace list shows primary/worktree split - ✓ worktree add data-machine-code test/smoke (created) - ✓ worktree list discovers both in-workspace and external worktrees - ✓ git status data-machine-code@test-smoke - ✓ primary mutation guard fires (blocked by existing write_enabled policy first; both gates work) - ✓ clone --name=foo@bar rejected (`@` reserved for worktrees) - ✓ worktree remove cleans the directory and prunes the registry - ✓ end-to-end on mcp-context-wporg with explicit --from=origin/main Note: workspace read/write/edit/ls still hit the pre-existing Studio WASM mount limitation when paths are outside the site folder. Tracked elsewhere; unrelated to this PR.
1 parent 6725718 commit 3f8bf59

8 files changed

Lines changed: 1369 additions & 151 deletions

File tree

README.md

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,18 +45,45 @@ wp datamachine-code workspace path
4545
wp datamachine-code workspace list
4646
wp datamachine-code workspace clone https://github.com/org/repo.git
4747
wp datamachine-code workspace show repo-name
48-
wp datamachine-code workspace read repo-name src/main.php
49-
wp datamachine-code workspace ls repo-name src/
50-
wp datamachine-code workspace write repo-name path/to/file.txt @content.txt
51-
wp datamachine-code workspace edit repo-name path/to/file.txt --old="foo" --new="bar"
48+
49+
# Worktrees — one per branch, parallel-safe
50+
wp datamachine-code workspace worktree add repo-name fix/foo
51+
wp datamachine-code workspace worktree list
52+
wp datamachine-code workspace worktree remove repo-name fix/foo
53+
wp datamachine-code workspace worktree prune
54+
55+
# All read/write/git ops accept either <repo> (primary) or <repo>@<branch-slug> (worktree)
56+
wp datamachine-code workspace read repo-name@fix-foo src/main.php
57+
wp datamachine-code workspace ls repo-name@fix-foo src/
58+
wp datamachine-code workspace write repo-name@fix-foo path/to/file.txt @content.txt
59+
wp datamachine-code workspace edit repo-name@fix-foo path/to/file.txt --old="foo" --new="bar"
5260
wp datamachine-code workspace remove repo-name
53-
wp datamachine-code workspace git status repo-name
54-
wp datamachine-code workspace git pull repo-name
55-
wp datamachine-code workspace git add repo-name --paths=src/file.php
56-
wp datamachine-code workspace git commit repo-name --message="fix: something"
57-
wp datamachine-code workspace git push repo-name
58-
wp datamachine-code workspace git log repo-name
59-
wp datamachine-code workspace git diff repo-name
61+
wp datamachine-code workspace git status repo-name@fix-foo
62+
wp datamachine-code workspace git pull repo-name@fix-foo
63+
wp datamachine-code workspace git add repo-name@fix-foo --path=src/file.php
64+
wp datamachine-code workspace git commit repo-name@fix-foo "fix: something"
65+
wp datamachine-code workspace git push repo-name@fix-foo
66+
wp datamachine-code workspace git log repo-name@fix-foo
67+
wp datamachine-code workspace git diff repo-name@fix-foo
68+
```
69+
70+
### Worktrees: parallel-safe branch work
71+
72+
The workspace is **worktree-native**. Each branch lives in its own directory at
73+
`<workspace>/<repo>@<branch-slug>` (slashes in branch names become dashes). Multiple
74+
agent sessions can edit different branches of the same repo simultaneously without
75+
stepping on each other.
76+
77+
The primary checkout (bare `<repo>`) is **read-only by default** for mutating
78+
operations — pass `--allow-primary-mutation` to override. The default-deny is
79+
intentional: the primary tracks the deployed branch, and silent branch-switches
80+
on it are how parallel agents corrupt each other's work.
81+
82+
```
83+
~/.datamachine/workspace/
84+
├── data-machine/ ← primary, hands-off by default
85+
├── data-machine@fix-foo/ ← worktree for fix/foo
86+
└── data-machine@feat-bar/ ← worktree for feat/bar
6087
```
6188

6289
## Requirements

data-machine-code.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,9 +294,11 @@ function datamachine_code_load_chat_tools() {
294294
- Discover available handlers: `{$wp} datamachine handlers list`
295295
296296
**Code (data-machine-code):** All code changes go through the managed workspace and GitHub — never edit site files directly.
297-
- Workspace: `{$wp} datamachine-code workspace clone|read|write|edit|git` — clone repos, create branches, edit files, commit, and push
297+
- Workspace: `{$wp} datamachine-code workspace clone|worktree|read|write|edit|git` — clone repos, create per-branch worktrees, edit files, commit, and push
298298
- GitHub: `{$wp} datamachine-code github issues|pulls|repos|comment` — create PRs, manage issues, comment on reviews
299-
- **Workflow:** clone → branch → edit → commit → push → PR. The workspace is a git checkout separate from the live site.
299+
- **Workflow:** clone → `worktree add <repo> <branch>` → edit → commit → push → PR. Operate on the `<repo>@<branch-slug>` handle (e.g. `data-machine@fix-foo-bar`); never branch-switch the primary checkout.
300+
- **Why worktrees:** every parallel session gets its own checkout on disk. Multiple agents can cook features in the same repo without stepping on each other.
301+
- **Primary is read-only by default:** mutating ops on bare `<repo>` handles require `--allow-primary-mutation`. The primary tracks the deployed branch — leave it alone unless you really mean it.
300302
- **Rule:** Never modify files under `wp-content/plugins/` or `wp-content/themes/` directly. Those paths are for **reading source** only. All code changes must go through the workspace so they are tracked in git and reviewed via pull requests.
301303
302304
**System:** `{$wp} datamachine system health|prompts|run`

docs/CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,22 @@
22

33
All notable changes to Data Machine Code will be documented in this file.
44

5+
## [Unreleased]
6+
7+
### Added
8+
- Worktree-native workspace: each branch lives in its own directory at `<workspace>/<repo>@<branch-slug>`. Multiple agent sessions can edit different branches of the same repo simultaneously.
9+
- Four new abilities: `datamachine/workspace-worktree-add|list|remove|prune`.
10+
- New CLI subcommand: `wp datamachine-code workspace worktree add|list|remove|prune`.
11+
- All read/write/git abilities accept the new `<repo>@<branch-slug>` handle format alongside bare repo names.
12+
- Pure-PHP smoke test for handle parsing and slug generation (`tests/smoke-worktree-handles.php`).
13+
- Manual end-to-end test plan (`tests/TESTING.md`).
14+
15+
### Changed
16+
- `clone` rejects names containing `@` — that suffix is reserved for worktrees.
17+
- `remove` refuses to delete a primary checkout that has linked worktrees attached.
18+
- `git push` only enforces the `fixed_branch` policy on the primary checkout. Worktrees may push any branch.
19+
- Mutating ops (`git pull|add|commit|push`) on a primary checkout require `--allow-primary-mutation` (CLI) / `allow_primary_mutation: true` (ability input). Worktrees are always allowed. Default-deny prevents parallel agents from clobbering the deployed branch.
20+
521
## [0.4.0] - 2026-04-15
622

723
### Added

0 commit comments

Comments
 (0)