feat(bounty): ServiceBounty + evaluator market — demand-side bounties with commit-reveal evaluation - #634

Open
bussyjd wants to merge 2 commits into
mainfrom
feat/servicebounty-eval-market
Open

feat(bounty): ServiceBounty + evaluator market — demand-side bounties with commit-reveal evaluation#634
bussyjd wants to merge 2 commits into
mainfrom
feat/servicebounty-eval-market

Conversation

@bussyjd

Copy link
Copy Markdown
Contributor

Stack position

PR 1 of 2 in the ServiceBounty stack. The real-money escrow leg follows in a stacked PR based on this branch. Independent of #632/#633 (skill marketplace / smoke agent) except for shared additive internal/erc8004 calldata builders — whichever merges second rebases trivially.

What

A demand-side marketplace primitive: a poster publishes a ServiceBounty CR ("do X for reward R"), a fulfiller agent claims and submits, and an evaluator market decides whether the work passes — with payment held in an escrow seam until the verdict.

Core pieces:

  • ServiceBounty CRD + controller (internal/serviceoffercontroller/bounty*.go): lifecycle Open → Claimed → Submitted → Evaluating → Paid/Rejected, driven by annotation write-channels so agents interact with plain kubectl RBAC, never controller credentials.
  • Verification by default: spec.eval.mode gates payout on an evaluator verdict; opting out requires the explicit --dangerously-skip-verification flag.
  • Commit-reveal evaluation: a panel of k evaluators commits sha256(score|salt|address) hashes, then reveals; median-of-k is the verdict; non-reveals are penalized as outliers. Quorum, reveal windows, and outlier bands are spec'd per bounty with sane defaults.
  • Evaluator ladder (EvaluatorEnrollment CRD): Shadow → Probation → Full progression — shadow evaluators score without weight, probation carries a value cap and half pay, divergence from the median sets careers back. No staking, no slashing; sybil cost comes from the unpaid shadow period and self-bonds.
  • Self-bonds: fulfillers attach a bond forfeited on rejected work (escrowed alongside the reward).
  • A2UI reports: bounty results render as structured agent-to-UI report documents (v1.0-candidate schema) incl. a bounty_report MCP tool over the existing paid-MCP seam.
  • Task-type registry: dynamic, versioned task packages (benchlocal@v1 enabled; finetune@v1 staged behind enabled:false).
  • ERC-8004 wiring (internal/erc8004/{reputation,validation}.go): calldata builders + readers for the Reputation/Validation registries — evaluator verdicts can be grounded on-chain (operator-submitted; the controller never signs).
  • Poster/fulfiller/evaluator CLI: obol bounty create|claim|submit|eval commit|eval reveal|status|... plus calldata derivation commands.

Security invariants (test-pinned)

  • Bounty reconcile creates no HTTPRoute/Middleware/ReferenceGrant/Secret/Namespace — the controller's blast radius doesn't grow.
  • Controller is read-only on evaluator enrollment specs.
  • Agent RBAC additions are namespace-scoped; admission hardening pins what agent SAs may write.
  • CRD ↔ Go parity test (caught a real pruning bug during development — kept as regression).
  • Escrow URL/credentials reach the controller via env only, never via CR spec/annotations.

Why a squash commit

This squashes a 15-commit development series (list in the commit message) so the PR reviews as one coherent unit. Granular history is preserved locally and can be pushed on request.

Validation

Full unit + controller-test suite green (panel selection determinism, commit-reveal verdicts, ladder transitions, parity, admission). Design docs included under plans/ (bounty-ane-marketplace-design.md, evaluator-market-research-notes.md). The escrow PR stacked on top carries the end-to-end money-leg validation.

🤖 Generated with Claude Code

… with commit-reveal evaluation
Squash of the eval-market series for review as one unit. Original commits
(granular history available on request):
dd8006e docs(plans): ServiceBounty + ANE marketplace design (no-slashing escrow)
bd83124 feat: scaffold ServiceBounty v1 + dynamic task-type registry
fab3737 fix: review fixes — reward payment envelope + CLI conventions
e84b77f feat: servicebounty-controller reconcile + escrow seam + lifecycle CLI
2c75ea0 docs(plans): canonical evaluator-market section + research notes
132e65f feat: evaluator-ladder schema + spec.eval.mode verification gate
45e12ea feat: A2UI report variants + catalog negotiation in deliverable schema
b295a8b feat: A2UI v1.0-candidate across the board
3889955 feat: admission hardening + poster-side CLI completeness
ef55ae8 test: CRD<->Go parity test — and the pruning bug it caught
b63a72d feat: benchlocal@v1 package + finetune@v1 staged (enabled:false)
7cb07a7 feat: bounty_report MCP tool — A2UI reports over the x402mcp seam
466671d feat: eval-market controller slice — commit-reveal quorum + self-bond
9af37c5 feat: evaluator enrollment + panel selection + OBOL eval-payment leg
cfce4f3 feat: ERC-8004 Validation/Reputation wiring — calldata builders + reveal provenance
…lenames in justfile
The generate target's singularization fallback turned 'servicebounties'
into 'servicebountie-crd.yaml'; add explicit case entries so controller-gen
output lands on the canonical filenames. Regenerated manifests pass the
CRD<->Go parity and admission tests unchanged.
@OisinKyne

Copy link
Copy Markdown
Contributor

We don't have any buyers with unfilled demands. What types of services do you anticipate here?

I don't think any of our buyers and sellers need an escrow and evaluator yet. I suggest leaving this unmerged until I have a better understanding of who needs this

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@bussyjd@OisinKyne
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

feat(bounty): ServiceBounty + evaluator market — demand-side bounties with commit-reveal evaluation - #634

Open
bussyjd wants to merge 2 commits into
mainfrom
feat/servicebounty-eval-market
Open

feat(bounty): ServiceBounty + evaluator market — demand-side bounties with commit-reveal evaluation#634
bussyjd wants to merge 2 commits into
mainfrom
feat/servicebounty-eval-market

Conversation

@bussyjd

Copy link
Copy Markdown
Contributor

Stack position

PR 1 of 2 in the ServiceBounty stack. The real-money escrow leg follows in a stacked PR based on this branch. Independent of #632/#633 (skill marketplace / smoke agent) except for shared additive internal/erc8004 calldata builders — whichever merges second rebases trivially.

What

A demand-side marketplace primitive: a poster publishes a ServiceBounty CR ("do X for reward R"), a fulfiller agent claims and submits, and an evaluator market decides whether the work passes — with payment held in an escrow seam until the verdict.

Core pieces:

  • ServiceBounty CRD + controller (internal/serviceoffercontroller/bounty*.go): lifecycle Open → Claimed → Submitted → Evaluating → Paid/Rejected, driven by annotation write-channels so agents interact with plain kubectl RBAC, never controller credentials.
  • Verification by default: spec.eval.mode gates payout on an evaluator verdict; opting out requires the explicit --dangerously-skip-verification flag.
  • Commit-reveal evaluation: a panel of k evaluators commits sha256(score|salt|address) hashes, then reveals; median-of-k is the verdict; non-reveals are penalized as outliers. Quorum, reveal windows, and outlier bands are spec'd per bounty with sane defaults.
  • Evaluator ladder (EvaluatorEnrollment CRD): Shadow → Probation → Full progression — shadow evaluators score without weight, probation carries a value cap and half pay, divergence from the median sets careers back. No staking, no slashing; sybil cost comes from the unpaid shadow period and self-bonds.
  • Self-bonds: fulfillers attach a bond forfeited on rejected work (escrowed alongside the reward).
  • A2UI reports: bounty results render as structured agent-to-UI report documents (v1.0-candidate schema) incl. a bounty_report MCP tool over the existing paid-MCP seam.
  • Task-type registry: dynamic, versioned task packages (benchlocal@v1 enabled; finetune@v1 staged behind enabled:false).
  • ERC-8004 wiring (internal/erc8004/{reputation,validation}.go): calldata builders + readers for the Reputation/Validation registries — evaluator verdicts can be grounded on-chain (operator-submitted; the controller never signs).
  • Poster/fulfiller/evaluator CLI: obol bounty create|claim|submit|eval commit|eval reveal|status|... plus calldata derivation commands.

Security invariants (test-pinned)

  • Bounty reconcile creates no HTTPRoute/Middleware/ReferenceGrant/Secret/Namespace — the controller's blast radius doesn't grow.
  • Controller is read-only on evaluator enrollment specs.
  • Agent RBAC additions are namespace-scoped; admission hardening pins what agent SAs may write.
  • CRD ↔ Go parity test (caught a real pruning bug during development — kept as regression).
  • Escrow URL/credentials reach the controller via env only, never via CR spec/annotations.

Why a squash commit

This squashes a 15-commit development series (list in the commit message) so the PR reviews as one coherent unit. Granular history is preserved locally and can be pushed on request.

Validation

Full unit + controller-test suite green (panel selection determinism, commit-reveal verdicts, ladder transitions, parity, admission). Design docs included under plans/ (bounty-ane-marketplace-design.md, evaluator-market-research-notes.md). The escrow PR stacked on top carries the end-to-end money-leg validation.

🤖 Generated with Claude Code

… with commit-reveal evaluation
Squash of the eval-market series for review as one unit. Original commits
(granular history available on request):
dd8006e docs(plans): ServiceBounty + ANE marketplace design (no-slashing escrow)
bd83124 feat: scaffold ServiceBounty v1 + dynamic task-type registry
fab3737 fix: review fixes — reward payment envelope + CLI conventions
e84b77f feat: servicebounty-controller reconcile + escrow seam + lifecycle CLI
2c75ea0 docs(plans): canonical evaluator-market section + research notes
132e65f feat: evaluator-ladder schema + spec.eval.mode verification gate
45e12ea feat: A2UI report variants + catalog negotiation in deliverable schema
b295a8b feat: A2UI v1.0-candidate across the board
3889955 feat: admission hardening + poster-side CLI completeness
ef55ae8 test: CRD<->Go parity test — and the pruning bug it caught
b63a72d feat: benchlocal@v1 package + finetune@v1 staged (enabled:false)
7cb07a7 feat: bounty_report MCP tool — A2UI reports over the x402mcp seam
466671d feat: eval-market controller slice — commit-reveal quorum + self-bond
9af37c5 feat: evaluator enrollment + panel selection + OBOL eval-payment leg
cfce4f3 feat: ERC-8004 Validation/Reputation wiring — calldata builders + reveal provenance
…lenames in justfile
The generate target's singularization fallback turned 'servicebounties'
into 'servicebountie-crd.yaml'; add explicit case entries so controller-gen
output lands on the canonical filenames. Regenerated manifests pass the
CRD<->Go parity and admission tests unchanged.
@OisinKyne

Copy link
Copy Markdown
Contributor

We don't have any buyers with unfilled demands. What types of services do you anticipate here?

I don't think any of our buyers and sellers need an escrow and evaluator yet. I suggest leaving this unmerged until I have a better understanding of who needs this

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@bussyjd@OisinKyne
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(bounty): ServiceBounty + evaluator market — demand-side bounties with commit-reveal evaluation - #634

Open
bussyjd wants to merge 2 commits into
mainfrom
feat/servicebounty-eval-market
Open

feat(bounty): ServiceBounty + evaluator market — demand-side bounties with commit-reveal evaluation#634
bussyjd wants to merge 2 commits into
mainfrom
feat/servicebounty-eval-market

Conversation

@bussyjd

Copy link
Copy Markdown
Contributor

Stack position

PR 1 of 2 in the ServiceBounty stack. The real-money escrow leg follows in a stacked PR based on this branch. Independent of #632/#633 (skill marketplace / smoke agent) except for shared additive internal/erc8004 calldata builders — whichever merges second rebases trivially.

What

A demand-side marketplace primitive: a poster publishes a ServiceBounty CR ("do X for reward R"), a fulfiller agent claims and submits, and an evaluator market decides whether the work passes — with payment held in an escrow seam until the verdict.

Core pieces:

  • ServiceBounty CRD + controller (internal/serviceoffercontroller/bounty*.go): lifecycle Open → Claimed → Submitted → Evaluating → Paid/Rejected, driven by annotation write-channels so agents interact with plain kubectl RBAC, never controller credentials.
  • Verification by default: spec.eval.mode gates payout on an evaluator verdict; opting out requires the explicit --dangerously-skip-verification flag.
  • Commit-reveal evaluation: a panel of k evaluators commits sha256(score|salt|address) hashes, then reveals; median-of-k is the verdict; non-reveals are penalized as outliers. Quorum, reveal windows, and outlier bands are spec'd per bounty with sane defaults.
  • Evaluator ladder (EvaluatorEnrollment CRD): Shadow → Probation → Full progression — shadow evaluators score without weight, probation carries a value cap and half pay, divergence from the median sets careers back. No staking, no slashing; sybil cost comes from the unpaid shadow period and self-bonds.
  • Self-bonds: fulfillers attach a bond forfeited on rejected work (escrowed alongside the reward).
  • A2UI reports: bounty results render as structured agent-to-UI report documents (v1.0-candidate schema) incl. a bounty_report MCP tool over the existing paid-MCP seam.
  • Task-type registry: dynamic, versioned task packages (benchlocal@v1 enabled; finetune@v1 staged behind enabled:false).
  • ERC-8004 wiring (internal/erc8004/{reputation,validation}.go): calldata builders + readers for the Reputation/Validation registries — evaluator verdicts can be grounded on-chain (operator-submitted; the controller never signs).
  • Poster/fulfiller/evaluator CLI: obol bounty create|claim|submit|eval commit|eval reveal|status|... plus calldata derivation commands.

Security invariants (test-pinned)

  • Bounty reconcile creates no HTTPRoute/Middleware/ReferenceGrant/Secret/Namespace — the controller's blast radius doesn't grow.
  • Controller is read-only on evaluator enrollment specs.
  • Agent RBAC additions are namespace-scoped; admission hardening pins what agent SAs may write.
  • CRD ↔ Go parity test (caught a real pruning bug during development — kept as regression).
  • Escrow URL/credentials reach the controller via env only, never via CR spec/annotations.

Why a squash commit

This squashes a 15-commit development series (list in the commit message) so the PR reviews as one coherent unit. Granular history is preserved locally and can be pushed on request.

Validation

Full unit + controller-test suite green (panel selection determinism, commit-reveal verdicts, ladder transitions, parity, admission). Design docs included under plans/ (bounty-ane-marketplace-design.md, evaluator-market-research-notes.md). The escrow PR stacked on top carries the end-to-end money-leg validation.

🤖 Generated with Claude Code

… with commit-reveal evaluation
Squash of the eval-market series for review as one unit. Original commits
(granular history available on request):
dd8006e docs(plans): ServiceBounty + ANE marketplace design (no-slashing escrow)
bd83124 feat: scaffold ServiceBounty v1 + dynamic task-type registry
fab3737 fix: review fixes — reward payment envelope + CLI conventions
e84b77f feat: servicebounty-controller reconcile + escrow seam + lifecycle CLI
2c75ea0 docs(plans): canonical evaluator-market section + research notes
132e65f feat: evaluator-ladder schema + spec.eval.mode verification gate
45e12ea feat: A2UI report variants + catalog negotiation in deliverable schema
b295a8b feat: A2UI v1.0-candidate across the board
3889955 feat: admission hardening + poster-side CLI completeness
ef55ae8 test: CRD<->Go parity test — and the pruning bug it caught
b63a72d feat: benchlocal@v1 package + finetune@v1 staged (enabled:false)
7cb07a7 feat: bounty_report MCP tool — A2UI reports over the x402mcp seam
466671d feat: eval-market controller slice — commit-reveal quorum + self-bond
9af37c5 feat: evaluator enrollment + panel selection + OBOL eval-payment leg
cfce4f3 feat: ERC-8004 Validation/Reputation wiring — calldata builders + reveal provenance
…lenames in justfile
The generate target's singularization fallback turned 'servicebounties'
into 'servicebountie-crd.yaml'; add explicit case entries so controller-gen
output lands on the canonical filenames. Regenerated manifests pass the
CRD<->Go parity and admission tests unchanged.
@OisinKyne

Copy link
Copy Markdown
Contributor

We don't have any buyers with unfilled demands. What types of services do you anticipate here?

I don't think any of our buyers and sellers need an escrow and evaluator yet. I suggest leaving this unmerged until I have a better understanding of who needs this

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@bussyjd@OisinKyne
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(bounty): ServiceBounty + evaluator market — demand-side bounties with commit-reveal evaluation - #634

Open
bussyjd wants to merge 2 commits into
mainfrom
feat/servicebounty-eval-market
Open

feat(bounty): ServiceBounty + evaluator market — demand-side bounties with commit-reveal evaluation#634
bussyjd wants to merge 2 commits into
mainfrom
feat/servicebounty-eval-market

Conversation

@bussyjd

Copy link
Copy Markdown
Contributor

Stack position

PR 1 of 2 in the ServiceBounty stack. The real-money escrow leg follows in a stacked PR based on this branch. Independent of #632/#633 (skill marketplace / smoke agent) except for shared additive internal/erc8004 calldata builders — whichever merges second rebases trivially.

What

A demand-side marketplace primitive: a poster publishes a ServiceBounty CR ("do X for reward R"), a fulfiller agent claims and submits, and an evaluator market decides whether the work passes — with payment held in an escrow seam until the verdict.

Core pieces:

  • ServiceBounty CRD + controller (internal/serviceoffercontroller/bounty*.go): lifecycle Open → Claimed → Submitted → Evaluating → Paid/Rejected, driven by annotation write-channels so agents interact with plain kubectl RBAC, never controller credentials.
  • Verification by default: spec.eval.mode gates payout on an evaluator verdict; opting out requires the explicit --dangerously-skip-verification flag.
  • Commit-reveal evaluation: a panel of k evaluators commits sha256(score|salt|address) hashes, then reveals; median-of-k is the verdict; non-reveals are penalized as outliers. Quorum, reveal windows, and outlier bands are spec'd per bounty with sane defaults.
  • Evaluator ladder (EvaluatorEnrollment CRD): Shadow → Probation → Full progression — shadow evaluators score without weight, probation carries a value cap and half pay, divergence from the median sets careers back. No staking, no slashing; sybil cost comes from the unpaid shadow period and self-bonds.
  • Self-bonds: fulfillers attach a bond forfeited on rejected work (escrowed alongside the reward).
  • A2UI reports: bounty results render as structured agent-to-UI report documents (v1.0-candidate schema) incl. a bounty_report MCP tool over the existing paid-MCP seam.
  • Task-type registry: dynamic, versioned task packages (benchlocal@v1 enabled; finetune@v1 staged behind enabled:false).
  • ERC-8004 wiring (internal/erc8004/{reputation,validation}.go): calldata builders + readers for the Reputation/Validation registries — evaluator verdicts can be grounded on-chain (operator-submitted; the controller never signs).
  • Poster/fulfiller/evaluator CLI: obol bounty create|claim|submit|eval commit|eval reveal|status|... plus calldata derivation commands.

Security invariants (test-pinned)

  • Bounty reconcile creates no HTTPRoute/Middleware/ReferenceGrant/Secret/Namespace — the controller's blast radius doesn't grow.
  • Controller is read-only on evaluator enrollment specs.
  • Agent RBAC additions are namespace-scoped; admission hardening pins what agent SAs may write.
  • CRD ↔ Go parity test (caught a real pruning bug during development — kept as regression).
  • Escrow URL/credentials reach the controller via env only, never via CR spec/annotations.

Why a squash commit

This squashes a 15-commit development series (list in the commit message) so the PR reviews as one coherent unit. Granular history is preserved locally and can be pushed on request.

Validation

Full unit + controller-test suite green (panel selection determinism, commit-reveal verdicts, ladder transitions, parity, admission). Design docs included under plans/ (bounty-ane-marketplace-design.md, evaluator-market-research-notes.md). The escrow PR stacked on top carries the end-to-end money-leg validation.

🤖 Generated with Claude Code

… with commit-reveal evaluation
Squash of the eval-market series for review as one unit. Original commits
(granular history available on request):
dd8006e docs(plans): ServiceBounty + ANE marketplace design (no-slashing escrow)
bd83124 feat: scaffold ServiceBounty v1 + dynamic task-type registry
fab3737 fix: review fixes — reward payment envelope + CLI conventions
e84b77f feat: servicebounty-controller reconcile + escrow seam + lifecycle CLI
2c75ea0 docs(plans): canonical evaluator-market section + research notes
132e65f feat: evaluator-ladder schema + spec.eval.mode verification gate
45e12ea feat: A2UI report variants + catalog negotiation in deliverable schema
b295a8b feat: A2UI v1.0-candidate across the board
3889955 feat: admission hardening + poster-side CLI completeness
ef55ae8 test: CRD<->Go parity test — and the pruning bug it caught
b63a72d feat: benchlocal@v1 package + finetune@v1 staged (enabled:false)
7cb07a7 feat: bounty_report MCP tool — A2UI reports over the x402mcp seam
466671d feat: eval-market controller slice — commit-reveal quorum + self-bond
9af37c5 feat: evaluator enrollment + panel selection + OBOL eval-payment leg
cfce4f3 feat: ERC-8004 Validation/Reputation wiring — calldata builders + reveal provenance
…lenames in justfile
The generate target's singularization fallback turned 'servicebounties'
into 'servicebountie-crd.yaml'; add explicit case entries so controller-gen
output lands on the canonical filenames. Regenerated manifests pass the
CRD<->Go parity and admission tests unchanged.
@OisinKyne

Copy link
Copy Markdown
Contributor

We don't have any buyers with unfilled demands. What types of services do you anticipate here?

I don't think any of our buyers and sellers need an escrow and evaluator yet. I suggest leaving this unmerged until I have a better understanding of who needs this

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@bussyjd@OisinKyne
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

feat(bounty): ServiceBounty + evaluator market — demand-side bounties with commit-reveal evaluation - #634

Open
bussyjd wants to merge 2 commits into
mainfrom
feat/servicebounty-eval-market
Open

feat(bounty): ServiceBounty + evaluator market — demand-side bounties with commit-reveal evaluation#634
bussyjd wants to merge 2 commits into
mainfrom
feat/servicebounty-eval-market

Conversation

@bussyjd

Copy link
Copy Markdown
Contributor

Stack position

PR 1 of 2 in the ServiceBounty stack. The real-money escrow leg follows in a stacked PR based on this branch. Independent of #632/#633 (skill marketplace / smoke agent) except for shared additive internal/erc8004 calldata builders — whichever merges second rebases trivially.

What

A demand-side marketplace primitive: a poster publishes a ServiceBounty CR ("do X for reward R"), a fulfiller agent claims and submits, and an evaluator market decides whether the work passes — with payment held in an escrow seam until the verdict.

Core pieces:

  • ServiceBounty CRD + controller (internal/serviceoffercontroller/bounty*.go): lifecycle Open → Claimed → Submitted → Evaluating → Paid/Rejected, driven by annotation write-channels so agents interact with plain kubectl RBAC, never controller credentials.
  • Verification by default: spec.eval.mode gates payout on an evaluator verdict; opting out requires the explicit --dangerously-skip-verification flag.
  • Commit-reveal evaluation: a panel of k evaluators commits sha256(score|salt|address) hashes, then reveals; median-of-k is the verdict; non-reveals are penalized as outliers. Quorum, reveal windows, and outlier bands are spec'd per bounty with sane defaults.
  • Evaluator ladder (EvaluatorEnrollment CRD): Shadow → Probation → Full progression — shadow evaluators score without weight, probation carries a value cap and half pay, divergence from the median sets careers back. No staking, no slashing; sybil cost comes from the unpaid shadow period and self-bonds.
  • Self-bonds: fulfillers attach a bond forfeited on rejected work (escrowed alongside the reward).
  • A2UI reports: bounty results render as structured agent-to-UI report documents (v1.0-candidate schema) incl. a bounty_report MCP tool over the existing paid-MCP seam.
  • Task-type registry: dynamic, versioned task packages (benchlocal@v1 enabled; finetune@v1 staged behind enabled:false).
  • ERC-8004 wiring (internal/erc8004/{reputation,validation}.go): calldata builders + readers for the Reputation/Validation registries — evaluator verdicts can be grounded on-chain (operator-submitted; the controller never signs).
  • Poster/fulfiller/evaluator CLI: obol bounty create|claim|submit|eval commit|eval reveal|status|... plus calldata derivation commands.

Security invariants (test-pinned)

  • Bounty reconcile creates no HTTPRoute/Middleware/ReferenceGrant/Secret/Namespace — the controller's blast radius doesn't grow.
  • Controller is read-only on evaluator enrollment specs.
  • Agent RBAC additions are namespace-scoped; admission hardening pins what agent SAs may write.
  • CRD ↔ Go parity test (caught a real pruning bug during development — kept as regression).
  • Escrow URL/credentials reach the controller via env only, never via CR spec/annotations.

Why a squash commit

This squashes a 15-commit development series (list in the commit message) so the PR reviews as one coherent unit. Granular history is preserved locally and can be pushed on request.

Validation

Full unit + controller-test suite green (panel selection determinism, commit-reveal verdicts, ladder transitions, parity, admission). Design docs included under plans/ (bounty-ane-marketplace-design.md, evaluator-market-research-notes.md). The escrow PR stacked on top carries the end-to-end money-leg validation.

🤖 Generated with Claude Code

… with commit-reveal evaluation
Squash of the eval-market series for review as one unit. Original commits
(granular history available on request):
dd8006e docs(plans): ServiceBounty + ANE marketplace design (no-slashing escrow)
bd83124 feat: scaffold ServiceBounty v1 + dynamic task-type registry
fab3737 fix: review fixes — reward payment envelope + CLI conventions
e84b77f feat: servicebounty-controller reconcile + escrow seam + lifecycle CLI
2c75ea0 docs(plans): canonical evaluator-market section + research notes
132e65f feat: evaluator-ladder schema + spec.eval.mode verification gate
45e12ea feat: A2UI report variants + catalog negotiation in deliverable schema
b295a8b feat: A2UI v1.0-candidate across the board
3889955 feat: admission hardening + poster-side CLI completeness
ef55ae8 test: CRD<->Go parity test — and the pruning bug it caught
b63a72d feat: benchlocal@v1 package + finetune@v1 staged (enabled:false)
7cb07a7 feat: bounty_report MCP tool — A2UI reports over the x402mcp seam
466671d feat: eval-market controller slice — commit-reveal quorum + self-bond
9af37c5 feat: evaluator enrollment + panel selection + OBOL eval-payment leg
cfce4f3 feat: ERC-8004 Validation/Reputation wiring — calldata builders + reveal provenance
…lenames in justfile
The generate target's singularization fallback turned 'servicebounties'
into 'servicebountie-crd.yaml'; add explicit case entries so controller-gen
output lands on the canonical filenames. Regenerated manifests pass the
CRD<->Go parity and admission tests unchanged.
@OisinKyne

Copy link
Copy Markdown
Contributor

We don't have any buyers with unfilled demands. What types of services do you anticipate here?

I don't think any of our buyers and sellers need an escrow and evaluator yet. I suggest leaving this unmerged until I have a better understanding of who needs this

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@bussyjd@OisinKyne
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(bounty): ServiceBounty + evaluator market — demand-side bounties with commit-reveal evaluation - #634

Open
bussyjd wants to merge 2 commits into
mainfrom
feat/servicebounty-eval-market
Open

feat(bounty): ServiceBounty + evaluator market — demand-side bounties with commit-reveal evaluation#634
bussyjd wants to merge 2 commits into
mainfrom
feat/servicebounty-eval-market

Conversation

@bussyjd

Copy link
Copy Markdown
Contributor

Stack position

PR 1 of 2 in the ServiceBounty stack. The real-money escrow leg follows in a stacked PR based on this branch. Independent of #632/#633 (skill marketplace / smoke agent) except for shared additive internal/erc8004 calldata builders — whichever merges second rebases trivially.

What

A demand-side marketplace primitive: a poster publishes a ServiceBounty CR ("do X for reward R"), a fulfiller agent claims and submits, and an evaluator market decides whether the work passes — with payment held in an escrow seam until the verdict.

Core pieces:

  • ServiceBounty CRD + controller (internal/serviceoffercontroller/bounty*.go): lifecycle Open → Claimed → Submitted → Evaluating → Paid/Rejected, driven by annotation write-channels so agents interact with plain kubectl RBAC, never controller credentials.
  • Verification by default: spec.eval.mode gates payout on an evaluator verdict; opting out requires the explicit --dangerously-skip-verification flag.
  • Commit-reveal evaluation: a panel of k evaluators commits sha256(score|salt|address) hashes, then reveals; median-of-k is the verdict; non-reveals are penalized as outliers. Quorum, reveal windows, and outlier bands are spec'd per bounty with sane defaults.
  • Evaluator ladder (EvaluatorEnrollment CRD): Shadow → Probation → Full progression — shadow evaluators score without weight, probation carries a value cap and half pay, divergence from the median sets careers back. No staking, no slashing; sybil cost comes from the unpaid shadow period and self-bonds.
  • Self-bonds: fulfillers attach a bond forfeited on rejected work (escrowed alongside the reward).
  • A2UI reports: bounty results render as structured agent-to-UI report documents (v1.0-candidate schema) incl. a bounty_report MCP tool over the existing paid-MCP seam.
  • Task-type registry: dynamic, versioned task packages (benchlocal@v1 enabled; finetune@v1 staged behind enabled:false).
  • ERC-8004 wiring (internal/erc8004/{reputation,validation}.go): calldata builders + readers for the Reputation/Validation registries — evaluator verdicts can be grounded on-chain (operator-submitted; the controller never signs).
  • Poster/fulfiller/evaluator CLI: obol bounty create|claim|submit|eval commit|eval reveal|status|... plus calldata derivation commands.

Security invariants (test-pinned)

  • Bounty reconcile creates no HTTPRoute/Middleware/ReferenceGrant/Secret/Namespace — the controller's blast radius doesn't grow.
  • Controller is read-only on evaluator enrollment specs.
  • Agent RBAC additions are namespace-scoped; admission hardening pins what agent SAs may write.
  • CRD ↔ Go parity test (caught a real pruning bug during development — kept as regression).
  • Escrow URL/credentials reach the controller via env only, never via CR spec/annotations.

Why a squash commit

This squashes a 15-commit development series (list in the commit message) so the PR reviews as one coherent unit. Granular history is preserved locally and can be pushed on request.

Validation

Full unit + controller-test suite green (panel selection determinism, commit-reveal verdicts, ladder transitions, parity, admission). Design docs included under plans/ (bounty-ane-marketplace-design.md, evaluator-market-research-notes.md). The escrow PR stacked on top carries the end-to-end money-leg validation.

🤖 Generated with Claude Code

… with commit-reveal evaluation
Squash of the eval-market series for review as one unit. Original commits
(granular history available on request):
dd8006e docs(plans): ServiceBounty + ANE marketplace design (no-slashing escrow)
bd83124 feat: scaffold ServiceBounty v1 + dynamic task-type registry
fab3737 fix: review fixes — reward payment envelope + CLI conventions
e84b77f feat: servicebounty-controller reconcile + escrow seam + lifecycle CLI
2c75ea0 docs(plans): canonical evaluator-market section + research notes
132e65f feat: evaluator-ladder schema + spec.eval.mode verification gate
45e12ea feat: A2UI report variants + catalog negotiation in deliverable schema
b295a8b feat: A2UI v1.0-candidate across the board
3889955 feat: admission hardening + poster-side CLI completeness
ef55ae8 test: CRD<->Go parity test — and the pruning bug it caught
b63a72d feat: benchlocal@v1 package + finetune@v1 staged (enabled:false)
7cb07a7 feat: bounty_report MCP tool — A2UI reports over the x402mcp seam
466671d feat: eval-market controller slice — commit-reveal quorum + self-bond
9af37c5 feat: evaluator enrollment + panel selection + OBOL eval-payment leg
cfce4f3 feat: ERC-8004 Validation/Reputation wiring — calldata builders + reveal provenance
…lenames in justfile
The generate target's singularization fallback turned 'servicebounties'
into 'servicebountie-crd.yaml'; add explicit case entries so controller-gen
output lands on the canonical filenames. Regenerated manifests pass the
CRD<->Go parity and admission tests unchanged.
@OisinKyne

Copy link
Copy Markdown
Contributor

We don't have any buyers with unfilled demands. What types of services do you anticipate here?

I don't think any of our buyers and sellers need an escrow and evaluator yet. I suggest leaving this unmerged until I have a better understanding of who needs this

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@bussyjd@OisinKyne
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(bounty): ServiceBounty + evaluator market — demand-side bounties with commit-reveal evaluation - #634

Open
bussyjd wants to merge 2 commits into
mainfrom
feat/servicebounty-eval-market
Open

feat(bounty): ServiceBounty + evaluator market — demand-side bounties with commit-reveal evaluation#634
bussyjd wants to merge 2 commits into
mainfrom
feat/servicebounty-eval-market

Conversation

@bussyjd

Copy link
Copy Markdown
Contributor

Stack position

PR 1 of 2 in the ServiceBounty stack. The real-money escrow leg follows in a stacked PR based on this branch. Independent of #632/#633 (skill marketplace / smoke agent) except for shared additive internal/erc8004 calldata builders — whichever merges second rebases trivially.

What

A demand-side marketplace primitive: a poster publishes a ServiceBounty CR ("do X for reward R"), a fulfiller agent claims and submits, and an evaluator market decides whether the work passes — with payment held in an escrow seam until the verdict.

Core pieces:

  • ServiceBounty CRD + controller (internal/serviceoffercontroller/bounty*.go): lifecycle Open → Claimed → Submitted → Evaluating → Paid/Rejected, driven by annotation write-channels so agents interact with plain kubectl RBAC, never controller credentials.
  • Verification by default: spec.eval.mode gates payout on an evaluator verdict; opting out requires the explicit --dangerously-skip-verification flag.
  • Commit-reveal evaluation: a panel of k evaluators commits sha256(score|salt|address) hashes, then reveals; median-of-k is the verdict; non-reveals are penalized as outliers. Quorum, reveal windows, and outlier bands are spec'd per bounty with sane defaults.
  • Evaluator ladder (EvaluatorEnrollment CRD): Shadow → Probation → Full progression — shadow evaluators score without weight, probation carries a value cap and half pay, divergence from the median sets careers back. No staking, no slashing; sybil cost comes from the unpaid shadow period and self-bonds.
  • Self-bonds: fulfillers attach a bond forfeited on rejected work (escrowed alongside the reward).
  • A2UI reports: bounty results render as structured agent-to-UI report documents (v1.0-candidate schema) incl. a bounty_report MCP tool over the existing paid-MCP seam.
  • Task-type registry: dynamic, versioned task packages (benchlocal@v1 enabled; finetune@v1 staged behind enabled:false).
  • ERC-8004 wiring (internal/erc8004/{reputation,validation}.go): calldata builders + readers for the Reputation/Validation registries — evaluator verdicts can be grounded on-chain (operator-submitted; the controller never signs).
  • Poster/fulfiller/evaluator CLI: obol bounty create|claim|submit|eval commit|eval reveal|status|... plus calldata derivation commands.

Security invariants (test-pinned)

  • Bounty reconcile creates no HTTPRoute/Middleware/ReferenceGrant/Secret/Namespace — the controller's blast radius doesn't grow.
  • Controller is read-only on evaluator enrollment specs.
  • Agent RBAC additions are namespace-scoped; admission hardening pins what agent SAs may write.
  • CRD ↔ Go parity test (caught a real pruning bug during development — kept as regression).
  • Escrow URL/credentials reach the controller via env only, never via CR spec/annotations.

Why a squash commit

This squashes a 15-commit development series (list in the commit message) so the PR reviews as one coherent unit. Granular history is preserved locally and can be pushed on request.

Validation

Full unit + controller-test suite green (panel selection determinism, commit-reveal verdicts, ladder transitions, parity, admission). Design docs included under plans/ (bounty-ane-marketplace-design.md, evaluator-market-research-notes.md). The escrow PR stacked on top carries the end-to-end money-leg validation.

🤖 Generated with Claude Code

… with commit-reveal evaluation
Squash of the eval-market series for review as one unit. Original commits
(granular history available on request):
dd8006e docs(plans): ServiceBounty + ANE marketplace design (no-slashing escrow)
bd83124 feat: scaffold ServiceBounty v1 + dynamic task-type registry
fab3737 fix: review fixes — reward payment envelope + CLI conventions
e84b77f feat: servicebounty-controller reconcile + escrow seam + lifecycle CLI
2c75ea0 docs(plans): canonical evaluator-market section + research notes
132e65f feat: evaluator-ladder schema + spec.eval.mode verification gate
45e12ea feat: A2UI report variants + catalog negotiation in deliverable schema
b295a8b feat: A2UI v1.0-candidate across the board
3889955 feat: admission hardening + poster-side CLI completeness
ef55ae8 test: CRD<->Go parity test — and the pruning bug it caught
b63a72d feat: benchlocal@v1 package + finetune@v1 staged (enabled:false)
7cb07a7 feat: bounty_report MCP tool — A2UI reports over the x402mcp seam
466671d feat: eval-market controller slice — commit-reveal quorum + self-bond
9af37c5 feat: evaluator enrollment + panel selection + OBOL eval-payment leg
cfce4f3 feat: ERC-8004 Validation/Reputation wiring — calldata builders + reveal provenance
…lenames in justfile
The generate target's singularization fallback turned 'servicebounties'
into 'servicebountie-crd.yaml'; add explicit case entries so controller-gen
output lands on the canonical filenames. Regenerated manifests pass the
CRD<->Go parity and admission tests unchanged.
@OisinKyne

Copy link
Copy Markdown
Contributor

We don't have any buyers with unfilled demands. What types of services do you anticipate here?

I don't think any of our buyers and sellers need an escrow and evaluator yet. I suggest leaving this unmerged until I have a better understanding of who needs this

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@bussyjd@OisinKyne
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

feat(bounty): ServiceBounty + evaluator market — demand-side bounties with commit-reveal evaluation - #634

Open
bussyjd wants to merge 2 commits into
mainfrom
feat/servicebounty-eval-market
Open

feat(bounty): ServiceBounty + evaluator market — demand-side bounties with commit-reveal evaluation#634
bussyjd wants to merge 2 commits into
mainfrom
feat/servicebounty-eval-market

Conversation

@bussyjd

Copy link
Copy Markdown
Contributor

Stack position

PR 1 of 2 in the ServiceBounty stack. The real-money escrow leg follows in a stacked PR based on this branch. Independent of #632/#633 (skill marketplace / smoke agent) except for shared additive internal/erc8004 calldata builders — whichever merges second rebases trivially.

What

A demand-side marketplace primitive: a poster publishes a ServiceBounty CR ("do X for reward R"), a fulfiller agent claims and submits, and an evaluator market decides whether the work passes — with payment held in an escrow seam until the verdict.

Core pieces:

  • ServiceBounty CRD + controller (internal/serviceoffercontroller/bounty*.go): lifecycle Open → Claimed → Submitted → Evaluating → Paid/Rejected, driven by annotation write-channels so agents interact with plain kubectl RBAC, never controller credentials.
  • Verification by default: spec.eval.mode gates payout on an evaluator verdict; opting out requires the explicit --dangerously-skip-verification flag.
  • Commit-reveal evaluation: a panel of k evaluators commits sha256(score|salt|address) hashes, then reveals; median-of-k is the verdict; non-reveals are penalized as outliers. Quorum, reveal windows, and outlier bands are spec'd per bounty with sane defaults.
  • Evaluator ladder (EvaluatorEnrollment CRD): Shadow → Probation → Full progression — shadow evaluators score without weight, probation carries a value cap and half pay, divergence from the median sets careers back. No staking, no slashing; sybil cost comes from the unpaid shadow period and self-bonds.
  • Self-bonds: fulfillers attach a bond forfeited on rejected work (escrowed alongside the reward).
  • A2UI reports: bounty results render as structured agent-to-UI report documents (v1.0-candidate schema) incl. a bounty_report MCP tool over the existing paid-MCP seam.
  • Task-type registry: dynamic, versioned task packages (benchlocal@v1 enabled; finetune@v1 staged behind enabled:false).
  • ERC-8004 wiring (internal/erc8004/{reputation,validation}.go): calldata builders + readers for the Reputation/Validation registries — evaluator verdicts can be grounded on-chain (operator-submitted; the controller never signs).
  • Poster/fulfiller/evaluator CLI: obol bounty create|claim|submit|eval commit|eval reveal|status|... plus calldata derivation commands.

Security invariants (test-pinned)

  • Bounty reconcile creates no HTTPRoute/Middleware/ReferenceGrant/Secret/Namespace — the controller's blast radius doesn't grow.
  • Controller is read-only on evaluator enrollment specs.
  • Agent RBAC additions are namespace-scoped; admission hardening pins what agent SAs may write.
  • CRD ↔ Go parity test (caught a real pruning bug during development — kept as regression).
  • Escrow URL/credentials reach the controller via env only, never via CR spec/annotations.

Why a squash commit

This squashes a 15-commit development series (list in the commit message) so the PR reviews as one coherent unit. Granular history is preserved locally and can be pushed on request.

Validation

Full unit + controller-test suite green (panel selection determinism, commit-reveal verdicts, ladder transitions, parity, admission). Design docs included under plans/ (bounty-ane-marketplace-design.md, evaluator-market-research-notes.md). The escrow PR stacked on top carries the end-to-end money-leg validation.

🤖 Generated with Claude Code

… with commit-reveal evaluation
Squash of the eval-market series for review as one unit. Original commits
(granular history available on request):
dd8006e docs(plans): ServiceBounty + ANE marketplace design (no-slashing escrow)
bd83124 feat: scaffold ServiceBounty v1 + dynamic task-type registry
fab3737 fix: review fixes — reward payment envelope + CLI conventions
e84b77f feat: servicebounty-controller reconcile + escrow seam + lifecycle CLI
2c75ea0 docs(plans): canonical evaluator-market section + research notes
132e65f feat: evaluator-ladder schema + spec.eval.mode verification gate
45e12ea feat: A2UI report variants + catalog negotiation in deliverable schema
b295a8b feat: A2UI v1.0-candidate across the board
3889955 feat: admission hardening + poster-side CLI completeness
ef55ae8 test: CRD<->Go parity test — and the pruning bug it caught
b63a72d feat: benchlocal@v1 package + finetune@v1 staged (enabled:false)
7cb07a7 feat: bounty_report MCP tool — A2UI reports over the x402mcp seam
466671d feat: eval-market controller slice — commit-reveal quorum + self-bond
9af37c5 feat: evaluator enrollment + panel selection + OBOL eval-payment leg
cfce4f3 feat: ERC-8004 Validation/Reputation wiring — calldata builders + reveal provenance
…lenames in justfile
The generate target's singularization fallback turned 'servicebounties'
into 'servicebountie-crd.yaml'; add explicit case entries so controller-gen
output lands on the canonical filenames. Regenerated manifests pass the
CRD<->Go parity and admission tests unchanged.
@OisinKyne

Copy link
Copy Markdown
Contributor

We don't have any buyers with unfilled demands. What types of services do you anticipate here?

I don't think any of our buyers and sellers need an escrow and evaluator yet. I suggest leaving this unmerged until I have a better understanding of who needs this

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@bussyjd@OisinKyne