feat(lanes): let Add Lane choose the pipeline template

Creation is the only point the UI could ever set a lane's template, and it
never offered the choice — so every lane added from "+ Add lane" was born
on `default` and rendered an 8-node map for a 16-node workflow, with no
screen able to change it afterwards. That is the defect that made the
ship-feature template unreachable from the browser.

The modal now shows a *Pipeline template* select fed by
`GET /api/lanes/pipelines`, labelled with each template's node count so the
consequence of the choice is visible. A failed fetch degrades to a `default`
option rather than blocking lane creation.

`pipeline` was already accepted by `POST /api/lanes` but silently dropped by
`/ensure` and `/worktree`, which build their own createLane payloads; both
now pass it through, and both map `EBADPIPELINE` to 400 like `EBADCWD`.
This commit is contained in:
2026-08-07 09:44:48 +07:00
parent 67edda77eb
commit 8fcef5a10b
8 changed files with 143 additions and 7 deletions
+6 -1
View File
@@ -135,9 +135,14 @@ POST /api/lanes/ensure
```
```json
{ "cwd": "/absolute/path/to/work", "title": "App package" }
{ "cwd": "/absolute/path/to/work", "title": "App package", "pipeline": "ship-feature" }
```
`pipeline` is optional and, like `title`, applies **only when a lane is
actually created** — an existing lane is returned untouched. Omitted, the lane
gets `default`. `POST /api/lanes/worktree` and `POST /api/lanes` take the same
optional field. An id no template defines returns `400 EBADPIPELINE`.
Idempotent lookup by working directory — the Workspace page opens on a `cwd`,
not on a lane id. Returns the lane whose own `cwd` is that path, or the longest
path-boundary parent of it, as `{ "lane": {...}, "created": false }` with `200`.