packages/mosaic/framework/tools/git/pr-review.sh's Gitea approve/reject paths passed a --comment flag that tea v0.11.1 does not define. tea pr approve / tea pr reject errored with flag provided but not defined: -comment whenever a review body was supplied, breaking the durable formal-review record-of-review path fleet-wide (fails closed, not a security hole).
Fix (minimal, shell-tooling only)
Removed --comment/-comment from both tea pr approve and tea pr reject invocations.
When a review body is supplied, it is now posted via the same verified Gitea comments REST API path the comment action already uses (#812) — write, then provider read-back verification of ID/body/repo/PR before reporting success.
Extracted the shared logic into a gitea_post_verified_comment() helper reused by all three actions (approve, request-changes, comment) instead of duplicating it. The pre-existing comment action's behavior and output are unchanged (still calls the same underlying write+read-back sequence, now via the shared helper).
If no comment body is supplied to approve, behavior is unchanged (plain approve, no comment call).
Red-first test
Extended the existing #812 regression harness (packages/mosaic/framework/tools/git/test-pr-review-gitea-comment.sh), which already exercises approve/reject/comment against stubbed tea/curl. The tea stub now rejects any -comment/--comment flag on pr approve/pr reject exactly like real tea v0.11.1 (flag provided but not defined: -comment, exit 1) so it authentically reproduces the bug.
RED (manual reproduction against pre-fix pr-review.sh, and against the updated harness before the fix): tea pr approve/tea pr reject invocations including --comment fail with flag provided but not defined: -comment, exit 1.
GREEN (after the fix): tea pr approve/tea pr reject run without --comment and succeed; when a body is supplied it is posted and read-back-verified via REST, reporting Added and verified review comment on Gitea PR #<n> (comment ID <id>).
All 7 packages/mosaic/framework/tools/git/test-*.sh harnesses pass, including the extended one.
Gates (repo root)
pnpm typecheck — PASS (42/42 tasks)
pnpm lint — PASS (23/23 tasks)
pnpm format:check — PASS
pnpm test — PASS (43/43 turbo tasks; Mosaic 75 files/1434 tests, Gateway 56 files/628 tests, DB 2/3 files, plus framework-shell python/bash suites)
shellcheck -x packages/mosaic/framework/tools/git/pr-review.sh — PASS (0 findings; plain shellcheck without -x reports only the pre-existing informational SC1091 for the source of a sibling script, matching this file's existing # shellcheck source= directive convention)
shellcheck -x on the updated test harness — PASS
No pre-existing failures were observed in any of the above; nothing new was introduced.
Integrity
No --no-verify, no weakened/skipped tests, no fabricated results.
Change is confined to framework tooling shell scripts and their test harness — no production application code touched.
Minimal scope: only the approve/reject --comment handling and shared-helper extraction; the comment action's own logic/output is unchanged (only reuses the extracted helper).
Closes#835. NO self-merge — awaiting named-executor merge clearance per authority model. Author lane: ms-835-build.
## Defect (#835, p3-low)
`packages/mosaic/framework/tools/git/pr-review.sh`'s Gitea approve/reject paths passed a `--comment` flag that `tea` v0.11.1 does not define. `tea pr approve` / `tea pr reject` errored with `flag provided but not defined: -comment` whenever a review body was supplied, breaking the durable formal-review record-of-review path fleet-wide (fails closed, not a security hole).
## Fix (minimal, shell-tooling only)
- Removed `--comment`/`-comment` from both `tea pr approve` and `tea pr reject` invocations.
- When a review body is supplied, it is now posted via the same verified Gitea comments REST API path the `comment` action already uses (#812) — write, then provider read-back verification of ID/body/repo/PR before reporting success.
- Extracted the shared logic into a `gitea_post_verified_comment()` helper reused by all three actions (`approve`, `request-changes`, `comment`) instead of duplicating it. The pre-existing `comment` action's behavior and output are unchanged (still calls the same underlying write+read-back sequence, now via the shared helper).
- If no comment body is supplied to `approve`, behavior is unchanged (plain approve, no comment call).
## Red-first test
Extended the existing #812 regression harness (`packages/mosaic/framework/tools/git/test-pr-review-gitea-comment.sh`), which already exercises approve/reject/comment against stubbed `tea`/`curl`. The `tea` stub now rejects any `-comment`/`--comment` flag on `pr approve`/`pr reject` exactly like real `tea` v0.11.1 (`flag provided but not defined: -comment`, exit 1) so it authentically reproduces the bug.
- RED (manual reproduction against pre-fix `pr-review.sh`, and against the updated harness before the fix): `tea pr approve`/`tea pr reject` invocations including `--comment` fail with `flag provided but not defined: -comment`, exit 1.
- GREEN (after the fix): `tea pr approve`/`tea pr reject` run without `--comment` and succeed; when a body is supplied it is posted and read-back-verified via REST, reporting `Added and verified review comment on Gitea PR #<n> (comment ID <id>)`.
- All 7 `packages/mosaic/framework/tools/git/test-*.sh` harnesses pass, including the extended one.
## Gates (repo root)
- `pnpm typecheck` — PASS (42/42 tasks)
- `pnpm lint` — PASS (23/23 tasks)
- `pnpm format:check` — PASS
- `pnpm test` — PASS (43/43 turbo tasks; Mosaic 75 files/1434 tests, Gateway 56 files/628 tests, DB 2/3 files, plus framework-shell python/bash suites)
- `shellcheck -x packages/mosaic/framework/tools/git/pr-review.sh` — PASS (0 findings; plain `shellcheck` without `-x` reports only the pre-existing informational SC1091 for the `source` of a sibling script, matching this file's existing `# shellcheck source=` directive convention)
- `shellcheck -x` on the updated test harness — PASS
No pre-existing failures were observed in any of the above; nothing new was introduced.
## Integrity
- No `--no-verify`, no weakened/skipped tests, no fabricated results.
- Change is confined to framework tooling shell scripts and their test harness — no production application code touched.
- Minimal scope: only the approve/reject `--comment` handling and shared-helper extraction; the `comment` action's own logic/output is unchanged (only reuses the extracted helper).
Closes #835. NO self-merge — awaiting named-executor merge clearance per authority model. Author lane: ms-835-build.
tea v0.11.1 defines no --comment/-comment flag on `pr approve` or `pr
reject`, so pr-review.sh's Gitea approve/reject paths errored with
"flag provided but not defined: -comment" whenever a review body was
supplied, breaking the durable formal-review path fleet-wide.
Remove --comment from both tea invocations and, when a review body is
present, post it via the same verified Gitea comments REST API path
the `comment` action already uses (#812) — extracted into a shared
gitea_post_verified_comment() helper so all three actions share one
write+read-back-verified implementation instead of duplicating it.
Extends the existing #812 regression harness
(test-pr-review-gitea-comment.sh) with a `tea` stub that rejects
unknown flags exactly like real tea v0.11.1, so it fails RED against
the pre-fix wrapper and passes GREEN after.
Closes#835.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Durable exact-head Reviewer-of-Record — APPROVE (do not merge without coordinator named-executor clearance)
Exact head bound:2e8e8aa83b4d4810d01e156438914b7798e8dee4
Independent CODE review — author lane ms-835-build != reviewer lane ms-857-review (distinct network-capable lane; conducted READ-ONLY via Gitea API + a read-only local clone of the PR head; no commits/pushes/approvals via any tool). Persisted here as a durable comment because the tea pr approve durable path is broken by exactly the defect this PR fixes (#835). VERDICT: APPROVE.
Scope (verified /pulls/857/files): exactly 2 files, both framework-shell — packages/mosaic/framework/tools/git/pr-review.sh (+132/-97) and test-pr-review-gitea-comment.sh (+37/-4). No production application code; no unrelated files.
Fix correctness:tea pr approve (L213) and tea pr reject (L230) no longer pass --comment/-comment. A shared helper gitea_post_verified_comment() (L69-176) is extracted verbatim from the pre-existing comment-action logic (POST → parse id → GET read-back → verify id/body/issue_url) and reused by approve (only when a body is supplied), request-changes (unconditional, -z COMMENT guard unchanged), and comment. The comment action's output string is byte-for-byte identical to pre-PR → no #812 regression.
Fails closed: every helper failure path (token/URL/repo resolution, curl transport, non-201 write, malformed/missing id, non-200 read-back, id/body/issue_url mismatch) → stderr + return 1; all three call sites use $(...) || exit 1. No silent-success path. shellcheck -x pr-review.sh = 0 findings.
Injection-safe: comment body is JSON-encoded via python3 os.environ, never interpolated into shell/JSON literals; curl args quoted. Regression test round-trips a body with embedded quotes, a leading --, and a newline.
Red-first genuine (independently reproduced): reviewer checked out pull/857/head (rev-parse == the bound head), ran the harness = PASS; paired the NEW harness with the pre-fix pr-review.sh (merge-base 11d2818) = genuine RED (exit 1) at the added approve-with-body case. All pre-existing #812 assertions present unmodified — nothing weakened/removed/repointed; no --no-verify/skip.
CI: Woodpecker pipeline #1942 (pull_request @ 2e8e8aa8) = success, all 9 steps green (clone, ci-postgres, install, sanitization, upgrade-guard, typecheck, lint, format, test).
Non-blocking nit (operational, not a defect): splitting approve/reject from the comment POST is two non-atomic tea calls; if approve/reject succeeds but the comment POST fails, the PR is approved/rejected with no comment and the script exits non-zero (fails loud). Unavoidable given tea v0.11.1 has no atomic option; handled as well as possible.
Author != reviewer preserved (author ms-835-build, reviewer ms-857-review). Merge authority is the coordinator's (Mos) — NO self-merge; awaiting a NAMED-EXECUTOR clearance.
### Durable exact-head Reviewer-of-Record — APPROVE (do not merge without coordinator named-executor clearance)
**Exact head bound:** `2e8e8aa83b4d4810d01e156438914b7798e8dee4`
**Independent CODE review** — author lane `ms-835-build` != reviewer lane `ms-857-review` (distinct network-capable lane; conducted READ-ONLY via Gitea API + a read-only local clone of the PR head; no commits/pushes/approvals via any tool). Persisted here as a durable comment because the `tea pr approve` durable path is broken by exactly the defect this PR fixes (#835). **VERDICT: APPROVE.**
- **Scope (verified `/pulls/857/files`):** exactly 2 files, both framework-shell — `packages/mosaic/framework/tools/git/pr-review.sh` (+132/-97) and `test-pr-review-gitea-comment.sh` (+37/-4). No production application code; no unrelated files.
- **Fix correctness:** `tea pr approve` (L213) and `tea pr reject` (L230) no longer pass `--comment`/`-comment`. A shared helper `gitea_post_verified_comment()` (L69-176) is extracted verbatim from the pre-existing `comment`-action logic (POST → parse id → GET read-back → verify id/body/issue_url) and reused by approve (only when a body is supplied), request-changes (unconditional, `-z COMMENT` guard unchanged), and comment. The `comment` action's output string is byte-for-byte identical to pre-PR → **no #812 regression**.
- **Fails closed:** every helper failure path (token/URL/repo resolution, curl transport, non-201 write, malformed/missing id, non-200 read-back, id/body/issue_url mismatch) → stderr + `return 1`; all three call sites use `$(...) || exit 1`. No silent-success path. `shellcheck -x pr-review.sh` = 0 findings.
- **Injection-safe:** comment body is JSON-encoded via `python3 os.environ`, never interpolated into shell/JSON literals; curl args quoted. Regression test round-trips a body with embedded quotes, a leading `--`, and a newline.
- **Red-first genuine (independently reproduced):** reviewer checked out `pull/857/head` (rev-parse == the bound head), ran the harness = PASS; paired the NEW harness with the pre-fix `pr-review.sh` (merge-base `11d2818`) = genuine RED (exit 1) at the added `approve`-with-body case. All pre-existing #812 assertions present unmodified — nothing weakened/removed/repointed; no `--no-verify`/skip.
- **CI:** Woodpecker pipeline **#1942** (pull_request @ `2e8e8aa8`) = **success**, all 9 steps green (clone, ci-postgres, install, sanitization, upgrade-guard, typecheck, lint, format, test).
**Non-blocking nit (operational, not a defect):** splitting approve/reject from the comment POST is two non-atomic `tea` calls; if approve/reject succeeds but the comment POST fails, the PR is approved/rejected with no comment and the script exits non-zero (fails loud). Unavoidable given tea v0.11.1 has no atomic option; handled as well as possible.
Author != reviewer preserved (author `ms-835-build`, reviewer `ms-857-review`). Merge authority is the coordinator's (Mos) — NO self-merge; awaiting a NAMED-EXECUTOR clearance.
Executor: Mos (coordinator / merge-authority). Host web1 · tmux pane mos-claude:0.0 · PID 3935025 · UTC 2026-07-20T09:19:35Z.
Clearance — all 6 checks verified primary-source by the executor, plus dual independent lane verification (MS-LEAD read-back 091339Z + homelab independent 091633Z):
PR #857 open / unmerged / mergeable / base main, 2 framework-shell files, no production code.
CI pipeline #1942 terminal success at exact head 2e8e8aa83b4d4810d01e156438914b7798e8dee4 (all steps green).
Durable Reviewer-of-Record comment #18366 = APPROVE, author-lane ms-835-build ≠ reviewer-lane ms-857-review, bound to 2e8e8aa8, no REQUEST-CHANGES.
reviewed-SHA == CI-SHA == PR head, all full-40 2e8e8aa83b4d4810d01e156438914b7798e8dee4.
Body carries Closes #835.
CI queue-guard clear (exit 0).
Merging now via squash. This comment is written BEFORE the merge mutation per the named-executor provenance rule (shared-token attribution hardening; xref #855).
### Named-executor merge — PROVENANCE STAMP (pre-mutation)
**Executor:** Mos (coordinator / merge-authority). Host `web1` · tmux pane `mos-claude:0.0` · PID `3935025` · UTC 2026-07-20T09:19:35Z.
**Clearance — all 6 checks verified primary-source by the executor, plus dual independent lane verification** (MS-LEAD read-back 091339Z + homelab independent 091633Z):
1. PR #857 open / unmerged / mergeable / base `main`, 2 framework-shell files, no production code.
2. CI pipeline #1942 terminal **success** at exact head `2e8e8aa83b4d4810d01e156438914b7798e8dee4` (all steps green).
3. Durable Reviewer-of-Record comment #18366 = **APPROVE**, author-lane `ms-835-build` ≠ reviewer-lane `ms-857-review`, bound to `2e8e8aa8`, no REQUEST-CHANGES.
4. reviewed-SHA == CI-SHA == PR head, all full-40 `2e8e8aa83b4d4810d01e156438914b7798e8dee4`.
5. Body carries `Closes #835`.
6. CI queue-guard clear (exit 0).
Merging now via **squash**. This comment is written BEFORE the merge mutation per the named-executor provenance rule (shared-token attribution hardening; xref #855).
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Defect (#835, p3-low)
packages/mosaic/framework/tools/git/pr-review.sh's Gitea approve/reject paths passed a--commentflag thatteav0.11.1 does not define.tea pr approve/tea pr rejecterrored withflag provided but not defined: -commentwhenever a review body was supplied, breaking the durable formal-review record-of-review path fleet-wide (fails closed, not a security hole).Fix (minimal, shell-tooling only)
--comment/-commentfrom bothtea pr approveandtea pr rejectinvocations.commentaction already uses (#812) — write, then provider read-back verification of ID/body/repo/PR before reporting success.gitea_post_verified_comment()helper reused by all three actions (approve,request-changes,comment) instead of duplicating it. The pre-existingcommentaction's behavior and output are unchanged (still calls the same underlying write+read-back sequence, now via the shared helper).approve, behavior is unchanged (plain approve, no comment call).Red-first test
Extended the existing #812 regression harness (
packages/mosaic/framework/tools/git/test-pr-review-gitea-comment.sh), which already exercises approve/reject/comment against stubbedtea/curl. Theteastub now rejects any-comment/--commentflag onpr approve/pr rejectexactly like realteav0.11.1 (flag provided but not defined: -comment, exit 1) so it authentically reproduces the bug.pr-review.sh, and against the updated harness before the fix):tea pr approve/tea pr rejectinvocations including--commentfail withflag provided but not defined: -comment, exit 1.tea pr approve/tea pr rejectrun without--commentand succeed; when a body is supplied it is posted and read-back-verified via REST, reportingAdded and verified review comment on Gitea PR #<n> (comment ID <id>).packages/mosaic/framework/tools/git/test-*.shharnesses pass, including the extended one.Gates (repo root)
pnpm typecheck— PASS (42/42 tasks)pnpm lint— PASS (23/23 tasks)pnpm format:check— PASSpnpm test— PASS (43/43 turbo tasks; Mosaic 75 files/1434 tests, Gateway 56 files/628 tests, DB 2/3 files, plus framework-shell python/bash suites)shellcheck -x packages/mosaic/framework/tools/git/pr-review.sh— PASS (0 findings; plainshellcheckwithout-xreports only the pre-existing informational SC1091 for thesourceof a sibling script, matching this file's existing# shellcheck source=directive convention)shellcheck -xon the updated test harness — PASSNo pre-existing failures were observed in any of the above; nothing new was introduced.
Integrity
--no-verify, no weakened/skipped tests, no fabricated results.--commenthandling and shared-helper extraction; thecommentaction's own logic/output is unchanged (only reuses the extracted helper).Closes #835. NO self-merge — awaiting named-executor merge clearance per authority model. Author lane: ms-835-build.
Durable exact-head Reviewer-of-Record — APPROVE (do not merge without coordinator named-executor clearance)
Exact head bound:
2e8e8aa83b4d4810d01e156438914b7798e8dee4Independent CODE review — author lane
ms-835-build!= reviewer lanems-857-review(distinct network-capable lane; conducted READ-ONLY via Gitea API + a read-only local clone of the PR head; no commits/pushes/approvals via any tool). Persisted here as a durable comment because thetea pr approvedurable path is broken by exactly the defect this PR fixes (#835). VERDICT: APPROVE./pulls/857/files): exactly 2 files, both framework-shell —packages/mosaic/framework/tools/git/pr-review.sh(+132/-97) andtest-pr-review-gitea-comment.sh(+37/-4). No production application code; no unrelated files.tea pr approve(L213) andtea pr reject(L230) no longer pass--comment/-comment. A shared helpergitea_post_verified_comment()(L69-176) is extracted verbatim from the pre-existingcomment-action logic (POST → parse id → GET read-back → verify id/body/issue_url) and reused by approve (only when a body is supplied), request-changes (unconditional,-z COMMENTguard unchanged), and comment. Thecommentaction's output string is byte-for-byte identical to pre-PR → no #812 regression.return 1; all three call sites use$(...) || exit 1. No silent-success path.shellcheck -x pr-review.sh= 0 findings.python3 os.environ, never interpolated into shell/JSON literals; curl args quoted. Regression test round-trips a body with embedded quotes, a leading--, and a newline.pull/857/head(rev-parse == the bound head), ran the harness = PASS; paired the NEW harness with the pre-fixpr-review.sh(merge-base11d2818) = genuine RED (exit 1) at the addedapprove-with-body case. All pre-existing #812 assertions present unmodified — nothing weakened/removed/repointed; no--no-verify/skip.2e8e8aa8) = success, all 9 steps green (clone, ci-postgres, install, sanitization, upgrade-guard, typecheck, lint, format, test).Non-blocking nit (operational, not a defect): splitting approve/reject from the comment POST is two non-atomic
teacalls; if approve/reject succeeds but the comment POST fails, the PR is approved/rejected with no comment and the script exits non-zero (fails loud). Unavoidable given tea v0.11.1 has no atomic option; handled as well as possible.Author != reviewer preserved (author
ms-835-build, reviewerms-857-review). Merge authority is the coordinator's (Mos) — NO self-merge; awaiting a NAMED-EXECUTOR clearance.Named-executor merge — PROVENANCE STAMP (pre-mutation)
Executor: Mos (coordinator / merge-authority). Host
web1· tmux panemos-claude:0.0· PID3935025· UTC 2026-07-20T09:19:35Z.Clearance — all 6 checks verified primary-source by the executor, plus dual independent lane verification (MS-LEAD read-back 091339Z + homelab independent 091633Z):
main, 2 framework-shell files, no production code.2e8e8aa83b4d4810d01e156438914b7798e8dee4(all steps green).ms-835-build≠ reviewer-lanems-857-review, bound to2e8e8aa8, no REQUEST-CHANGES.2e8e8aa83b4d4810d01e156438914b7798e8dee4.Closes #835.Merging now via squash. This comment is written BEFORE the merge mutation per the named-executor provenance rule (shared-token attribution hardening; xref #855).