gitea forge preset is broken against the real tea CLI (0.14.2)
Summary
The gitea provider preset (packages/codev/scripts/forge/gitea/*.sh, added for #589) does
not work against the actual tea CLI. Most read concepts either error out or emit a JSON
shape that doesn't match forge-contracts.ts. The scripts appear to have been written against
the Gitea REST API JSON shape, but they invoke the tea CLI, whose --output json
emits a different, flattened shape (and in some cases the referenced flag/field/subcommand
doesn't exist at all). This matches the in-repo note in issue-search.sh:
"tea is not available in the authoring environment (#920)" — the preset was authored blind.
Verified end-to-end with tea 0.14.2 (latest release, 2026-06-26) against a live Forgejo
instance (Forgejo is Gitea-API-compatible). Not a version-gap issue — 0.14.2 is current.
Broken concepts (verified)
| Script |
Current command |
Observed failure |
user-identity.sh |
tea whoami --output json | jq -r .login |
tea whoami has no --output json flag → Error: flag provided but not defined: -output |
pr-list.sh |
tea pulls list --fields …,description --output json |
Error: invalid field 'description' — the whole concept errors; tea pulls list exposes no description/body field |
pr-view.sh |
tea pulls view N --output json |
Returns [] / a table header, not the PR object |
issue-view.sh |
tea issues view N --output json | jq '.url = (.html_url // .url)' |
Returns a flattened single-element array (list shape) with no body/html_url/url fields |
issue-comment.sh |
tea issues comment … |
No such subcommand — tea issues has no comment; commenting lives under tea comments add |
pr-exists.sh |
… | jq 'select(.head.ref == $B and (.state=="closed" and .merged==true) …)' |
tea pulls list emits .head as a string, not {ref}, and reports merged PRs as state:"merged" (no .merged bool) → Cannot index string with string "ref" |
recently-merged.sh |
--fields …,head,description,merged + .head.ref + .merged==true |
Same string-head + invalid description field problems |
Working as-is: auth-status, issue-list, recently-closed, pr-merge, repo-archive
(the last already uses tea api).
Root cause
Two divergent JSON surfaces in tea:
tea <entity> list --output json — a flattened, --fields-limited view
(head/base are strings, index is a string, no nested objects, no body/description
for pulls, state is synthesized to "merged").
tea api <endpoint> — a raw passthrough to the Gitea REST API, returning the exact
documented API shape.
codev's jq normalizers and forge-contracts.ts are written for (2) but the scripts call (1).
Recommended fix: route read concepts through tea api
tea api returns precisely the shape the existing jq already assumes, so the fix is mostly a
data-source swap with the jq kept intact. Verified against live Forgejo:
# user-identity
tea api user | jq -r '.login' # => the login, matches gh api user
# pr-list / pr-exists (repo from git remote, e.g. $CODEV_REPO)
tea api "repos/$CODEV_REPO/pulls?state=all&limit=200" \
| jq '.[0] | {number, state, merged, headRef: .head.ref, body, author: .user.login}'
# => number:int, state:"closed", merged:true, head.ref, body, user.login — all present
# pr-view
tea api "repos/$CODEV_REPO/pulls/$CODEV_PR_NUMBER" # full PR object
# issue-view
tea api "repos/$CODEV_REPO/issues/$CODEV_ISSUE_ID" # full issue object incl. body
# issue-comment
tea comments add "$CODEV_ISSUE_ID" "$CODEV_COMMENT_BODY"
This is minimal-diff (keep the jq contracts), and robust across tea versions since it avoids
the CLI's --fields/flattening quirks entirely.
One inherent caveat (not a codev bug)
For a merged PR whose source branch was deleted, Gitea's API returns
.head.ref == "refs/pull/N/head" instead of the original branch name — so a branch-name match
in pr-exists won't hit a merged+deleted branch. That's a Gitea behavior; worth a comment in
the script but doesn't affect the "does an open/merged PR exist for the branch I'm about to
push" use case.
Reproducibility (not environment-specific)
Verified two independent ways, neither dependent on the reporting instance:
1. The failures are defined in the tea binary, before any server contact:
$ tea whoami --help # OPTIONS: only --help. No --output/json exists, any server.
$ tea issues --help # subcommands: list, create, edit, close — NO 'comment'.
2. Canonical upstream Gitea (gitea.com, reference implementation) via plain curl — no tea:
$ curl -s https://gitea.com/api/v1/repos/gitea/tea/pulls?state=all&limit=1 \
| jq '.[0] | {head_type: (.head|type), head_ref: .head.ref, user_login: .user.login, merged}'
{ "head_type": "object", "head_ref": "renovate/go-dependencies",
"user_login": "renovate-bot", "merged": false }
The REST shape codev's jq assumes (.head.ref, .user.login, .merged, object responses) is
correct and canonical — the scripts just read from the wrong source (tea <entity> list, which
flattens/limits it) instead of tea api. A self-hosted Forgejo returns byte-identical shape, so
this is not a fork divergence; it reproduces against gitea.com itself.
Environment
tea 0.14.2 (latest release, 2026-06-26; brew install tea)
- codev
@cluesmith/codev 3.2.2
- Confirmed against both a self-hosted Forgejo and public
gitea.com (canonical Gitea)
- Note: the gitea
.sh scripts are not exercised by CI (forge.test.ts uses mock scripts; per
the in-repo #920 note tea isn't available in the authoring/CI env), so these were validated
manually against live instances.
- Happy to open a PR implementing the
tea api approach above if you're on board.
giteaforge preset is broken against the realteaCLI (0.14.2)Summary
The
giteaprovider preset (packages/codev/scripts/forge/gitea/*.sh, added for #589) doesnot work against the actual
teaCLI. Most read concepts either error out or emit a JSONshape that doesn't match
forge-contracts.ts. The scripts appear to have been written againstthe Gitea REST API JSON shape, but they invoke the
teaCLI, whose--output jsonemits a different, flattened shape (and in some cases the referenced flag/field/subcommand
doesn't exist at all). This matches the in-repo note in
issue-search.sh:"tea is not available in the authoring environment (#920)" — the preset was authored blind.
Verified end-to-end with
tea0.14.2 (latest release, 2026-06-26) against a live Forgejoinstance (Forgejo is Gitea-API-compatible). Not a version-gap issue — 0.14.2 is current.
Broken concepts (verified)
user-identity.shtea whoami --output json | jq -r .logintea whoamihas no--output jsonflag →Error: flag provided but not defined: -outputpr-list.shtea pulls list --fields …,description --output jsonError: invalid field 'description'— the whole concept errors;tea pulls listexposes nodescription/bodyfieldpr-view.shtea pulls view N --output json[]/ a table header, not the PR objectissue-view.shtea issues view N --output json | jq '.url = (.html_url // .url)'body/html_url/urlfieldsissue-comment.shtea issues comment …tea issueshas nocomment; commenting lives undertea comments addpr-exists.sh… | jq 'select(.head.ref == $B and (.state=="closed" and .merged==true) …)'tea pulls listemits.headas a string, not{ref}, and reports merged PRs asstate:"merged"(no.mergedbool) →Cannot index string with string "ref"recently-merged.sh--fields …,head,description,merged+.head.ref+.merged==truehead+ invaliddescriptionfield problemsWorking as-is:
auth-status,issue-list,recently-closed,pr-merge,repo-archive(the last already uses
tea api).Root cause
Two divergent JSON surfaces in
tea:tea <entity> list --output json— a flattened,--fields-limited view(
head/baseare strings,indexis a string, no nested objects, nobody/descriptionfor pulls, state is synthesized to
"merged").tea api <endpoint>— a raw passthrough to the Gitea REST API, returning the exactdocumented API shape.
codev's jq normalizers and
forge-contracts.tsare written for (2) but the scripts call (1).Recommended fix: route read concepts through
tea apitea apireturns precisely the shape the existing jq already assumes, so the fix is mostly adata-source swap with the jq kept intact. Verified against live Forgejo:
This is minimal-diff (keep the jq contracts), and robust across
teaversions since it avoidsthe CLI's
--fields/flattening quirks entirely.One inherent caveat (not a codev bug)
For a merged PR whose source branch was deleted, Gitea's API returns
.head.ref == "refs/pull/N/head"instead of the original branch name — so a branch-name matchin
pr-existswon't hit a merged+deleted branch. That's a Gitea behavior; worth a comment inthe script but doesn't affect the "does an open/merged PR exist for the branch I'm about to
push" use case.
Reproducibility (not environment-specific)
Verified two independent ways, neither dependent on the reporting instance:
1. The failures are defined in the
teabinary, before any server contact:2. Canonical upstream Gitea (
gitea.com, reference implementation) via plaincurl— notea:The REST shape codev's jq assumes (
.head.ref,.user.login,.merged, object responses) iscorrect and canonical — the scripts just read from the wrong source (
tea <entity> list, whichflattens/limits it) instead of
tea api. A self-hosted Forgejo returns byte-identical shape, sothis is not a fork divergence; it reproduces against gitea.com itself.
Environment
tea0.14.2 (latest release, 2026-06-26;brew install tea)@cluesmith/codev3.2.2gitea.com(canonical Gitea).shscripts are not exercised by CI (forge.test.tsuses mock scripts; perthe in-repo
#920noteteaisn't available in the authoring/CI env), so these were validatedmanually against live instances.
tea apiapproach above if you're on board.