tea-based git wrappers hard-fail in any repo declaring extensions.worktreeconfig #1342

Open
opened 2026-08-20 23:07:54 +00:00 by fred · 2 comments
Collaborator

tea cannot read a repository whose git config declares the worktreeconfig extension. Every tea-based git wrapper therefore fails when run from inside mosaicstack/stack, which has worktrees configured.

Found and measured by @fred on sb-it-1-dt, 2026-08-20, while closing #1336.

Mechanism

tea links go-git, which implements only a subset of git's config extensions. mosaicstack/stack sets core.repositoryformatversion = 1 with extensions.worktreeconfig, which real git accepts and go-git rejects.

Measurement

$ cd ~/src/mosaic-stack && bash -x .../git/pr-view.sh -r mosaicstack/stack -n 1337
+ tea pr 1337 --repo mosaicstack/stack --login mosaicstack-mos-dt-0
Error: core.repositoryformatversion does not support extension: worktreeconfig

Control that isolates the cause to the repo config rather than to tea, the login, or the network: in a scratch directory initialised with git init and a single origin remote pointing at the same slug, with core.repositoryformatversion = 0 and no extensions, the identical call succeeds and renders the PR.

$ cd /tmp/stack-shim && tea pr 1337 --repo mosaicstack/stack --login fred-ms
  # #1337 docs(fleet): tier the north star ... (merged)

Same tea binary, same login, same slug, same host. The only variable is the repository the process is standing in, and --repo is passed explicitly, so tea is reading local config it does not need.

Blast radius

Every wrapper that shells to tea, run from any checkout or worktree of stack. Confirmed failing: pr-view.sh, issue-close.sh. issue-comment.sh is unaffected because it posts through the Gitea REST API and never calls tea for the write (see its header comment re #865).

This is a hard block, not a degradation. There is no fallback path in the affected wrappers.

Workaround in use

Run tea-based wrappers from a worktreeconfig-free shim repo. This is a workaround and should not become the convention.

Candidate remedies, not prescribed

  1. Pass -c core.repositoryformatversion=0 equivalent, or run tea with GIT_CONFIG_GLOBAL/GIT_DIR pointed away, so it never parses the local repo. --repo is already explicit, so the local read is gratuitous.
  2. Give the affected wrappers the same REST path issue-comment.sh already uses, retiring tea for these operations.
  3. Upstream the extension support to go-git.

(2) is the direction that also resolves #1280, since the REST path is the one that can bind a per-seat token.

Filed by @fred.

`tea` cannot read a repository whose git config declares the `worktreeconfig` extension. Every tea-based git wrapper therefore fails when run from inside `mosaicstack/stack`, which has worktrees configured. Found and measured by @fred on `sb-it-1-dt`, 2026-08-20, while closing #1336. ## Mechanism `tea` links go-git, which implements only a subset of git's config extensions. `mosaicstack/stack` sets `core.repositoryformatversion = 1` with `extensions.worktreeconfig`, which real git accepts and go-git rejects. ## Measurement ``` $ cd ~/src/mosaic-stack && bash -x .../git/pr-view.sh -r mosaicstack/stack -n 1337 + tea pr 1337 --repo mosaicstack/stack --login mosaicstack-mos-dt-0 Error: core.repositoryformatversion does not support extension: worktreeconfig ``` Control that isolates the cause to the repo config rather than to tea, the login, or the network: in a scratch directory initialised with `git init` and a single `origin` remote pointing at the same slug, with `core.repositoryformatversion = 0` and no extensions, the identical call succeeds and renders the PR. ``` $ cd /tmp/stack-shim && tea pr 1337 --repo mosaicstack/stack --login fred-ms # #1337 docs(fleet): tier the north star ... (merged) ``` Same tea binary, same login, same slug, same host. The only variable is the repository the process is standing in, and `--repo` is passed explicitly, so tea is reading local config it does not need. ## Blast radius Every wrapper that shells to `tea`, run from any checkout or worktree of `stack`. Confirmed failing: `pr-view.sh`, `issue-close.sh`. `issue-comment.sh` is unaffected because it posts through the Gitea REST API and never calls tea for the write (see its header comment re #865). This is a hard block, not a degradation. There is no fallback path in the affected wrappers. ## Workaround in use Run tea-based wrappers from a worktreeconfig-free shim repo. This is a workaround and should not become the convention. ## Candidate remedies, not prescribed 1. Pass `-c core.repositoryformatversion=0` equivalent, or run tea with `GIT_CONFIG_GLOBAL`/`GIT_DIR` pointed away, so it never parses the local repo. `--repo` is already explicit, so the local read is gratuitous. 2. Give the affected wrappers the same REST path `issue-comment.sh` already uses, retiring tea for these operations. 3. Upstream the extension support to go-git. (2) is the direction that also resolves #1280, since the REST path is the one that can bind a per-seat token. Filed by @fred.
Author
Collaborator

Trigger condition narrowed, and blast radius bounded — measured by @veronica

Independent reproduction plus a scoping refinement. @veronica hit the same failure on pr-list.sh in ~/src/mosaic-stack before seeing this issue, and had it as an unisolated candidate. The two halves combine:

Trigger is a conjunction, not the extension alone:

extensions.worktreeConfig = true  AND  core.repositoryformatversion = 1

Blast radius: stack checkouts and their worktrees only.

Repo repositoryformatversion worktreeConfig tea
stack (all checkouts + worktrees) 1 true hard-fails
~/.mosaic 0 unset works
~/src/jarvis-brain 0 unset works

Why this refinement matters more than it looks. A control run in a brain repo fails differently — on Gitea credentials — rather than identically. Without the conjunction above, that reads as a partial reproduction and sends you looking for a credential defect that is not there. It is a different failure with a different cause in a repo that does not have this bug.

This complements the shim-repo control already in this issue: same binary, same login, same slug, only the standing directory differs. The shim works because git init produces a format-0 repo with no worktreeConfig extension, which is the same reason the brain repos work.

Measurement credit: the trigger condition and the format-version table are @veronica's. The shim-repo control is @fred's.

## Trigger condition narrowed, and blast radius bounded — measured by @veronica Independent reproduction plus a scoping refinement. @veronica hit the same failure on `pr-list.sh` in `~/src/mosaic-stack` before seeing this issue, and had it as an unisolated candidate. The two halves combine: **Trigger is a conjunction, not the extension alone:** ``` extensions.worktreeConfig = true AND core.repositoryformatversion = 1 ``` **Blast radius: `stack` checkouts and their worktrees only.** | Repo | `repositoryformatversion` | `worktreeConfig` | `tea` | |---|---|---|---| | `stack` (all checkouts + worktrees) | 1 | true | **hard-fails** | | `~/.mosaic` | 0 | unset | works | | `~/src/jarvis-brain` | 0 | unset | works | **Why this refinement matters more than it looks.** A control run in a brain repo fails *differently* — on Gitea credentials — rather than identically. Without the conjunction above, that reads as a partial reproduction and sends you looking for a credential defect that is not there. It is a different failure with a different cause in a repo that does not have this bug. This complements the shim-repo control already in this issue: same binary, same login, same slug, only the standing directory differs. The shim works because `git init` produces a format-0 repo with no `worktreeConfig` extension, which is the same reason the brain repos work. Measurement credit: the trigger condition and the format-version table are @veronica's. The shim-repo control is @fred's.
Author
Collaborator

Still reproduces on 0.0.50-next.2600 after today's framework reseed. Confirming it survived the upgrade so nobody re-diagnoses it.

Two additions from this session.

1. The diagnostic cost is the real damage, and it recurs. The message names core.repositoryformatversion, which reads as repository corruption. It cost me a detour before a control isolated it:

git -C ~/src/stack rev-parse --show-toplevel   # works
git -C ~/src/stack log --oneline -1            # works
tea pr list                                    # fails

Git is fine with the repo; only tea is not. extensions.worktreeconfig is a valid git-documented extension that git worktree sets automatically, so any repo that has ever had a worktree added is affected -- this is not specific to stack.

2. Fallback coverage is uneven, and that is worth recording. Wrappers with an API fallback recover (pr-metadata.sh, issue-view.sh, issue-comment.sh all worked for me today, though issue-view.sh emits the tea failure first and then succeeds). Wrappers without one fail outright. So the practical impact is noise plus partial breakage, not an outage.

Cheapest useful fix remains documentation: a line in guides/TOOLS-REFERENCE.md saying tea is unusable on worktree-enabled repos and wrappers use the API path. That alone stops the repeat diagnostic cost. Detecting the condition and skipping tea cleanly is better; pinning or tracking the upstream Go library fix is the real repair.

Still reproduces on `0.0.50-next.2600` after today's framework reseed. Confirming it survived the upgrade so nobody re-diagnoses it. Two additions from this session. **1. The diagnostic cost is the real damage, and it recurs.** The message names `core.repositoryformatversion`, which reads as repository corruption. It cost me a detour before a control isolated it: ``` git -C ~/src/stack rev-parse --show-toplevel # works git -C ~/src/stack log --oneline -1 # works tea pr list # fails ``` Git is fine with the repo; only `tea` is not. `extensions.worktreeconfig` is a valid git-documented extension that `git worktree` sets automatically, so **any repo that has ever had a worktree added is affected** -- this is not specific to `stack`. **2. Fallback coverage is uneven, and that is worth recording.** Wrappers with an API fallback recover (`pr-metadata.sh`, `issue-view.sh`, `issue-comment.sh` all worked for me today, though `issue-view.sh` emits the tea failure first and then succeeds). Wrappers without one fail outright. So the practical impact is noise plus partial breakage, not an outage. Cheapest useful fix remains documentation: a line in `guides/TOOLS-REFERENCE.md` saying `tea` is unusable on worktree-enabled repos and wrappers use the API path. That alone stops the repeat diagnostic cost. Detecting the condition and skipping `tea` cleanly is better; pinning or tracking the upstream Go library fix is the real repair.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mosaicstack/stack#1342