feat(dev): lab — parked-work view [worktrees 3/3] #136
Labels
No labels
bug
enhancement
in-progress
needs-info
needs-triage
p0
ready-for-agent
ready-for-human
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Cloonar/nixos#136
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Parent
Cloonar/nixos#133 (full settled design).
What to build
A per-project Parked view so you can see and clean up parked worktrees/branches.
<details>"Parked" strip on each project card (same idiom as the ⋯ menu), collapsed by default showing a cheap count (git for-each-ref refs/heads/lab refs/heads/afk+git worktree list). Keep it off the ~4s fragment poll.lab/andafk/, tagged by kind.afk/<N>deletes its claim branch → the issue becomes claimable again (a manual requeue; ADR-0013).Mobile-first (single column, ~44px tap targets). Inline JS per ADR-0004 — verify with the ephemeral jsdom approach (no committed harness).
Acceptance criteria
lab/andafk/parked entries with dirty/clean, ahead, age, PR badge, and worktree path.Blocked by
Cloonar/nixos#134
Agent Brief
Category: enhancement
Summary: Add the per-project Parked view (worktrees slice 3/3): a collapsible strip on each project card listing parked
lab/andafk/branches/worktrees, with a per-entry Discard.Current behavior:
ADR-0017 slices 1–2 landed: every instance runs in its own worktree off
origin/<default>, and one guarded-teardown rule keeps dirty/unmerged work while GC-ing clean/merged worktrees and branches. So dirty or clean-but-unmergedlab/<label>andafk/<N>branches/worktrees survive teardown ("parked") — a failed AFK run keeps itsafk/<N>claim branch (ADR-0013), a dirty manual Stop keeps its worktree — but there is no UI to see or clean up that parked work. The reconciliation code already computes the exact parked set: managed (lab/+afk/) branches and worktrees minus those a live session owns (gatherRefs/ownedBranches).Desired behavior:
Each project card gains a collapsible Parked strip (the native
<details>/<summary>idiom the ⋯ menu uses — mobile-first, ~44px targets):for-each-refoverlab/+afk/plusworktree list) — no network. Rendered only when count > 0. Cheap enough to live on the normal snapshot/poll path./fragmentpoll, so the expensive work never runs on the ~4s poll. Each entry: branch name; kind (manuallab/vsafk/<N>); dirty ● / clean ○ (when it has a worktree); commits ahead oforigin/<default>; age; best-effort PR badge; unpushed warning; copyable worktree path (when one exists).data-confirmidiom. Discard is unguarded — force-removes the worktree (if any) and force-deletes the branch regardless of dirty/merged state — so it must NOT route through the guarded teardown. The entry surfaces ahead/unpushed state so the user sees what they're nuking. No Resume.afk/<N>entry deletes its claim branch, so the issue becomes claimable again (manual requeue; ADR-0013).Settled design decisions (from triage grilling — do not re-litigate):
#liverecurses into every node, so a client-injected lazy body is wiped on the next poll. Extend the morph's existing "client-owned" concept from attributes (value/checked/selected/open) to subtrees: a node markeddata-statichas its own attributes patched but its children left untouched. The parked body carriesdata-static; fetched once on expand, re-fetched on each re-open. Chosen over re-fetching the body every poll.Tracker.ListPulls(match branch against PR heads client-side, as the reaper does). It's ateanetwork call ⇒ lazy endpoint only, never the snapshot/count. Never-pushedlab/branches never match (no badge) — correct.gatherRefs/ownedBranches): parked = managed branches/worktrees minus live-owned. Don't re-derive independently.Key interfaces:
Gitseam — add: commits-ahead-of-base (rev-list --count origin/<default>..<branch>), last-commit age, unpushed count (rev-list --count origin/<branch>..<branch>; for a never-pushedlab/branch this equals ahead). ReuseBranches,Worktrees,WorktreeDirty,RemoveWorktree(force),DeleteBranch(-D).Tracker.ListPulls(dir)— reused unchanged for the PR badge.gatherRefs→ managed worktrees, branch→worktree index, owned set) — reused to enumerate the parked set.teardownGuarded/decideTeardown) — explicitly bypassed by Discard.#livemorph (morphChildren/patchNode) — gains thedata-staticclient-owned-subtree rule./fragment; new Discard route (POST) with the branch passed as a form field (branch names contain/).Acceptance criteria:
/fragmentpoll) listing bothlab/andafk/entries with dirty/clean (when worktree present), commits-ahead, age, best-effort PR badge, unpushed warning, copyable worktree path.data-staticrule), verified via the ephemeral jsdom harness (ADR-0004 — no committed JS).afk/<N>entry removes the claim branch so the issue re-enters the claimable set.data-staticon the parked body.go test ./...,go vet ./...,go build ./...pass locally (pre-commit is eval-only — it does not build/run Go)..menu/.btnidioms.default.nixversion date string bumped.Out of scope: