This commit is contained in:
Ian Gulliver
2026-10-14 21:01:38 -07:00
parent 9e741ede32
commit b2bd894677
20 changed files with 585 additions and 343 deletions
+4 -2
View File
@@ -19,9 +19,11 @@ Schema changes are the `migrations` slice in `internal/store/store.go`: named en
## Closing a task
A task ends `merged` or `discarded`; either way its sessions are stopped, its worktree and branch are removed, its `open` inbox items become `dismissed` (resolved by whoever closed it), and its record and events remain. `GET /api/tasks/{id}/unmerged` reports what would be lost or merged: commits on the branch that aren't on the default branch, and files, lines and uncommitted paths that differ from the merge base. The UI shows it in the confirm dialog of both buttons.
A task ends `merged` or `discarded`; either way its sessions are stopped, its worktree and branch are removed, its `open` inbox items become `dismissed` (resolved by whoever closed it), and its record and events remain. `GET /api/tasks/{id}/unmerged` reports what would be lost or merged: commits on the branch that aren't on the default branch, and files, lines and uncommitted paths that differ from the merge base. The UI shows it in the confirm dialog of both buttons, which are disabled while the task's session is `running` or `queued`.
`POST /api/tasks/{id}/merge` squashes the worktree as it stands, uncommitted and untracked files included (captured through a temporary index, so the worktree isn't touched), onto the default branch with `git merge-tree --merge-base`, makes one commit with `git commit-tree` authored and committed by the merging user, and runs `git merge --ff-only` in the project's checkout, which must have the default branch checked out. The commit message is the task title. Nothing is pushed. It is refused (409) while a session is `running` or `queued`, on merge conflicts (the message lists the files; the task stays active), and if the default branch moved between the merge and the fast-forward. When the merge changes nothing, no commit is made. `POST /api/tasks/{id}/discard` removes everything without merging.
`POST /api/tasks/{id}/merge-in` (the transcript's **Merge main in** button, labelled with the default branch) brings the default branch into the task branch through the agent: it sends `mergeInPrompt` (`internal/agents/mergein.go`) as a `byre` message to the task's session, or starts a session with it when the task has none. The prompt has the agent run `git merge --no-ff --no-commit`, resolve conflicts, regenerate generated files rather than hand-merging them, check the build and tests, and leave the merge uncommitted; byre's end-of-turn commit concludes it as a merge commit. It is refused (409) while a session is `running` or `queued`.
`POST /api/tasks/{id}/merge` starts the same turn and records, in memory, that the task is to be merged by the requesting user, who must have a git identity (400 otherwise). When that turn ends normally (not interrupted, not an error), byre squashes the worktree, now containing the default branch, onto it with `git merge-tree --merge-base`, makes one commit with `git commit-tree` authored and committed by the merging user, runs `git merge --ff-only` in the project's checkout (which must have the default branch checked out), then closes the task. The commit message is the task title. Nothing is pushed. When the merge changes nothing, no commit is made. If the squash fails, for example because the default branch moved again during the turn, byre files an error in the inbox and the task stays active. An interrupted or failed turn, or a byre restart during it, leaves the task active without squashing. `POST /api/tasks/{id}/discard` removes everything without merging.
## Running as a service