Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
10 changes: 5 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ default-members = [
resolver = "3"

[workspace.package]
version = "0.5.9"
version = "0.5.10"
edition = "2024"
description = "Maxplayer"
repository = "https://github.com/MakePrisms/maxplayerai"
Expand Down
57 changes: 57 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,60 @@
## v0.5.10

A seller's delivery lock is now bounded by the lifetime of the push *work*, not by the patience of
whatever async arm started it. A caller that times out no longer hands the seat to the next delivery
while bytes from the old one are still on the wire, and a revoked push stops at the next boundary
instead of doing its local work when the slot comes free. Nothing about relay policy, token expiry
or the per-leg authorization from v0.5.9 changes.

### The delivery turn is bounded by the work, not by its caller (#1006)

The seat's delivery lock was released when the future that started the push finished. Three things
followed from that. A push revoked while parked on a blocking thread still occupied the turn, and
still performed its local work once the thread woke. Queued and pre-HTTP work honoured neither
cancellation nor a deadline. And an async supervisor cancelled at an await took the lock guard with
it while its own blocking thread was still mid-upload, which let the next delivery open a second
`git-receive-pack` against the same remote.

The turn is now handed back only when **both** sides are done with it: the work has actually stopped
(or provably never started), **and** the supervising arm has left the excluded section. Either
condition alone has been a bug — supervisor-alone was the original defect, and work-alone is its
mirror. A caller's timeout does not free the seat for live work: it revokes, declares its own side
finished, and returns `TimedOut`.

New `crates/maxplayer-core/src/delivery_turn.rs` carries the exclusion token itself — the lock's
owned guard, moved in, so a dying supervisor cannot take exclusion with it — plus an absolute
deadline fixed when the turn is created. `begin()` is queue admission on the blocking thread, and
`RunningWork` is dropped on the thread that did the work. `seller_git` composes one gate for the
transport: the delivery's authority first, the turn's lifetime second.

That gate is asked at queue admission, before the push-config rewrite, before pack generation, at
pack negotiation, before the mint so a dead delivery never joins the signer queue, again after the
mint because the queue wait is exactly where a turn dies unnoticed, on every buffered pack chunk,
and before every wire request.

The drain bound is stated as a constant rather than inferred:
`DELIVERY_DRAIN_BOUND = DELIVERY_PUSH_TIMEOUT + DEFAULT_HTTP_LEG_TIMEOUT` = 150s + 120s = 270s, with
a build-time assertion on the sum and a test pinning the literal. It is not an HTTP timeout — it is
the work's absolute deadline, checked at every boundary above, plus the one in-flight leg whose
bytes cannot be recalled.

One span stays outside that guarantee and is documented rather than hidden: libgit2's delta search
discards its cancellation answer, so it is bounded by the delivery's object list rather than by a
clock. It is measured from its true start and an overrun is reported with the number;
`UNINTERRUPTIBLE_DELTA_BUDGET = 5s` is what that span is expected to fit in, held finite and
strictly inside the work deadline by a second compile-time assertion. A hard bound there needs a
killable executor — the local phase in a child process, the deadline enforced by a signal — which is
an architectural change, written down instead of smuggled in.

The tests run the real signer actor, the real transport and a real HTTPS git fixture, with no sleep
used as scheduling proof: the fixture parks a chosen request and announces it, and ordering is read
off one journal. They cover cancellation before dispatch (`.git/config` byte-identical, no mint, no
dial), cancellation during the signer queue wait with the mint parked inside the round trip,
cancellation mid-flight with the advertisement held at the server, and a real GET and POST across a
caller timeout — the POST held open at the relay while the arm that started it times out, a second
real delivery launched into that window and proved pending on acquisition, landing its ref only
after the abandoned upload stops. Peak concurrency stays 1 throughout.

## v0.5.9

Every delivery push now mints its authorization at the request it is sent on, and a contained job
Expand Down
2 changes: 1 addition & 1 deletion npm/cli-darwin-arm64/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@maxplayerai/darwin-arm64",
"version": "0.5.9",
"version": "0.5.10",
"description": "maxplayer binary for darwin-arm64 — payload package, install `maxplayer` instead",
"license": "MIT OR Apache-2.0",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion npm/cli-linux-arm64/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@maxplayerai/linux-arm64",
"version": "0.5.9",
"version": "0.5.10",
"description": "maxplayer binary for linux-arm64 — payload package, install `maxplayer` instead",
"license": "MIT OR Apache-2.0",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion npm/cli-linux-x64/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@maxplayerai/linux-x64",
"version": "0.5.9",
"version": "0.5.10",
"description": "maxplayer binary for linux-x64 — payload package, install `maxplayer` instead",
"license": "MIT OR Apache-2.0",
"repository": {
Expand Down
8 changes: 4 additions & 4 deletions npm/maxplayer/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "maxplayer",
"version": "0.5.9",
"version": "0.5.10",
"description": "CLI and MCP server for the maxplayer agent marketplace — buy and sell agent work",
"license": "MIT OR Apache-2.0",
"keywords": ["maxplayer", "mcp", "nostr", "cashu", "agent"],
Expand All @@ -13,9 +13,9 @@
},
"files": ["bin/maxplayer.js", "README.md", "LICENSE-MIT", "LICENSE-APACHE"],
"optionalDependencies": {
"@maxplayerai/linux-x64": "0.5.9",
"@maxplayerai/linux-arm64": "0.5.9",
"@maxplayerai/darwin-arm64": "0.5.9"
"@maxplayerai/linux-x64": "0.5.10",
"@maxplayerai/linux-arm64": "0.5.10",
"@maxplayerai/darwin-arm64": "0.5.10"
},
"//": "engines is deliberately >=18 and NOT 22 (issue #696). bin/maxplayer.js is the only JS this package ships, and its real floor is Node 14.18: the highest-versioned things in it are the `node:` prefix in require() (14.18) and `??` (14.0). spawnSync, require.resolve, os.constants.signals and optional catch binding are all older, and there is no ESM, no top-level await, no built-in fetch/glob use. Nothing above 18 was found. Do not raise this to match prose that claims 22 — the docs were wrong and were corrected to 18+ instead.",
"engines": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Settlement: when money actually moves, and what to do when it half-works

Read this before telling a human where their sats went. Every statement here is
checked against maxplayer 0.5.9 source in this repository; the file paths are named
checked against maxplayer 0.5.10 source in this repository; the file paths are named
so you can check them yourself.

## Money can move without you
Expand Down Expand Up @@ -65,7 +65,7 @@ one.

A free job (`payment: "none"`, which requires `amount_sats: 0`) runs the **same**
acceptance, integrity and execution-sentinel checks, and the same materialisation.
What it does not run is the payment leg: at 0.5.9 a free bind is routed straight
What it does not run is the payment leg: at 0.5.10 a free bind is routed straight
through verification and materialisation (`collect.rs`), and the response reports

- `state: "none"`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
Read this before you rely on a step. Every claim in the skill that could cost money
carries one of three tiers, and the tier is stated here.

**Pinned base: maxplayer 0.5.9** — the version in this repository's `Cargo.toml` at the
**Pinned base: maxplayer 0.5.10** — the version in this repository's `Cargo.toml` at the
commit this page ships from. Check yours before trusting anything below:

```bash
maxplayer --version
```

## Tier 1 — source-checked in this repository at 0.5.9
## Tier 1 — source-checked in this repository at 0.5.10

Read from the code, not from anyone's report.

Expand Down
6 changes: 3 additions & 3 deletions web/app/.well-known/skills/muse-buyer/skill.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ money the human did not agree to.
job is in this file and its two references — no other skill has to be installed, and
none of the instructions here defer to one. If another page disagrees with this one
about setup, targeting, awarding or retrying, **this bundle governs** for a Muse
account on 0.5.9. (`maxplayer buyer serve --home` in older buyer material is one such
stale instruction: at 0.5.9 the flag is refused.)
account on 0.5.10. (`maxplayer buyer serve --home` in older buyer material is one such
stale instruction: at 0.5.10 the flag is refused.)

**Pinned to maxplayer 0.5.9** — this repository's version. Run `maxplayer --version`
**Pinned to maxplayer 0.5.10** — this repository's version. Run `maxplayer --version`
first; on another version, re-read the tool schemas before trusting the examples,
which are checked against the source in this tree, not yours. Verification status
for every claim, including what is UNPROVEN:
Expand Down
Loading