DI fix passes locally in grunt-runner Docker but still fails on
actual Forgejo runner. Adding diagnostic tests to isolate whether
mock() tracking itself is broken, or something else in the runner
environment causes it.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
mock.module("fs/promises") on Linux Bun poisons the entire mock
tracking system — not just fs mocks, but ALL mock/spy assertions
(octokit mocks, spyOn(global, "fetch"), etc.) stop recording calls.
Replace with dependency injection: downloadCommentImages() now accepts
an optional fsDeps parameter. Tests pass mock mkdir/writeFile directly.
Production callers omit it and get real fs. No mock.module anywhere.
Fixes 18 test failures blocking CI on Forgejo Linux runners.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- All milestones delivered, E2E validated on PR #8
- Deferred: commit authorship E2E, cross-repo test
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add bot_email action input for custom git commit email on Forgejo
- Update claude.yml to use CLAUDE_BOT_TOKEN with bot_id/bot_name/bot_email
- Update git-config.ts to use provided email over noreply format
- Add "Dedicated Bot User" setup guide to docs/forgejo.md
- Update CLAUDE.md with bot identity documentation
Infrastructure (done outside code):
- claude-bot user created (ID 48, non-admin, with avatar)
- Claude team with write access in all 12 orgs
- CLAUDE_BOT_TOKEN org-level secret in all 12 orgs
Progress: ~85% complete - pending E2E validation after merge
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- PRD #5: Dedicated Forgejo user for Claude bot (dedicated identity, scoped token)
- PRD #6: E2E test all 5 untested Forgejo trigger scenarios
- PRD #7: Senior developer review of all Forgejo platform support code
- Defined 5, 7, and 6 milestones respectively
- All three can be parallelized (#7 is read-only, runs alongside #5)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PRD #1 (Forgejo Platform Support) is 100% complete.
All milestones M1-M9 implemented and validated.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add platform detection to prepareMcpConfig() via detectPlatform()
- Skip GitHub public MCP server (ghcr.io/github/github-mcp-server) on Forgejo
- Skip checkActionsReadPermission on Forgejo (workflow token has full access)
- Reuse existing github-actions-server.ts for both platforms (no duplication)
- Add 6 Forgejo-specific tests to install-mcp-server.test.ts
- Updated PRD checkboxes for M6
Progress: 67% complete (6/9 milestones) - M7 now unblocked
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>
- Add src/platform/detector.ts with 3-tier detection (explicit input,
FORGEJO env var, GITHUB_SERVER_URL heuristic)
- Add 'platform' input to action.yml (auto/github/forgejo)
- Add 'Detect Platform' shell step as first composite action step
- Split bun installation: oven-sh/setup-bun for GitHub, curl fallback
for Forgejo runners
- Condition 'Revoke app token' step to skip on Forgejo
- Pass resolved PLATFORM env var to run step
- Add 14 unit tests covering all detection paths
Progress: M1 complete (1/9 milestones) - M2 and M5 now unblocked
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>