Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .github/ISSUE_TEMPLATE/bounty.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
name: MRWK bounty
description: Propose work that may receive an MRWK bounty.
description: Draft bounty text for maintainer proposal and execution.
title: "MRWK bounty: <amount> MRWK - <short scope>"
labels: ["mrwk:bounty"]
body:
- type: markdown
attributes:
value: |
Do not add the live bounty label from this template. A GitHub issue is not claimable until the treasury proposal executes, the public bounty page exists, and maintainers post the reserved bounty comment.

Use the stable bounty shape from `docs/bounty-rules.md` so humans, GitHub search, API clients, and MCP agents can parse the reward, scope, evidence, and exclusions.
Keep public MRWK wording work-based: no price, investment, exchange, liquidity, bridge, cash-out, or fabricated payout claims.
- type: textarea
Expand Down
83 changes: 83 additions & 0 deletions .github/ISSUE_TEMPLATE/proposed-work.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
name: Proposed work request
description: Suggest work for maintainer review before any MRWK bounty exists.
title: "Proposed work: <short scope>"
labels: ["proposed-work"]
body:
- type: markdown
attributes:
value: |
This is not a live MRWK bounty. Opening this issue does not reserve MRWK, create a payout, or make work claimable.

Do not submit `/claim` for this issue unless maintainers later post a live reserved bounty comment and the public bounty page exists.
- type: textarea
id: problem
attributes:
label: Problem
description: Describe the bug, missing docs, confusing workflow, UX issue, test gap, or improvement opportunity.
validations:
required: true
- type: textarea
id: evidence
attributes:
label: Evidence
description: Link the exact page, API route, file, PR, issue, command output, screenshot, or reproduction path.
validations:
required: true
- type: textarea
id: proposed_work
attributes:
label: Proposed work
description: Describe the smallest useful fix, verification, documentation, or implementation work.
validations:
required: true
- type: textarea
id: expected_value
attributes:
label: Expected value
description: Explain who this helps and what gets easier, safer, clearer, or more reliable.
validations:
required: true
- type: dropdown
id: reference_tier
attributes:
label: Reference tier
description: Non-binding guidance only. Maintainers decide whether any bounty proposal is opened.
options:
- "25-100 MRWK: small docs, typo, reproduction, triage"
- "100-500 MRWK: useful issue, test, docs page, small bugfix"
- "500-2,500 MRWK: normal feature, verified bugfix, agent integration"
- "2,500-10,000 MRWK: security fix, major feature, infrastructure work"
validations:
required: true
- type: textarea
id: acceptance
attributes:
label: Possible acceptance criteria
description: List what would need to be true before maintainers could accept the work.
validations:
required: true
- type: textarea
id: tests
attributes:
label: Evidence or tests required
description: List commands, URLs, screenshots, logs, reproduction steps, or review evidence.
validations:
required: true
- type: textarea
id: duplicate_search
attributes:
label: Duplicate search
description: Link related issues or PRs and explain why this is not already covered.
validations:
required: true
- type: textarea
id: out_of_scope
attributes:
label: Out of scope
description: List work that should not be included.
placeholder: |
- No broad rewrites.
- No speculative price, liquidity, bridge, exchange, cash-out, or payout claims.
- No private secrets or security exploit details in public artifacts.
validations:
required: true
11 changes: 11 additions & 0 deletions docs/agent-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,17 @@ Use this checklist before opening a PR for `mrwk:bounty` issues:
Common rejection reasons: duplicate scope, style-only changes without user
impact, missing evidence, or ignoring issue-specific acceptance criteria.

## Proposed Work Requests

Proposed work requests are intake issues, not live bounties. They may describe a
bug, docs gap, UX issue, verification task, or possible future bounty scope, but
they do not reserve MRWK and they do not make work claimable.

Do not submit `/claim` for a proposed work request. You may add concise evidence,
duplicate-search notes, reproduction steps, or a suggested reference tier, but
wait for `mrwk:bounty`, a `Reserved on MergeWork` comment, and a public bounty
page before treating the issue as bounty work.

### Recovering from Rejection

A `mrwk:rejected` label does not mean the entire contribution is worthless. Use rejection as diagnostic feedback:
Expand Down
22 changes: 22 additions & 0 deletions docs/bounty-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,30 @@ Accepted work can include:

MRWK uses work-based tiers at launch. The project does not publish a fiat peg.

## Proposed Work Requests

A proposed work request is not a live MRWK bounty. It is an intake issue for
ideas, bugs, docs gaps, verification needs, and possible future bounty scopes.
Opening one does not reserve MRWK, create a payout, or make work claimable.

The normal lifecycle is:

```text
proposed issue -> maintainer review -> optional create_bounty proposal -> 24-hour delay -> execution -> mrwk:bounty + Reserved on MergeWork -> claims open
```

Reference tiers are guidance, not entitlement. Contributors and agents may
suggest a tier to help maintainers size the work, but maintainers decide whether
to reject, ask for more information, point to an existing live bounty, accept
non-bounty work, or create a public treasury proposal.

Do not submit `/claim` for a proposed work request unless maintainers later make
the issue live by executing the treasury proposal, adding `mrwk:bounty`, and
posting the `Reserved on MergeWork` comment with the public bounty URL.

## Labels

- `proposed-work`: intake issue for possible future work; not a live bounty.
- `mrwk:bounty`: issue has a posted MRWK reward.
- `mrwk:claimed`: someone is actively working on the issue.
- `mrwk:submitted`: work is ready for review.
Expand Down
28 changes: 28 additions & 0 deletions scripts/docs_smoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
"docs/agent-guide.md": [
("Public reads such as `GET /api/v1/bounties/{id}/attempts` do not require login"),
("creating or releasing an attempt requires the GitHub-authenticated browser session"),
"Proposed work requests are intake issues, not live bounties",
"wait for `mrwk:bounty`",
],
"docs/paid-bounties.md": [
"This page is not manually updated for every payout.",
Expand All @@ -65,6 +67,9 @@
"Smoke-check or bug-report claim:",
"Discussion or decision-support claim:",
"Do not describe work as accepted, merged, or paid until the public GitHub label",
"## Proposed Work Requests",
"proposed issue -> maintainer review -> optional create_bounty proposal",
"Reference tiers are guidance, not entitlement",
],
"docs/api-examples.md": [
"Internal ledger accounts use the same account response shape",
Expand Down Expand Up @@ -151,6 +156,7 @@ def main() -> int:
bounty_template = bounty_issue_template.read_text(encoding="utf-8").lower()
for phrase in [
"mrwk bounty: <amount> mrwk - <short scope>",
"do not add the live bounty label from this template",
"id: evidence",
"evidence or tests required",
"id: out_of_scope",
Expand All @@ -159,10 +165,32 @@ def main() -> int:
if phrase not in bounty_template:
print(f"bounty issue template missing required phrase: {phrase}")
ok = False
if 'labels: ["mrwk:bounty"]' in bounty_template:
print("bounty issue template must not auto-apply mrwk:bounty")
ok = False
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
for field_id in ("evidence", "out_of_scope", "duplicate_stale_rules"):
if not _template_field_is_required(bounty_template, field_id):
print(f"bounty issue template {field_id} field must be required")
ok = False
proposed_work_template = ROOT / ".github/ISSUE_TEMPLATE/proposed-work.yml"
if not proposed_work_template.exists():
print("missing proposed work issue template: .github/ISSUE_TEMPLATE/proposed-work.yml")
ok = False
else:
proposed_template = proposed_work_template.read_text(encoding="utf-8").lower()
for phrase in [
'title: "proposed work: <short scope>"',
'labels: ["proposed-work"]',
"not a live mrwk bounty",
"do not submit `/claim`",
"id: duplicate_search",
]:
if phrase not in proposed_template:
print(f"proposed work issue template missing required phrase: {phrase}")
ok = False
if "mrwk:bounty" in proposed_template:
print("proposed work issue template must not mention or apply mrwk:bounty")
ok = False
if ok:
print("docs smoke ok")
return 0
Expand Down
40 changes: 40 additions & 0 deletions tests/test_docs_public_urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,46 @@ def test_admin_runbook_documents_webhook_event_limit_cap() -> None:
assert "/api/v1/admin/webhook-events?status=missing_submitter&limit=100" not in runbook


def test_proposed_work_template_is_not_a_live_bounty_template() -> None:
template = Path(".github/ISSUE_TEMPLATE/proposed-work.yml").read_text(encoding="utf-8")
lowered = template.lower()

assert 'title: "proposed work: <short scope>"' in lowered
assert 'labels: ["proposed-work"]' in lowered
assert "mrwk:bounty" not in lowered
assert "not a live mrwk bounty" in lowered
assert "do not submit `/claim`" in lowered
assert "reference tier" in lowered


def test_bounty_issue_template_does_not_auto_mark_issue_live() -> None:
template = Path(".github/ISSUE_TEMPLATE/bounty.yml").read_text(encoding="utf-8")

assert 'labels: ["mrwk:bounty"]' not in template
assert "Do not add the live bounty label from this template" in template


def test_bounty_rules_document_proposed_work_lifecycle() -> None:
rules = Path("docs/bounty-rules.md").read_text(encoding="utf-8")
squashed = " ".join(rules.split())

assert "## Proposed Work Requests" in rules
assert "proposed work request is not a live MRWK bounty" in rules
assert (
"proposed issue -> maintainer review -> optional create_bounty proposal -> "
"24-hour delay -> execution -> mrwk:bounty"
) in squashed
assert "Reference tiers are guidance, not entitlement" in rules


def test_agent_guide_tells_agents_not_to_claim_proposed_work() -> None:
guide = Path("docs/agent-guide.md").read_text(encoding="utf-8")

assert "Proposed work requests are intake issues, not live bounties" in guide
assert "Do not submit `/claim`" in guide
assert "wait for `mrwk:bounty`" in guide


def test_api_examples_document_bounty_list_response_shape() -> None:
examples = Path("docs/api-examples.md").read_text(encoding="utf-8")

Expand Down
Loading