Forgejo REST API returns state as lowercase ("closed"/"open") but
branch.ts compares against GraphQL-style uppercase ("CLOSED"/"MERGED").
This caused @claude on closed/merged PRs to take the open-PR checkout
path, failing with "fatal: invalid reference: refs/pull/N/head".
Normalize state to uppercase in the Forgejo data fetcher, matching the
existing pattern used for review state (line 153).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Both mock.module and spyOn cause cross-file test pollution in Bun's
single-process runner — mock.module poisons the module registry permanently,
and spyOn doesn't correctly restore ESM live bindings across files on Linux.
The real downloadCommentImages is safe to call because test comment bodies
contain no GitHub image URLs, so the function finds zero images and returns
an empty Map naturally. The only side effect is mkdir("/tmp/github-images")
which is harmless on CI runners.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
mock.module("image-downloader") in forgejo-data-fetcher.test.ts replaced
the module in Bun's registry globally for the entire process. When Bun's
non-deterministic file ordering ran this file BEFORE image-downloader.test.ts,
the image-downloader tests imported a stubbed module instead of the real one,
breaking all 18 tests. This was the root cause of the CI failures that
persisted through 5 previous fix attempts.
spyOn patches the live module export per-test and is auto-restored by Bun
after each test — no cross-file pollution regardless of execution order.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Forgejo doesn't have the flat GET /pulls/{number}/comments endpoint
(returns 404). Replace pulls.listReviewComments() with a 2-phase
approach: fetch reviews first, then pulls.listCommentsForReview()
per-review in parallel. Updates tests to mock the new per-review API.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add 3 REST calls to Promise.all for PRs (listComments, listReviews,
listReviewComments) and 1 for issues (listComments)
- Add mapping helpers: mapRestComments, mapRestReviewComments,
mapRestReviews (groups inline comments by pull_request_review_id)
- Import and apply TOCTOU filtering (filterCommentsToTriggerTime,
filterReviewsToTriggerTime) and actor filtering from GitHub fetcher
- Add image processing pipeline via downloadCommentImages (no-op on
Forgejo due to URL pattern mismatch, architecturally correct)
- Deep-clone reviews before filtering to preserve contextData immutability
- Update test suite: 51 tests covering mapping helpers, full fetch
flow, TOCTOU filtering, actor filtering, and contextData immutability
- Updated PRD checkboxes for M4b completion
Progress: 44% complete (4/9 milestones) - next: M5 or M3
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>