diff --git a/ISSUE-34-VALIDATION.md b/ISSUE-34-VALIDATION.md new file mode 100644 index 0000000..7464bee --- /dev/null +++ b/ISSUE-34-VALIDATION.md @@ -0,0 +1,24 @@ +# Issue #34 validation receipt + +- Issue: https://github.com/CodeBountyOrg/BountyTestRepository/issues/34 +- Visible amount/source: $10 USD from CodeBounty bot comment plus `💰 Bounty Available` label +- Announcement comment: https://github.com/CodeBountyOrg/BountyTestRepository/issues/34#issuecomment-2723925317 +- Required linkage: `Fixes #34` +- Local fixture: `test-fixtures/codebounty-issue-34-march14.json` +- Local validator: `scripts/validate-codebounty-issue-34.py` + +## Commands + +```bash +python3 -m py_compile scripts/validate-codebounty-issue-34.py +python3 scripts/validate-codebounty-issue-34.py test-fixtures/codebounty-issue-34-march14.json +git diff --check +``` + +## Snapshot boundary + +Fresh pre-push triage showed issue #34 open, unlocked, unassigned, repo public/not archived, and zero same-scope open PR collisions for `34`, `#34`, `fixes #34`, `issue 34`, `issue-34`, or `issue march 14 3am`. + +## Claim boundary + +This artifact counts as submitted-visible only after a public PR exists. Verified-payable remains blocked until CodeBounty application eligibility and maintainer/platform acceptance are verified. diff --git a/bounty-notes/issue-34-march14.md b/bounty-notes/issue-34-march14.md new file mode 100644 index 0000000..36e83f7 --- /dev/null +++ b/bounty-notes/issue-34-march14.md @@ -0,0 +1,21 @@ +# CodeBounty issue #34 — March 14 3am fixture note + +This note captures the public CodeBounty evidence for issue #34 so the test repository has a small, deterministic artifact tied to the bounty flow. + +## Public evidence + +- GitHub issue: https://github.com/CodeBountyOrg/BountyTestRepository/issues/34 +- Title: `issue march 14 3am` +- Body snapshot: `sdad` +- Public label: `💰 Bounty Available` +- Announcement: https://github.com/CodeBountyOrg/BountyTestRepository/issues/34#issuecomment-2723925317 +- Visible amount: `$10 USD` +- Bot-linked local bounty URL: `http://localhost:3000/bounty/67d3e306c25c14dc1ccc86bc` + +## Public-action gate + +The pre-push snapshot found the issue open, unlocked, unassigned, and free of exact same-scope open PR collisions. The required PR body linkage is `Fixes #34`. + +## Payout boundary + +This is submitted-visible only after the PR is public. It is not verified-payable until CodeBounty platform application eligibility plus maintainer/platform acceptance are verified. No paid funds are assumed from this fixture. diff --git a/scripts/validate-codebounty-issue-34.py b/scripts/validate-codebounty-issue-34.py new file mode 100644 index 0000000..d77ebab --- /dev/null +++ b/scripts/validate-codebounty-issue-34.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python3 +"""Validate the deterministic fixture for CodeBounty issue #34. + +This repository is a CodeBounty test surface. The validator is stdlib-only so +maintainers can verify the fixture without platform credentials or dependency +installation. +""" + +from __future__ import annotations + +import json +import sys +from pathlib import Path +from typing import NoReturn + +EXPECTED_REPO = "CodeBountyOrg/BountyTestRepository" +EXPECTED_ISSUE = 34 +EXPECTED_AMOUNT = 10 +EXPECTED_LINKAGE = "fixes #34" +EXPECTED_COMMENT = ( + "https://github.com/CodeBountyOrg/BountyTestRepository/issues/34" + "#issuecomment-2723925317" +) + + +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-34-march14.json" + ) + data = load_fixture(fixture_path) + + issue = data.get("issue") or {} + bounty = data.get("bounty") or {} + collision = data.get("collision_snapshot") 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 issue.get("state_at_snapshot") != "open": + fail("issue must be open at the captured snapshot") + if issue.get("locked_at_snapshot") is not False: + fail("issue must be unlocked at the captured snapshot") + if issue.get("assignees_at_snapshot") != []: + fail("issue must be unassigned at the captured snapshot") + if "💰 Bounty Available" not in issue.get("labels_at_snapshot", []): + fail("fixture must preserve the public bounty label") + if "march 14 3am" not in str(issue.get("title", "")).lower(): + fail("fixture title should preserve the March 14 issue identity") + + 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("announcement_comment_url") != EXPECTED_COMMENT: + fail("announcement comment URL changed or missing") + 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 collision.get("repo_archived") is not False: + fail("repo must be non-archived in the collision snapshot") + if collision.get("same_scope_open_prs") != []: + fail("fixture requires zero same-scope open PR collisions at snapshot") + if str(linkage.get("required_phrase", "")).lower() != EXPECTED_LINKAGE: + fail("PR linkage must include Fixes #34") + if deliverable.get("type") != "codebounty-platform-flow-fixture": + fail("deliverable type should identify the CodeBounty platform-flow fixture") + + print( + json.dumps( + { + "ok": True, + "repo": issue["repo"], + "issue": issue["number"], + "visible_amount_usd": bounty["amount"], + "required_pr_phrase": linkage["required_phrase"], + "same_scope_open_prs": len(collision["same_scope_open_prs"]), + "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-34-march14.json b/test-fixtures/codebounty-issue-34-march14.json new file mode 100644 index 0000000..d3fcc55 --- /dev/null +++ b/test-fixtures/codebounty-issue-34-march14.json @@ -0,0 +1,56 @@ +{ + "issue": { + "repo": "CodeBountyOrg/BountyTestRepository", + "number": 34, + "title": "issue march 14 3am", + "url": "https://github.com/CodeBountyOrg/BountyTestRepository/issues/34", + "state_at_snapshot": "open", + "locked_at_snapshot": false, + "assignees_at_snapshot": [], + "labels_at_snapshot": [ + "💰 Bounty Available" + ], + "body": "sdad" + }, + "bounty": { + "source": "CodeBounty bot comment", + "source_confidence": "bot-comment-plus-bounty-label", + "announcement_comment_url": "https://github.com/CodeBountyOrg/BountyTestRepository/issues/34#issuecomment-2723925317", + "local_bounty_url": "http://localhost:3000/bounty/67d3e306c25c14dc1ccc86bc", + "amount": 10, + "currency": "USD", + "label": "💰 Bounty Available", + "platform_application_required": true, + "verified_payable": false + }, + "collision_snapshot": { + "captured_at_utc": "2026-05-14T02:02:49Z", + "repo_archived": false, + "open_pr_count_at_repo": 35, + "search_terms": [ + "34", + "#34", + "fixes #34", + "issue 34", + "issue-34", + "issue march 14 3am" + ], + "same_scope_open_prs": [] + }, + "pr_linkage": { + "required_phrase": "Fixes #34", + "case_sensitive": false + }, + "deliverable": { + "type": "codebounty-platform-flow-fixture", + "purpose": "Preserve deterministic evidence for the March 14 CodeBounty test issue so future intake can validate issue state, visible amount, required GitHub linkage, collision checks, and payout boundary without relying on localhost platform access.", + "acceptance_checks": [ + "fixture issue number is 34", + "visible CodeBounty amount is 10 USD", + "public bot announcement URL is recorded", + "no same-scope open PR collision existed at snapshot", + "PR body/linkage includes Fixes #34", + "verified-payable remains false until CodeBounty application and maintainer/platform acceptance are confirmed" + ] + } +}