Guider

Worktrees med nav-pilot og cplt

Med git worktree har du flere brancher sjekket ut samtidig, hver i sin mappe. Slik bruker du det i sandkassen.

brew update
brew upgrade navikt/tap/nav-pilot navikt/tap/cplt
copilot update    # Copilot CLI
opencode upgrade  # hvis du bruker opencode

Hvorfor worktrees

Et worktree er en ekstra utsjekking av samme repo, på en annen branch og i en annen mappe. Agenten kan jobbe på én branch mens du jobber på en annen, og flere subagenter kan jobbe parallelt uten å skrive over hverandres filer. Objekter, refs og konfig ligger i én felles git-mappe, den git rev-parse --git-common-dir viser. Hvert worktree har i stedet for en .git-mappe en .git-fil som peker til sin egen admin-mappe under <felles>/worktrees/<navn>.

Det er tre måter å bruke worktrees på med nav-pilot og cplt:

  • Du starter nav-pilot i et worktree du har laget selv.
  • Agenten lager worktrees til subagenter mens den jobber.
  • Du jobber i et worktree fra et bare repo, eller med .git et annet sted.

Den første og den tredje virker uten oppsett. Den andre må du slå på, og den virker bare på macOS.

Starte i et worktree

Lag worktreet utenfor sandkassen, og start nav-pilot i det:

cd ~/src/min-app
git worktree add ../min-app-ny-branch -b ny-branch
cd ../min-app-ny-branch
nav-pilot

nav-pilot gir cplt worktreet som prosjektkatalog. cplt finner den felles git-mappa, her .git-mappa i hovedutsjekkingen, og gir agenten tilgang til den, så git status, git commit og resten virker. Agenten kan skrive i worktreet, ikke i hovedutsjekkingen.

Den felles git-mappa bør ligge under hjemmekatalogen din. Ligger den et annet sted, for eksempel under /Users/Shared, gir cplt ikke tilgang, og git feiler i sandkassen. cplt sier fra om det ved oppstart og i cplt doctor, se Feilsøking.

Godkjenningen av repoets .cplt.toml gjelder hele repoet. Har du godkjent den i hovedutsjekkingen, spør ikke cplt på nytt i worktreet, med mindre branchen har endret forslaget.

Worktrees til subagenter

Som standard kan agenten bare skrive i prosjektkatalogen, så den har ikke noe sted å lage nye worktrees. Slå på en egen worktree-mappe for repoet:

cplt config set sandbox.allow_git_worktrees true           # alle repoer
cplt config set --local sandbox.allow_git_worktrees true   # bare denne utsjekkingen

Neste gang du starter nav-pilot, lager cplt mappa ~/.cplt-worktrees/<id>, viser den ved oppstart og setter miljøvariabelen CPLT_WORKTREE_ROOT. Alle worktrees av samme repo får samme mappe, en annen klone får sin egen.

Du trenger ikke be agenten om å bruke mappa. cplt forteller den om mappa i starten av økten, sammen med kommandoene:

cplt worktree add <navn> <ref>                         # sjekker ut <ref> med detached HEAD og skriver ut stien
git -C "$CPLT_WORKTREE_ROOT/<navn>" switch -c <branch> # lag en branch hvis subagenten skal committe på en branch

På macOS er .cplt.toml, .github/hooks, .agents/plugins, .gitmodules og de andre beskyttede stiene skrivebeskyttet også inne i worktree-mappa. En vanlig git worktree add eller git worktree remove inne i sandkassen feiler derfor så snart repoet har en slik fil. cplt worktree add <navn> <ref> ber cplt-prosessen utenfor sandkassen om å opprette worktreet i ~/.cplt-worktrees/<id>/<navn> med detached HEAD.

Worktrees og brancher blir liggende etter økten. Fjern dem utenfor cplt når du er ferdig:

git worktree list
git worktree remove ~/.cplt-worktrees/<id>/<navn>
git branch -d <branch>

Innstillingen kan bare settes i din egen cplt-konfig. Et repo kan ikke slå den på for deg med .cplt.toml.

Bare repo og .git et annet sted

Noen holder repoet som et bare repo, uten arbeidskatalog, med hver branch som et worktree ved siden av. Andre har git-mappa et annet sted enn koden. Begge virker som når du starter i et worktree. cplt følger .git-fila til den felles git-mappa og gir agenten tilgang dit.

git clone --bare git@github.com:navikt/min-app.git ~/src/min-app.git
git -C ~/src/min-app.git worktree add ~/src/min-app-main main
cd ~/src/min-app-main
nav-pilot

cplt godtar bare oppsett slik git selv lager dem. En .git-fil som er endret for hånd til å peke på et annet repo, gir ingen tilgang.

Bruker du worktrees til subagenter i tillegg, kan ikke repoet bruke worktree.useRelativePaths. cplt nekter å starte når et worktree i repoet har relative stier, også utenfor worktree-mappa. Slå av innstillingen og skriv om stiene, utenfor cplt, for hvert worktree som har dem:

git config --unset worktree.useRelativePaths
git worktree repair --no-relative-paths ~/src/min-app-main

Begrensninger og sikkerhet

  • Ingen isolasjon mellom subagenter. Alle worktrees i en økt deler samme tilgang. En subagent kan skrive i de andres worktrees og i utsjekkingen du startet fra.
  • Bare macOS. På Linux nekter cplt config set å slå på worktrees til subagenter, fordi Landlock ikke kan stenge enkeltfiler inne i et worktree som lages etter oppstart. De to andre måtene virker på Linux også.
  • Slik lager cplt et worktree for agenten. Når agenten kjører cplt worktree add <navn> <ref>, slår cplt utenfor sandkassen opp <ref> lokalt uten nettverk, hooks eller filterdrivere, sjekker ut filene i en privat midlertidig mappe og kontrollerer at alle sporede beskyttede stier, som .cplt.toml, .github/hooks, .agents/plugins og .gitmodules, har nøyaktig samme innhold og kjøretillatelser som oppstarts-HEAD, uten symlenker som peker ut eller nøstede .git-mapper. Først når sjekken passerer, flyttes worktreet atomisk på plass i ~/.cplt-worktrees/<id>/<navn> med detached HEAD. Agenten kan derfor ikke sjekke ut en eldre eller nyere commit som endrer beskyttede hooks eller konfigurasjonsfiler.
  • Samme beskyttelse som i prosjektet. Hooks og config i den felles git-mappa, config.worktree for hvert worktree, .cplt.toml, .github/hooks og de andre beskyttede filene er stengt for skriving i hvert worktree.
  • cplt sjekker mappa ved hver oppstart og ved slutten av økten. Finner den en .git eller et bare repo der git ikke selv ville lagt det, en mappe dypere enn 64 nivåer, eller en symlenke som peker ut av worktreet, nekter den å starte og sier hvilke mapper du ikke skal kjøre git i.
  • Endringsrapporten dekker ikke worktrees. Rapporten cplt skriver etter økten, viser bare endringer i prosjektkatalogen. Se over det agenten har gjort i worktreene, før du kjører noe derfra utenfor sandkassen.

Detaljene står på engelsk i konfigurasjonsdokumentasjonen til cplt og i SECURITY.md.

Feilsøking

git feiler i sandkassen, men virker utenfor

Den felles git-mappa fra git rev-parse --git-common-dir ligger utenfor hjemmekatalogen, eller stien inneholder anførselstegn, parentes, semikolon eller omvendt skråstrek. cplt sier fra om begge deler ved oppstart, med Not granting the shared git directory. Flytt repoet inn under hjemmekatalogen, eller gi mappa et navn uten de tegnene. Ligger mappa utenfor hjemmekatalogen, kan du også gi tilgang til den:

cplt config set --local allow.write /Users/Shared/min-app/.git

cplt nekter å starte fordi et worktree er halvferdig

Worktrees må fjernes utenfor cplt med git worktree remove ~/.cplt-worktrees/<id>/<navn>. Feiler oppstarten med the worktree links of this repository do not match what git writes, har noen kjørt git worktree remove eller vanlig git worktree add inne i sandkassen, som feiler på beskyttede filer og etterlater et halvferdig worktree. Slett mappa feilmeldingen lister opp, og rydd opp utenfor cplt:

rm -rf ~/.cplt-worktrees/<id>/<navn>
git worktree prune

cplt sier at worktree-mappa har for mange mapper

Sjekken går gjennom høyst 100 000 mapper. Noen få store JavaScript-worktrees kan være nok. Slett worktrees du er ferdig med, eller hev grensen:

cplt config set sandbox.worktree_walk_max_dirs 300000

Go-bygg feiler med exit status 128 i et worktree

Go leter oppover etter en .git-mappe for å stemple bygget med versjonsinformasjon. I et worktree er .git en fil, så Go går forbi den og kan finne en annen .git-mappe høyere opp, for eksempel i hjemmekatalogen din. Den har ikke agenten tilgang til, og bygget feiler med error obtaining VCS status: exit status 128. Slå av stemplingen:

go build -buildvcs=false

Bygger du gjennom mise, kan du sette det for hele repoet i mise.toml:

[env]
GOFLAGS = "-buildvcs=false"

GOFLAGS fra skallet ditt slipper også inn i sandkassen.

Andre feilmeldinger fra sandkassen står i Feil i sandkassen.