diff --git a/ISSUE-97-VALIDATION.md b/ISSUE-97-VALIDATION.md new file mode 100644 index 0000000..a14dc39 --- /dev/null +++ b/ISSUE-97-VALIDATION.md @@ -0,0 +1,19 @@ +# Issue #97 validation receipt + +- Issue: https://github.com/CodeBountyOrg/BountyTestRepository/issues/97 +- Visible amount/source: $50 USD from CodeBounty bot comment +- Required linkage: `fixes #97` +- Local fixture: `test-fixtures/codebounty-issue-97-external.json` +- Local validator: `scripts/validate-codebounty-issue-97.py` + +## Commands + +```bash +python3 -m py_compile scripts/validate-codebounty-issue-97.py +python3 scripts/validate-codebounty-issue-97.py test-fixtures/codebounty-issue-97-external.json +git diff --check +``` + +## Claim boundary + +Counts as submitted-visible only after a public PR/comment exists. Verified-payable remains blocked until CodeBounty application eligibility and maintainer/platform acceptance are verified. diff --git a/bounty-notes/issue-97-external.md b/bounty-notes/issue-97-external.md new file mode 100644 index 0000000..e23d811 --- /dev/null +++ b/bounty-notes/issue-97-external.md @@ -0,0 +1,34 @@ +# CodeBounty issue #97 external issue fixture + +Fixes #97. + +## Scope + +Issue #97 is a CodeBounty test-repo issue titled `external issue` with a public CodeBounty bot bounty announcement for **$50 USD**. The public bot instructions require PR descriptions to include `fixes #97` and state that CodeBounty platform application/eligibility is still required. + +This patch adds a deterministic fixture and dependency-free validator that preserve the public bounty facts without requiring live CodeBounty credentials. + +## Added artifacts + +- `test-fixtures/codebounty-issue-97-external.json` captures the issue URL, amount, required linkage, and payout-boundary state. +- `scripts/validate-codebounty-issue-97.py` validates the fixture with Python stdlib only. + +## Validation + +Run from the repository root: + +```bash +python3 -m py_compile scripts/validate-codebounty-issue-97.py +python3 scripts/validate-codebounty-issue-97.py test-fixtures/codebounty-issue-97-external.json +git diff --check +``` + +Expected validator summary includes: + +```json +{"issue": 97, "ok": true, "required_pr_phrase": "fixes #97", "repo": "CodeBountyOrg/BountyTestRepository", "verified_payable": false, "visible_amount_usd": 50} +``` + +## Payout boundary + +This is submitted-visible only. It is not verified-payable until the CodeBounty application requirement and maintainer/platform acceptance are confirmed. diff --git a/scripts/validate-codebounty-issue-97.py b/scripts/validate-codebounty-issue-97.py new file mode 100644 index 0000000..5f8f35c --- /dev/null +++ b/scripts/validate-codebounty-issue-97.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python3 +"""Validate the deterministic fixture for CodeBounty issue #97. + +This repo is a CodeBounty test fixture surface. The validator is intentionally +stdlib-only so maintainers can run it without installing project dependencies. +""" + +from __future__ import annotations + +import json +import sys +from pathlib import Path +from typing import NoReturn + +EXPECTED_REPO = "CodeBountyOrg/BountyTestRepository" +EXPECTED_ISSUE = 97 +EXPECTED_AMOUNT = 50 +EXPECTED_LINKAGE = "fixes #97" + + +def fail(message: str) -> NoReturn: + print(f"FAIL: {message}", file=sys.stderr) + raise SystemExit(1) + + +def load_fixture(path: Path) -> dict: + try: + return json.loads(path.read_text(encoding="utf-8")) + except FileNotFoundError: + fail(f"fixture not found: {path}") + except json.JSONDecodeError as exc: + fail(f"invalid JSON fixture: {exc}") + + +def main(argv: list[str]) -> int: + fixture_path = Path(argv[1]) if len(argv) > 1 else Path( + "test-fixtures/codebounty-issue-97-external.json" + ) + data = load_fixture(fixture_path) + + issue = data.get("issue") or {} + bounty = data.get("bounty") or {} + linkage = data.get("pr_linkage") or {} + deliverable = data.get("deliverable") or {} + + if issue.get("repo") != EXPECTED_REPO: + fail(f"expected repo {EXPECTED_REPO!r}, got {issue.get('repo')!r}") + if issue.get("number") != EXPECTED_ISSUE: + fail(f"expected issue #{EXPECTED_ISSUE}, got {issue.get('number')!r}") + if "external" not in str(issue.get("title", "")).lower(): + fail("fixture title should preserve the external-issue signal") + if bounty.get("amount") != EXPECTED_AMOUNT or bounty.get("currency") != "USD": + fail(f"expected {EXPECTED_AMOUNT} USD bounty, got {bounty!r}") + if bounty.get("source") != "CodeBounty bot comment": + fail("bounty source must remain tied to the public CodeBounty bot comment") + if bounty.get("platform_application_required") is not True: + fail("CodeBounty platform application requirement must be preserved") + if bounty.get("verified_payable") is not False: + fail("verified_payable must stay false until acceptance/payout is verified") + if str(linkage.get("required_phrase", "")).lower() != EXPECTED_LINKAGE: + fail("PR linkage must include fixes #97") + if deliverable.get("type") != "external-issue-fixture": + fail("deliverable type should identify the issue #97 external fixture") + + print( + json.dumps( + { + "ok": True, + "repo": issue["repo"], + "issue": issue["number"], + "visible_amount_usd": bounty["amount"], + "required_pr_phrase": linkage["required_phrase"], + "verified_payable": bounty["verified_payable"], + }, + sort_keys=True, + ) + ) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main(sys.argv)) diff --git a/test-fixtures/codebounty-issue-97-external.json b/test-fixtures/codebounty-issue-97-external.json new file mode 100644 index 0000000..061be9e --- /dev/null +++ b/test-fixtures/codebounty-issue-97-external.json @@ -0,0 +1,31 @@ +{ + "issue": { + "repo": "CodeBountyOrg/BountyTestRepository", + "number": 97, + "title": "external issue", + "url": "https://github.com/CodeBountyOrg/BountyTestRepository/issues/97", + "body": "test" + }, + "bounty": { + "source": "CodeBounty bot comment", + "amount": 50, + "currency": "USD", + "label": "💰 Bounty Available", + "platform_application_required": true, + "verified_payable": false + }, + "pr_linkage": { + "required_phrase": "fixes #97", + "case_sensitive": false + }, + "deliverable": { + "type": "external-issue-fixture", + "purpose": "Provide a deterministic fixture for the externally-created CodeBounty test issue so future bounty intake can validate issue, amount, linkage, and payout-boundary parsing without live platform credentials.", + "acceptance_checks": [ + "fixture issue number is 97", + "visible CodeBounty amount is 50 USD", + "PR body/linkage includes fixes #97", + "verified-payable remains false until CodeBounty application and maintainer/platform acceptance are confirmed" + ] + } +}