git: a creation gate that never writes history, a git tab with Paperclip's worktree scan, and a warning line in every pane

This commit is contained in:
Sam
2026-11-12 20:38:44 +11:00
parent f7b77f370f
commit c419de5b48
18 changed files with 2223 additions and 82 deletions

View File

@@ -72,36 +72,100 @@ Inside a pane, `R` in `Repair>repair` rebuilds everything; `B` only adds what is
A new project gets a worktree policy: Paperclip makes a branch and a separate directory per task,
so two tasks never change the same files, and there is a diff to review and a merge to approve.
That needs a repository **with at least one commit**. `office` checks, and when the folder is not
one it explains what is lost and asks before touching anything:
That needs a repository **with at least one commit**, because a worktree is a checkout of a commit:
anything not committed is invisible to the agent. When the folder cannot do that yet, `office`
asks, and never writes history:
```
/tmp/officetest is not a git repository, so each task cannot have its own branch and worktree.
without them, two tasks can change the same files at once, and there
/tmp/gate1 is not a git repository, so a task cannot have its own branch and worktree.
without one, two tasks can change the same files at once, and there
is no diff to review and nothing to merge.
make it a repository now? This runs: git init -b main, git add -A,
and one commit of EVERY file in the folder, including anything you
have not noticed. Add a .gitignore first if that is not what you want.
type yes to do it:
Y make the repository, write .gitignore with .paperclip/,
stage everything, and stop. You commit it in lazygit, then
run this command again to create the project with worktrees.
N create the project in place instead: no branches, no diff,
nothing to merge.
Y or N:
```
Three answers, in order of preference:
Answer **Y** and it stops before committing, on purpose:
1. **Answer the question.** It only appears at a terminal, so nothing is created by a script by
accident.
2. **`--git-init`** does the same without asking, for a script.
3. **Do it yourself**, which is what a machine without a terminal is told to do, with the exact
commands.
```
made a repository on branch main
wrote .gitignore, ignoring .paperclip/
If you say no, or there is no terminal and no flag, the project is still created — as
`local_path`, in place. A task then edits the folder directly: no branch, no diff, nothing to
merge. That is honest for a folder of notes and wrong for code.
Everything is staged and nothing is committed. Check what git is about
to take, and commit it:
The base branch is read from the folder (`git symbolic-ref`), not assumed to be `main`, so a
repository on `master` works.
cd /tmp/gate1 && lazygit
space stage or unstage a file i ignore a file or folder
c commit ? every key
## A folder on a machine that does not serve Paperclip
Then run this command again. It will create the project with worktrees.
the project was not created: commit the staged files, then run this again.
```
Two decisions are kept out of the tool's hands, because both belong to the person:
- **what gets committed**, because what you commit is what the agent can see. `lazygit`'s files
panel stages and unstages with `space`, and **`i` adds a file or folder to `.gitignore`** — for a
pattern, `e` opens the file. The first commit is unpushed, so `A` amends it if you change your
mind.
- **whether there is a commit at all**. No commit means no worktrees, and `N` creates the project
in place (`local_path`) instead: a task edits the folder directly, with no diff and nothing to
merge. A project's policy is fixed when it is created, so that choice cannot be revisited
without making the project again.
`--commit-all` does the whole thing in one step for anyone who does not want to look. With no
terminal and no flag, `office` changes nothing and prints the three commands instead.
**`.paperclip/` is written into `.gitignore` on every path and is not a preference.** Paperclip
puts its worktrees inside the project folder; a commit that took them would put checkouts of the
repository inside the repository.
The base branch is read from the folder (`git symbolic-ref`), not assumed to be `main`, and it is
set in both places Paperclip keeps it: the policy's `baseRef` and the workspace's `defaultRef`.
## Seeing the state: the `git` tab, and the banner
`Project>project` → `(` `)` → **git** reads the folder and Paperclip together:
```
THIS FOLDER
repository yes · branch main
commits 3
remote none — not needed for worktrees
changed 0 staged · 0 unstaged · 2 untracked
.gitignore .paperclip/
worktrees isolated_workspace · git_worktree · base main
WORKTREES, AS PAPERCLIP SEES THEM
AUD-172-add-a-status-md-with-one-line clean · 1 behind · merged into base
This workspace is 1 commit behind main.
```
Two halves, deliberately: the top is git run in this folder, which Paperclip never checks; the
bottom is Paperclip's own scan of each task's worktree
(`GET /api/execution-workspaces/{id}/close-readiness`), which already knows the branch, what is
dirty, how far behind the base it is, and whether it is merged. Nothing is recomputed.
`t` opens `lazygit` in the project folder, wherever the git tab says something needs doing.
While the folder cannot hold a worktree, **every pane** carries one line at the top:
```
commit will swallow the worktrees — .paperclip/ is not in .gitignore · Project>project → git
```
It takes the page title's line and leaves the panels and the key hints alone. It is read once when
the pane starts, so fixing the folder and pressing `R` (which rebuilds every pane) is what clears
it.
## A folder on a machine that does not serve Paperclip## A folder on a machine that does not serve Paperclip
Panes run where the folder is. **Agents run where Paperclip is**, because Paperclip starts them
itself. When those are different machines the panes read the folder correctly and the agents