Skip to content

feat(plugin): ship the buyer playbook as a Claude Code plugin - #938

Open
orveth wants to merge 2 commits into
mainfrom
feat/buyer-plugin-skill
Open

feat(plugin): ship the buyer playbook as a Claude Code plugin#938
orveth wants to merge 2 commits into
mainfrom
feat/buyer-plugin-skill

Conversation

@orveth

@orveth orveth commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Implements workstreams A (plugin packaging) and B (the buyer skill) from docs/superpowers/specs/2026-08-31-buyer-optimal-use-distribution.md (#936, merged). C and D are deliberately out of scope.

What lands

npm/plugin/
├── .claude-plugin/plugin.json   name: maxplayer
├── .mcp.json                    npx -y maxplayer mcp
├── README.md
└── skills/buyer/SKILL.md        the playbook — source of truth
docs/BUYER-PLAYBOOK.md           generated from SKILL.md
scripts/verify-buyer-playbook.sh generator + drift gate, wired into ci.yml

SKILL.md is the spec's Appendix 1, extracted rather than retyped. It is model-invocable, so a delegation-shaped request loads it without maxplayer vocabulary in the prompt. The plugin reuses the published launcher, so there is no second distribution of the binary.

Two corrections to the playbook

The skill instructed the agent to do one thing the tools cannot do, and to skip one thing they can. Both are fixed here and in the spec appendix, so the two copies agree:

  1. "Set a claim timeout (~10 min)." There is no claim timeout — claim_timeout appears nowhere in crates/maxplayer/src/mcp.rs. It is workstream D item 3, unbuilt. Replaced with the repost rule, which does hold.
  2. "Use the readiness/wait surface if available; otherwise poll collect." That surface already exists: get_job takes wait_for: claim|result plus timeout_secs, capped internally. The skill now names it instead of teaching the polling fallback.

The second one also narrows workstream D2, which proposes exposing a wait surface as though none is exposed. The per-job wait ships today; only the cross-job version ("block until any awarded job is ready") is missing.

The drift gate is red-proven

Two copies of the same normative text rot silently. verify-buyer-playbook.sh owns both the generator and the check, so they cannot diverge. Four failure arms, all exit non-zero, green restored after each:

  • docs page edited directly
  • skill edited without regenerating the docs page
  • docs page deleted
  • skill frontmatter destroyed (the instrument-failure path — it refuses to generate rather than emitting an empty page and passing)

Notes for review

  • Buyer home. maxplayer mcp has no --home, and this manifest sets no env, so the server uses the default ~/.maxplayer. Correct for a new buyer; operators with several homes must register the server themselves. Documented in npm/plugin/README.md.
  • Version. npx -y maxplayer resolves latest, per the spec's "no second distribution". That means a plugin user follows releases automatically — including of a binary that spends money. Flagging it as a deliberate decision to confirm, not an oversight. The plugin's own version is independent and is not a release-flow bump site.
  • The four MCP tool names were checked against mcp.rs, which AGENTS.md names as the source of truth.

🤖 Generated with Claude Code

The four MCP tools teach the mechanics of posting, awarding and collecting.
They cannot teach shape, and shape is what decides whether delegation saves
money or costs it. This puts the playbook where a new buyer gets it without
asking.

npm/plugin/ carries the manifest, an .mcp.json that spawns the published
launcher, and skills/buyer/SKILL.md. The skill is model-invocable, so a
delegation-shaped request loads it without maxplayer vocabulary in the prompt.
No second copy of the binary: npx -y maxplayer mcp.

SKILL.md is the source of truth. docs/BUYER-PLAYBOOK.md is generated from it
for hosts that speak MCP but not plugins, and verify-buyer-playbook.sh fails
CI when the two drift. The script owns the generator too, so the check cannot
diverge from what it checks.

Two lines of the playbook did not match the tools, corrected here and in the
spec appendix so the two copies agree:

- It told the agent to set a claim timeout. No such parameter exists in
  mcp.rs; it is unbuilt. Replaced with the repost rule that does hold.
- It hedged about a readiness surface "if available" and taught collect
  polling as the fallback. get_job already long-polls on wait_for=result,
  so the skill now names it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Aug 31, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
mobee Ready Ready Preview Aug 31, 2026 3:34pm

Request Review

Absolute sats were a snapshot of one relay in one week, and a model reads
a number as a target whatever label sits beside it. "Calibration, not
constants" does not stop anchoring.

What the A/B established is an ordering, not a price: plan cheap,
implementation dear, gate expensive behind cheap. That survives any price
level, so it stays. The four step headers now name their relative cost.

The prices are replaced by the loop that finds the real one, using
machinery that already exists: offer your own valuation in amount_sats,
cap it with max_sats (a claim above it is refused), read the claims that
arrive, and repost higher if none do. An unclaimed offer costs nothing.

Workstream B item 5 defined the skill as carrying a price ladder, so it
contradicted the skill as shipped; it now describes discovery instead.

Problem and Evidence keep their numbers. There a price is a record of
what one run cost, which is what evidence should be.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to 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.

1 participant