docs(lanes): document per-feature state and archive (B)

This commit is contained in:
2026-08-04 15:06:05 +07:00
parent 3a83e849cf
commit 917f0794d5
5 changed files with 129 additions and 2 deletions
+75
View File
@@ -397,6 +397,81 @@ resolved path is confined to the lane's log directory after `realpath`, so a
name from the request can never escape it; anything else is `404 ENOLOG`. A lane
with no slot returns `{"available": false}`.
#### Lane features
```http
GET /api/lanes/:id/features
```
List every feature this lane has activated, archived or live:
```json
{
"features": [
{ "slug": "auth-redesign", "active": true, "title": "Auth redesign (v2)", "stage": "implement", "status": "running", "created_at": 1722702012 },
{ "slug": "migration", "active": false, "title": null, "stage": "done", "status": "idle", "created_at": 1722700000 },
]
}
```
Each feature carries a canonicalized `slug` (drops leading `feat/`, `/` → `-`, preserves case, keeps `[A-Za-z0-9._-]` only — **not the same rule as `worktree.js:slugify`**, which lowercases). `active` is `true` for the currently live feature. `title` is the display name (human-chosen via `ccam feature activate --title`; omitted/`null` if never set or identical to slug). `stage`, `status`, `notes` reflect the **saved** state when this feature was last archived; `active:true` shows the **live** lane's current stage instead.
```http
GET /api/lanes/:id/features/:slug
```
Show one feature's saved pipeline:
```json
{
"slug": "auth-redesign",
"active": true,
"title": "Auth redesign (v2)",
"stage": "implement",
"status": "running",
"notes": "Testing with OAuth...",
"created_at": 1722702012
}
```
Works on both archived and active features. If the slug has never been activated, returns `404 ENOFEAT`.
```http
POST /api/lanes/:id/features/activate
{ "slug": "auth-redesign", "title": "Auth redesign (v2)" }
```
Activate a feature by slug. Request body:
- `slug` (required, string) — the canonicalized slug (or raw slug; the route canonicalizes it before lookup)
- `title` (optional, string) — human-friendly name to save with this feature
Response:
```json
{
"slug": "auth-redesign",
"active": true,
"title": "Auth redesign (v2)",
"stage": "implement",
"status": "running",
"created_at": 1722702012,
"archivedPrevious": { "slug": "migration", "stage": "done" }
}
```
Behavior:
- If the target slug has been activated before, restores its saved stage/status/notes onto the live lane
- If the slug is new, creates a fresh feature row with empty stage/status/notes
- If a different feature is currently active, archives it first (copies live stage/status/notes to its row) — echoed in `archivedPrevious`
- Returns **200** on success; **409 ESTALE** if another request changed the lane between read and write
Status codes:
- **200** — feature activated
- **409** — the lane's stage changed concurrently (rare with single-session lanes)
- **400** — missing/invalid request body
### Locks
Cross-lane named locks (`server/lib/named-lock.js`) — the OTHER axis from a