- Create or choose a GitHub issue.
- Decide the MRWK amount using the reference tiers.
- Add acceptance text that explains what counts as useful accepted work.
- Set
max_awardsto the number of separate payouts allowed. Use1for a single-award bounty. - Use
/adminorPOST /api/v1/bountieswith an admin token. Multi-award bounties reservereward_mrwk * max_awards. - Add
mrwk:bountyto the GitHub issue.
- Review the submission and test evidence.
- Confirm the work matches the bounty acceptance text.
- Confirm the labeler is listed in
MERGEWORK_GITHUB_ACCEPTED_LABELERS. - Confirm the PR body links the bounty issue. Use
Bounty #3orRefs #3for multi-award bounties; useCloses #3only when the bounty issue should close after that PR. - Apply
mrwk:acceptedto the PR. - Confirm the webhook records one ledger payment to the PR author.
- Add
mrwk:paidto the PR after the explorer/API shows the proof. - Add
mrwk:paidto the bounty issue only after all awards are exhausted or the bounty is intentionally closed.
To close an open bounty without paying the remaining awards, release the unused reserve:
curl -X POST https://api.mrwk.ltclab.site/api/v1/bounties/<id>/close \
-H "content-type: application/json" \
-H "x-mergework-admin-token: $MERGEWORK_ADMIN_TOKEN" \
-d '{
"reference": "https://github.com/ramimbo/mergework/issues/<issue>#close",
"closed_by": "maintainer-login"
}'If the contributor linked a wallet, the payout goes directly to that mrwk1
address. If not, it goes to github:{login} and can be claimed later after
GitHub OAuth and wallet-linking.
Use the admin-token payout API when the accepted proof is a comment, wallet address, or other non-PR submission:
curl -X POST https://api.mrwk.ltclab.site/api/v1/bounties/<id>/pay \
-H "content-type: application/json" \
-H "x-mergework-admin-token: $MERGEWORK_ADMIN_TOKEN" \
-d '{
"to_account": "mrwk1...",
"submission_url": "https://github.com/ramimbo/mergework/issues/2#issuecomment-...",
"accepted_by": "maintainer-login"
}'to_account must be a registered mrwk1... wallet or github:{login}.
Manual payout checklist:
- Verify the public proof and wallet address.
- Pay through
POST /api/v1/bounties/{id}/pay. - Confirm the explorer/API shows the proof.
- Add
mrwk:paidto the paid comment or submission when possible. - Add
mrwk:paidto the bounty issue only after all awards are exhausted or the bounty is intentionally closed.
Do not apply mrwk:accepted to maintainer-authored bounty issues for payment;
those issues require the manual payout path.
- Confirm the webhook or admin API records one ledger payment for that award.
- Confirm the proof pays the intended contributor account.
- Add the paid bounty row to docs/paid-bounties.md and GitHub Discussions #16.
Production GitHub OAuth is configured for https://mrwk.ltclab.site.
Contributors use /me to sign in, link wallets, and claim older GitHub ledger
balances. If the GitHub app is rotated later, update deployment secrets outside
the repository and restart Docker Compose.
- Ask for concrete missing evidence with
mrwk:needs-info. - Use
mrwk:rejectedonly when the submission is clearly not acceptable. - Keep public comments short and specific.
- For security reports, keep private details out of public comments and proofs.
- Database:
/srv/mergework/data/mergework.sqlite3. - Backups:
/srv/mergework/backups. - Health check:
GET /health. - Logs:
docker compose logs -f app caddy.
Generate MERGEWORK_GITHUB_WEBHOOK_SECRET, MERGEWORK_ADMIN_TOKEN, and
MERGEWORK_COOKIE_SECRET with at least 32 random characters. Keep them outside
the repository.
Run the deploy gate before posting a bounty:
docker compose run --rm app python scripts/check_deploy_ready.pyRun a staging webhook payout dry run against a staging host:
MERGEWORK_STAGING_BASE_URL=https://staging.mrwk.example.test \
MERGEWORK_DRY_RUN_REPO=ramimbo/mergework \
docker compose run --rm app python scripts/staging_webhook_dry_run.py