Skip to content
Open
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
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ Then ask your coding agent:

The setup skill inspects the repository, asks which upstream release or branch to track, and shows its complete plan before pushing or rewriting branches. It then creates the patch stack, validates it, and guides the first tested promotion.

For agent development after setup, create a complete composed workspace instead of editing a raw lane:

```bash
npx patchlane workspace create --lane patch/product
# work and test in the printed directory
npx patchlane workspace status --json
npx patchlane workspace land --dry-run
```

Prefer to configure it yourself? Follow the [manual setup guide](docs/manual-setup.md). Already using an earlier Patchlane version? Use the [migration guide](docs/migrations.md).

## How It Works
Expand All @@ -28,13 +37,14 @@ Prefer to configure it yourself? Follow the [manual setup guide](docs/manual-set
4. Run the fork's existing CI on the generated branch.
5. Promote only the exact SHA that passed CI.

The promoted base and sync branches are generated output. Fork-owned changes belong on `patch/*` branches.
The promoted base and sync branches are generated output. Fork-owned changes belong on `patch/*` branches. For agent development, use a composed workspace so every lane, workflow, test, and local tool is visible while commits remain assignable to one lane.

## Documentation

- [Manual setup](docs/manual-setup.md)
- [Migration guide](docs/migrations.md)
- [Configuration and command reference](docs/configuration.md)
- [Composed workspaces](docs/workspaces.md)

## Development

Expand Down
16 changes: 16 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,22 @@ npx patchlane notify --event=sync-failed --recovered

The repository defaults to `GITHUB_REPOSITORY` in Actions or the GitHub `origin` remote locally. Structured context can be supplied with flags or the `PATCHLANE_STATUS`, `PATCHLANE_RUN_URL`, `UPSTREAM_SHA`, `SYNC_SHA`, `FAILED_PATCH_REF`, `FAILED_COMMIT`, `CONFLICT_PATHS`, and `APPLIED_PATCH_REFS` environment variables.

### Composed workspaces

Use a composed workspace for agent development instead of editing a raw patch branch:

```bash
npx patchlane workspace create --lane patch/product
cd ../project-patch-product
npx patchlane workspace status --json
npx patchlane workspace land --dry-run
npx patchlane workspace land # local lane only
npx patchlane workspace land --push # explicit remote write
npx patchlane workspace remove
```

`workspace create` pins the source and every configured lane in local metadata under the Git common directory. Landing requires clean, linear history, checks that all pinned lane refs are fresh, replays commits onto exactly one lane, recomposes every lane, and requires an exact tree match. Use `--config-ref <ref>` when the current branch does not contain `.patchlane.yml`, and `workspace remove --force` only when intentionally discarding unlanded work.

### Install agent skills

```bash
Expand Down
19 changes: 19 additions & 0 deletions docs/manual-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,25 @@ npx patchlane bootstrap --wait

After bootstrap, scheduled syncs and automatic promotions are active. On the first workflow-driven sync that publishes a new integration SHA, confirm that authentication succeeds, CI runs as a `push` for that SHA, and promotion updates the base branch.

## Agent development with composed workspaces

Once the configured composition is valid, agents should work from a complete workspace rather than a raw patch branch:

```bash
npx patchlane workspace create --lane patch/product
cd ../REPOSITORY-patch-product
npx patchlane workspace status --json
```

Make and test linear commits in the generated worktree. Before landing, validate the projection and exact recomposition:

```bash
npx patchlane workspace land --dry-run
npx patchlane workspace land
```

Use `--push` only with explicit approval. A stale lane, projection conflict, or round-trip mismatch leaves configured lane refs unchanged and should be resolved rather than bypassed.

## Adding product patches

Create each additional patch independently from the same selected source:
Expand Down
17 changes: 17 additions & 0 deletions docs/migrations.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,23 @@

Follow the section for the version you are adopting. Migration notes are listed newest first.

## 0.5.3

Patchlane 0.5.3 keeps the version-1 configuration schema, ordered `patchRefs`, generated workflows, and existing sync and promotion behavior compatible. It adds composed workspaces for agent development.

Run the new workflow from a configured branch:

```bash
npx patchlane@0.5.3-dev.0 agents
npx patchlane@0.5.3-dev.0 doctor
npx patchlane@0.5.3-dev.0 sync --dry-run
npx patchlane@0.5.3-dev.0 workspace create --lane patch/product
```

Agents should edit and test in the generated worktree, keep commits linear, and run `workspace land --dry-run` before landing. Existing forks may continue editing raw patch branches. No remote lane is changed unless `workspace land --push` is explicitly used. Workspace metadata is local Git-common-directory state and is not committed.

Preserve branch names, patch order, workflow schedules, authentication, and repository-specific workflow changes while upgrading generated workflow package references to the released Patchlane version. Use the normal tested sync and promotion flow to roll any configuration or workflow changes forward.

## 0.5

Patchlane 0.5 requires every version-1 `.patchlane.yml` file to define `allowedWorkflows` and updates generated workflows to authenticate with a GitHub App. Patchlane implicitly includes its generated `sync-upstream.yml` and `promote-tested-sync.yml` workflows, so list only repository-specific workflows.
Expand Down
63 changes: 63 additions & 0 deletions docs/workspaces.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Composed workspaces

Patchlane workspaces provide the complete composed fork while keeping commits assigned to one configured patch lane.

## Create a workspace

From a configured repository worktree:

```bash
npx patchlane workspace create --lane patch/product
```

Patchlane resolves the configured upstream source, fetches and pins every lane, composes them in order, and creates a disposable Git worktree at the generated path. Use `--path` or `--name` to override the destination, and `--config-ref origin/main` when the current branch does not contain `.patchlane.yml`.

The workspace records its inputs under the repository's common Git directory in `patchlane/workspaces/<id>.json`. This metadata is local state and is never committed to a lane.

## Work and inspect

Change to the path printed by `workspace create`, edit normally, commit linearly, and run the repository's normal tests. Inspect the state before editing and before landing:

```bash
npx patchlane workspace status --json
```

All configured lane refs must remain unchanged while the workspace is being developed. A workspace becomes stale when any lane moves; Patchlane does not automatically refresh or rebase it.

## Validate and land

Preview projection and exact recomposition without moving a lane:

```bash
npx patchlane workspace land --dry-run
```

For a successful preview, land locally:

```bash
npx patchlane workspace land
```

Use `--push` only when a remote write is explicitly approved:

```bash
npx patchlane workspace land --push
```

Landing replays the workspace commits onto exactly one target lane, recomposes all lanes using the recorded SHAs, and compares the composed tree with the tested workspace tree. It updates no lane when projection conflicts or the tree comparison fails. Remote pushes use `--force-with-lease` and are never performed by default.

A round-trip mismatch is intentionally diagnostic. Check whether the selected lane is wrong, a later lane overwrites the change, or the workspace contains work for more than one lane. Use separate workspaces for multi-lane changes.

## Remove

A workspace with dirty files or unlanded commits cannot be removed accidentally:

```bash
npx patchlane workspace remove
```

Use `--force` only when deliberately discarding that work. Removal deletes the registered worktree, disposable workspace branch, candidate refs, and local metadata. It does not change configured lane refs.

## Deferred capabilities

Patchlane 0.5.3 supports one target lane and linear history. Multi-lane commit assignment, lane dependency graphs, workspace refresh, ownership policies, automatic lane creation, and synthetic octopus commits remain future work.
2 changes: 1 addition & 1 deletion examples/promote-tested-sync.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
node-version: '22'

- name: Run patchlane promote
run: npx patchlane@0.5.2 promote
run: npx patchlane@0.5.3-dev.0 promote
env:
GH_TOKEN: ${{ steps.patchlane-token.outputs.token }}
EXPECTED_SYNC_SHA: ${{ github.event.workflow_run.head_sha }}
2 changes: 1 addition & 1 deletion examples/sync-upstream.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:
node-version: '22'

- name: Run patchlane sync
run: npx patchlane@0.5.2 sync
run: npx patchlane@0.5.3-dev.0 sync
env:
GH_TOKEN: ${{ steps.patchlane-token.outputs.token }}
UPSTREAM_SOURCE: ${{ inputs.source }}
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "patchlane",
"version": "0.5.2",
"version": "0.5.3-dev.0",
"description": "CLI tool for maintaining forked repositories with custom patches",
"type": "module",
"bin": {
Expand Down
4 changes: 4 additions & 0 deletions skills/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
{
"name": "patchlane-sync-patches",
"files": ["SKILL.md"]
},
{
"name": "patchlane-workspace",
"files": ["SKILL.md"]
}
]
}
12 changes: 11 additions & 1 deletion skills/patchlane-fork-setup/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ description: Set up or migrate a GitHub fork to use Patchlane upstream sync auto

Inspect the fork before changing anything. Confirm the default branch, remotes, existing workflows, fork-only commits, and existing `patch/*` branches.

Treat the promoted base branch as generated output. Keep fork-owned product changes, Patchlane configuration, agent skills, and workflows on focused patch branches.
Treat the promoted base branch as generated output. Keep fork-owned product changes, Patchlane configuration, agent skills, and workflows on focused patch branches. When an agent needs to make a change, prefer a composed workspace over editing a raw patch branch.

## Confirm the plan

Expand Down Expand Up @@ -89,6 +89,16 @@ The workflows do not exist on the default branch before the first promotion. Boo
4. Confirm the generated base is rooted at the selected source.
5. On the first workflow-driven sync that publishes a new integration SHA, confirm authentication succeeds, CI runs as a `push` for that exact SHA, and promotion moves the base branch to that SHA.

## Agent workspaces

After the fork has a valid composition, agents should create complete worktrees instead of editing a raw lane directly:

```bash
npx patchlane workspace create --lane patch/product
```

The workspace includes every configured lane, Patchlane skills, CI, tests, and local tooling. Make linear commits in the reported worktree, run the repository tests, then validate with `npx patchlane workspace land --dry-run`. The selected lane is the only landing destination; inspect round-trip mismatch diagnostics rather than assigning files heuristically. Use `workspace land --push` only after explicit approval. See `docs/workspaces.md` in the repository or the `patchlane-workspace` skill for the complete workflow.

## Finish

Summarize:
Expand Down
2 changes: 1 addition & 1 deletion skills/patchlane-fork-setup/assets/promote-tested-sync.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
node-version: '22'

- name: Run patchlane promote
run: npx patchlane@0.5.2 promote
run: npx patchlane@0.5.3-dev.0 promote
env:
GH_TOKEN: ${{ steps.patchlane-token.outputs.token }}
EXPECTED_SYNC_SHA: ${{ github.event.workflow_run.head_sha }}
2 changes: 1 addition & 1 deletion skills/patchlane-fork-setup/assets/sync-upstream.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:
node-version: '22'

- name: Run patchlane sync
run: npx patchlane@0.5.2 sync
run: npx patchlane@0.5.3-dev.0 sync
env:
GH_TOKEN: ${{ steps.patchlane-token.outputs.token }}
UPSTREAM_SOURCE: ${{ inputs.source }}
Expand Down
4 changes: 3 additions & 1 deletion skills/patchlane-sync-patches/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: Update patch branches in a Patchlane-managed fork so `npx patchlane

# Patchlane Patch Refresh

Start by reproducing the problem instead of guessing. Read `.patchlane.yml`, resolve its explicit upstream `source` and ordered `patchRefs`, and run or review `npx patchlane sync --dry-run` so the first failing patch branch is explicit without resetting the local sync branch.
Start by reproducing the problem instead of guessing. Read `.patchlane.yml`, resolve its explicit upstream `source` and ordered `patchRefs`, and run or review `npx patchlane sync --dry-run` so the first failing patch branch is explicit without resetting the local sync branch. When repairing code or behavior, prefer `npx patchlane workspace create --lane <lane>` so the complete composed fork remains visible; edit a raw lane only when the user explicitly requests it.

Use this workflow:

Expand All @@ -31,6 +31,8 @@ Watch for common failure modes:
- patches created from the wrong upstream tag or branch
- later patch branches silently depending on files introduced by an earlier patch

For repairs made in a composed workspace, run `npx patchlane workspace status --json` and `npx patchlane workspace land --dry-run` before projecting the commits. A round-trip mismatch or a stale lane means the workspace must be reviewed or recreated; do not bypass the check.

Finish by summarizing:

- which patch branch or branches changed
Expand Down
62 changes: 62 additions & 0 deletions skills/patchlane-workspace/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
name: patchlane-workspace
description: Develop Patchlane fork changes in a complete composed workspace, then project linear commits onto one selected patch lane with exact round-trip validation.
---

# Patchlane Composed Workspace

When making a change to a Patchlane fork:

1. Do not edit a raw patch branch unless the user explicitly requests it.
2. From a configured branch, run `patchlane workspace create --lane <lane>`.
3. Work only in the generated workspace.
4. Inspect existing code across all composed lanes before changing behavior.
5. Keep the workspace history linear; do not create merge commits.
6. Commit complete, reviewable changes and run the repository's normal tests.
7. Run `patchlane workspace status --json` before landing.
8. Run `patchlane workspace land --dry-run` and review any conflict or round-trip mismatch.
9. Use an existing configured lane that matches the requested change; do not invent a lane silently.
10. Obtain approval before running `patchlane workspace land --push`.

A workspace includes the complete composed fork: upstream code, every configured patch lane, Patchlane workflows and skills, tests, CI configuration, and development tooling. The selected lane is the only lane that receives commits during landing. Patchlane replays the workspace commits onto that lane, recomposes every lane, and requires the resulting tree to match the tested workspace tree exactly.

## Create

From the repository worktree containing `.patchlane.yml`:

```bash
patchlane workspace create --lane patch/product
```

Use `--config-ref origin/main` when the current branch does not contain `.patchlane.yml`. Use `--path` or `--name` only when a stable custom worktree location or identifier is needed. Change directory to the reported path before editing.

## Land

Before landing:

```bash
patchlane workspace status --json
patchlane workspace land --dry-run
```

Fix dirty files, merge commits, stale lane refs, projection conflicts, and round-trip mismatches rather than bypassing validation. A mismatch commonly means the selected lane is wrong, a later lane overwrites the change, or the workspace contains changes for multiple lanes. Split those changes into separate workspaces when appropriate.

Land locally with:

```bash
patchlane workspace land
```

Remote writes are never implicit. After reviewing the dry run and receiving approval, use:

```bash
patchlane workspace land --push
```

Keep the workspace until the landed lane has been reviewed or upstreamed. Remove it only after confirming there are no unlanded changes:

```bash
patchlane workspace remove
```

Use `workspace remove --force` only when intentionally discarding dirty or unlanded work.
Loading