Files
stack/packages/mosaic/framework/tools/git/README.md
Hermes Agent 10fdd49e32
All checks were successful
ci/woodpecker/pr/ci Pipeline was successful
fix(tools): bound Gitea read-back to this write; verify approve/reject state (#865)
Review remediation for two correctness holes in the #865 fix:

BLOCKER 1 — issue-comment.sh read-back was body-only across all history:
if `tea comment` silently no-opped (the #865 bug) while an identically
bodied comment already existed from a prior run, the read-back matched the
OLD comment and falsely reported success. Now record the pre-write maximum
comment id as a boundary and require a comment with id > boundary AND exact
body match; monotonic Gitea ids make id > boundary mean "created by this
write". Fails closed otherwise.

BLOCKER 2 — pr-review.sh approve/reject trusted tea's exit code for the
review STATE (same never-trust-exit-zero defect class as #865). Removed the
TODO deferral and added a real bounded read-back: record the max review id
before `tea pr approve`/`reject`, then require a review with id > boundary,
the expected state (APPROVED / REQUEST_CHANGES), and commit_id equal to the
PR's current head. Fails closed if absent.

Tests: extended test-pr-review-gitea-comment.sh to model and assert the new
review-state read-back (guardrails preserved, assertions added). Added
test-issue-comment-readback.sh proving the pre-existing-identical-body
false positive now fails closed and a genuinely new comment verifies.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-21 18:21:02 -05:00

3.8 KiB

Git provider wrappers

These scripts provide host-aware GitHub and Gitea issue, pull-request, milestone, and CI operations.

Durable review provenance

A successful provider write command—or a wrapper message based only on that command's exit code—is not durable review provenance. Review comments, approvals, and change requests count as durable provenance only after the wrapper reads the created provider record back and verifies that it was created by this write.

pr-review.sh therefore fails closed when a Gitea comment cannot be written, its created comment ID cannot be identified, or provider read-back does not match. It reports comment success only after that read-back verification passes. The approve and request-changes actions apply the same discipline to the review state itself: they record the maximum existing review id before invoking tea pr approve/reject, then require a review whose id is strictly greater than that boundary, whose state matches the requested action (APPROVED / REQUEST_CHANGES), and whose reviewed commit equals the PR's current head. tea's exit code alone is never treated as evidence the review landed.

issue-comment.sh applies the same fail-closed, boundary-bounded read-back to issue comments: it records the maximum existing comment id before posting via tea comment, then re-fetches the issue's comments via the Gitea REST API and requires a comment whose id is strictly greater than that boundary and whose body exactly matches what was submitted. Bounding the read-back by the pre-write id is essential — a body-only match across all history would falsely report success if tea comment silently no-ops (the #865 bug) while an identically-bodied comment already existed from a prior run. Gitea comment and review ids are monotonic, so id > boundary reliably means "created after this write began".

tea invocation notes (Gitea)

  • tea v0.11.1 has no comment subcommand under tea pr or tea issue. The correct invocation is the top-level tea comment <index> <body> [--repo ...] [--login ...]. The tea pr comment / tea issue comment forms don't error — tea silently falls through to a no-op and still exits 0, producing a false-success write (#865). Always use the top-level form.
  • tea pr approve and tea pr reject take an optional review comment/reason as a trailing positional argument, not a --comment/-comment flag (that flag does not exist on those subcommands). pr-review.sh avoids this positional form entirely for the approve/reject actions and instead posts any review comment through the same durable, read-back-verified comment API used for the comment action (see #835/#812) — the trailing-positional form remains available to callers who invoke tea directly, but is not used by these wrappers.

--login passthrough

Both pr-review.sh and issue-comment.sh accept an optional --login <name> flag that overrides the automatically detected Gitea tea login for that single invocation. The override is appended to the tea command line after the detected default (get_gitea_repo_args() / get_gitea_login[_for_host]()), because tea honors only the last --login flag on its command line — an override placed before the default would be silently clobbered by it. Callers who need a different login than the host default should pass --login <reviewer-login> rather than relying on ordering tricks or re-invoking tea login globally.

As a durable successor to this mechanism, consider giving each reviewer/approver slot its own dedicated Gitea login credential, so that author≠reviewer holds at the credential level rather than relying on wrapper-level --login bookkeeping. This is a recommendation for future hardening, not something implemented by this flag.