Skip to content

feat(trade): standalone fixed-lot Cashu token trading (credit trading prototype) - #1107

Draft
maxie-agent wants to merge 31 commits into
mainfrom
feat/credit-trade
Draft

maxie-agent wants to merge 31 commits into
mainfrom
feat/credit-trade

Conversation

@maxie-agent

@maxie-agent maxie-agent commented Oct 7, 2026 •

Copy link
Copy Markdown
Collaborator

Round 7 — final nits from the c5f06cf re-review (2026-10-09, head a0058a0)

The re-review of c5f06cf was approve-with-nits. This round closes L-a, N-a, N-b, N-c and the Info note on CI coverage. No further external review is planned.

Finding Commit Change Regression test
L-a fixed 50 s phase budgets e46458b advance_inner has one 100 s deadline. Refund work is capped at min(now + 50 s, end). The counterparty claim runs under timeout_at(end), so it inherits whatever the refund did not use. The comment names both enclosing budgets (120 s per recovery item; 60 s per inbound message, where claiming and the preimage are saved first and the next tick claims). A lab-only override scales the budgets for tests. The optional skip of the witness RPC was not taken: the partial-claim path still needs that call for the preimage. tests/round7.rs r7_slow_counterparty_claim_inherits_unused_refund_budget: slow-but-live counterparty mint (new delay_ms fault, 1.2 s per request), refund cap 4 s, deadline 30 s. The claim took ~8.4 s and still landed: claim attempt journaled, 24 sats on B, own-mint remainder refunded.
N-a N1 tested only for the first lock e46458b Test only r7_noncanonical_second_lock_rejected_before_taker_claims: asymmetric_fees(100, 0), forged second lock of 34 sats in 11 proofs. The taker stays first_locked with no {id}-claim attempt. The honest second lock (q.give = (33, 1), unlike q.request.funding) is then still accepted.
N-b N2 tests did not show the refund finishing e46458b Test only Both r6_own_mint_checkstate_{503,blackhole}_still_claims now clear the fault, advance again and assert a 112-sat own-mint balance and complete (reviewer probe P3). P4 is added as r7_own_mint_fully_dead_still_claims: every own-mint endpoint 503, claim lands, then the swap completes.
N-c README exit-1 wording a0058a0 README and SKILL: exit 1 = "command error, pre-submission refusal, or definitive terminal unpaid_released". Docs only
Info CI did not cover this crate a0058a0 New ci.yml job maxplayer-trade (fmt, clippy, default + lab tests). It installs protoc and runs, --locked against crates/maxplayer-trade/Cargo.toml: cargo fmt --check, clippy default + lab --all-targets --no-deps -- -D warnings, the default suite and the full lab suite (TRADE_LAB_SECONDS=1). rust-cache is keyed on the crate's target; permissions are contents: read. The CI job itself

Correction to earlier rounds. Before this round, no job in ci.yml built or tested crates/maxplayer-trade, because it is its own [workspace]. The "all jobs success" CI lines in Round 6 (c5f06cf) and Round 4 below were true of the root workspace only. They were not evidence for this crate. The crate evidence was the local runs. The round-6 line "default and lab clippy … exit 0" was run without -D warnings. With -D warnings, c5f06cf fails on five lint classes that were already present: collapsible_if, too_many_arguments, needless_update, cloned_ref_to_slice_refs, assertions_on_constants. The new job allows exactly those five by name. Every other lint is a hard failure. Reviewed money code was not restyled in this round.

Verification at a0058a0 (fake/loopback mints only):

  • cargo fmt --check: exit 0. Clippy default and lab with -D warnings plus the five allows: exit 0.
  • Default suite: 94 passed, 0 failed (lib 22, cli 5, e2e 6, money 16, pinned_quote_recovery 1, relays 7, review_regressions 17, round5 20).
  • Full lab suite (TRADE_LAB_SECONDS=1): 136 passed, 0 failed (lib 22, cli 5, e2e 11, money 17, pinned_quote_recovery 1, relays 7, review_regressions 46, round5 26, round7 1). r5_refund_precedes_stalled_claim and the r6 503/black-hole tests still pass.
  • Mutations ran on a disposable copy with its own CARGO_TARGET_DIR, deleted afterwards. 8/8 failed at their SAFETY: assertion (exit 101):
    • L-a: reverted to fixed per-phase slices.
    • N-a ×2: q.request.funding.* passed at the second call site; the check dropped.
    • N-b ×3 (503, black hole, P4): no refund once the swap is settling.
    • N2 rerun ×2: refund errors propagate again.
  • Post-push repeat loops at a0058a0: 3/3 rounds passed (round5 26 + round7 1 per round, 81/81, 0 failures; 236–241 s per round). The mutation runner used its own target dir, so these loops ran on uncontaminated artifacts.
  • Exact-head CI at a0058a0 (run 37958874108): all 9 jobs success, including the new maxplayer-trade (fmt, clippy, default + lab tests) (job 113916299434, 29 min). In CI that job ran default 94/0 and full lab 136/0, matching the local counts. Vercel and Vercel Preview Comments: success.

Still deferred per Bob: L3, L4, L5, the earlier nits (unchanged; see Round 6), and cleanup of the five pre-existing clippy lint classes the new CI job allows by name (collapsible_if, too_many_arguments, needless_update, cloned_ref_to_slice_refs, assertions_on_constants).

This PR stays draft; passing tests are not independent approval.


Round 6 — re-review fixes (2026-10-09, head c5f06cf)

Re-review of b3372b1 findings N1, N2, L1, L2 fixed in c5f06cf9a69a94ac3f1a634fc1b7b204674b1c72. Regressions are appended to tests/round5.rs (r6_*).

Finding Fix Regression test
N1 non-canonical sender split mint::validate now takes the quoted gross/claim_fee and requires total == gross && input_fee == claim_fee before the receiver locks or reveals anything (maker checks the taker's first lock, taker checks the maker's second lock) r6_noncanonical_sender_split_rejected_before_maker_locks: taker sends 26 sats in 11 proofs on the 100-ppk mint; maker stays quoted, writes no lock attempt
N2 own-mint NUT-07 failure skips live claim Maker tick split into maker_refund and maker_claim, each with its own 50 s budget; own-mint refundable/refund errors are logged, never propagated, so the claim always runs on the same tick r6_own_mint_checkstate_503_still_claims, r6_own_mint_checkstate_blackhole_still_claims: own-mint checkstate 503 / hung; maker still claims 24 sats and reaches settling
L1 expired unsent quote Expired quote_created withdrawal classified refused (retryable with the same invoice), not unpaid_released r6_expired_quote_created_is_refused_and_same_invoice_retries: no melt POST for the expired quote; retry with same invoice reaches done
L2 submitted withdrawal exits 1 New money::submitted_unresolved (payment-hash lookup); CLI exits 3 when a submitted, non-terminal withdrawal errors. README/SKILL/recovery docs: exit 1 is never proof a submitted withdrawal was refused r6_cli_mint_dropped_after_post_is_exit_three: mint dies after the melt POST; CLI exits 3

Test-only fake-mint faults added: reject_checkstate, blackhole_checkstate, die_after_melt. The N1 non-canonical lock is built by a helper inside the test file; production code has no switch.

Verification at the committed source:

  • cargo fmt --check, default and lab clippy (--locked --all-targets --no-deps): exit 0. (Without -D warnings; see Round 7.)
  • Default suite: 93 passed, 0 failed. Full lab suite (monolithic run): 133 passed, 0 failed.
  • Mutations (disposable copy, one at a time): all 6/6 failed at their labelled SAFETY: assertions: N1, N2 (503), N2 (black hole), H2 refund-before-claim order (rerun because N2 reworks that path), L1, L2. Receipts: round6/mutations.json, mutation-*.log under workspace .openclaw/tmp.
  • Fake/test mints only; no real wallets, real payments, Maxplayer jobs, or merges.
  • Exact-head CI at c5f06cf (run 37886904672): all 7 jobs success; Vercel and Vercel Preview Comments success. (Correction, round 7: none of these jobs built or tested crates/maxplayer-trade.)
  • Post-push repeat verification at c5f06cf: 3/3 rounds of tests/round5.rs passed, 24 tests each (72/72), zero failures (201–209 s per round).
  • Harness incident, disclosed: the first two loop-1 attempts each failed r6_cli_mint_dropped_after_post_is_exit_three (exit 1, not 3). Cause: the mutation runner built its disposable crate copy into the shared target/ directory, and the L2-mutant maxplayer-trade binary/artifacts were left there as fresh. In 20 isolated runs from a separate target dir, the test passed 20/20 (exit 3). After cargo clean -p maxplayer-trade, the test passed and all three loops above passed from a clean build. The full lab gate (133/0) ran before the mutations, so it was not affected. The mutation runner now uses its own target directory. Failed-attempt logs are kept under workspace .openclaw/tmp/round6/loop1-failed*.

Deferred per Bob: L3, L4, L5 and the nits from the round-6 re-review are not addressed in this push.

This PR stays draft; passing tests are not independent approval.


Round-four scope closeout (evidence bb7b81e)

REQUEST-CHANGES: cashu-rust-dev reviewed 1c68714 and returned H1, H2, M1–M4 and additional findings. Round 5 (b3372b1) addressed them; the round-6 re-review findings are addressed in c5f06cf (see Round 6 above). This PR stays draft; passing tests are not independent approval.

Early-push disclosure: at Bob's request, 19299727e5e25479977cd95dee86a45a16bb3821 was pushed before the loops, stress run and automatic refund rerun finished.

  • Final implementation verification: 74 default / 109 lab tests passed; fmt and both clippy checks exited 0.
  • 20 rounds: 80/80 suite runs, 1,040 tests, zero failures. All six safety mutations failed as intended and restored controls passed.
  • Final-binary fake trade/sell-back completed with independent three-relay readback. Detached maker serve refunded automatically (no manual maker recover); taker recovered after long+margin. Both audited refunded, 128→126 fake sats each.
  • Stress is not yet fully proven: seven completed executable entries exited 0; the eighth review-regression suite was still running at evidence capture. Existing runner left untouched. Do not interpret 7/7 recorded entries as the full suite completing.
  • This docs-only commit changes only evidence paths; no source, tests, README, skills or real wallets were touched. Current-head CI/Vercel is not yet certified by this closeout.

Redacted REPORT · Complete CLI/state handoff

Earlier body below is historical evidence; current review blockers and the scope closeout above take precedence.


Standalone Cashu HTLC trading — round 4, final-review candidate

Draft, MakePrisms-owned feat/credit-trade; do not merge. Author-led verification,
not independent reviewer approval. Only crates/maxplayer-trade changes. No Maxplayer
jobs, production relay writes, core/CLI edits or new real funding.

Head: 9dad8e62669468492f997b4cb44fabe2b26ba8e1.
Round-four comparison.
Full redacted evidence and per-mint verdicts.

Per-finding history and changes

Finding / change Current disposition and evidence
Original C1/C2 and H1–H3 Hostile-witness admission/sanitization, partial claim, late maker claim, failed-claim fairness and canonical hash fixes retained; named regressions and historical safety mutations documented in README.
Original M1–M3 and L1–L5 Notice fallback, exact journaled outputs/DLEQ, terminal taker policy, deadlines/fee validation/preflight/cancellation/clock checks retained; full review suites rerun.
Round-two N1/N2 Fresh restore→state→restore evidence, pending/ambiguous fail-closed handling and last-moment send deadlines retained.
Round-two N3/N4 Unforwardable locks remain refundable; refund race/preimage persistence and exact-output reconciliation retained.
Round-three §2.1 Settlement errors cannot skip timed refunds; explicit refund/claim quarantine requires exact commit evidence, never credits invalid proofs; both-role probes retained.
Round-three §2.2 / §2.3 NUT-07 advertisement still explicitly does not prove witnesses; actual live refund evidence now added. Late server-processing window remains a documented limit, not claimed fixed.
Real-money work Cherry-picked capped test-only opt-in and fail-closed withdrawal onto round-three state handling. Default fence unchanged; exact URL plus environment required; 500 per real lock and cumulative funding/mint/home.
Relay rate limits Measured old unchanged-event amplification; durable positive receipts suppress resends, bounded exponential backoff+jitter, relay-wide rate-limit cooldown and blocked/banned gate.
Publish safety At least one recorded positive ACK required for admission; missing ACK cannot authorize money progression. Already-committed mint effects remain journaled; all-relays-down locked-trade test refunds both roles.
Relay defaults nos.lol, relay.primal.net, offchain.pub passed fresh-key ACK/live/independent ≥60s stored readback for 3410/3411/23412. Ditto/Wellorder failed 23412 storage; Nostr Band failed all.
Cleanup Money/journal panic unwraps replaced with retained-state errors; historical docs labeled; exact withdraw help and redacted witness audit covered.

Final verification

Suite Default Lab
Library 22 22
CLI 5 5
Full trade/recovery 6 11
Funding/withdrawal 12 13
Pinned quote reproducer 1 1
Relays 7 7
Review regressions 13 41
Passed, zero failures 66 100

20/20 complete rounds passed: 860 test executions, 80 distinct suite invocations, zero
failures and no isolated reruns.
Per round: 2 full trade/sell-back variants, 21 N-series/
probe/R4, 13 money and 7 relay tests. All used --test-threads=1; first five rounds serialized,
then an uninterrupted suite checkpoint and two CPU-isolated lanes. Same binaries/timings.

  • Full lab suite under deliberate CPU contention: 100/100, no failures.
  • Three disposable mutations compiled and failed at the intended safety assertions:
    missing-ACK money state; withdrawal restore/change retention; default dual real-mint fence.
    All restored controls passed.
  • Fmt passed. Default/lab clippy exited 0 with non-blocking style warnings, not warning-free.
  • Root CI does not exercise this independent workspace; the local evidence is separate.

Final default-binary live results

Production timings 3600/900/180/60 verified in actual quotes. Fake and real refund scenarios
ran concurrently. Both takers were killed after validating the second lock, with incoming
proofs persisted and no claim authorization; no timing override or recovery improvisation.

  • Fake devkit↔space: full trade + sell-back complete; lot/available/sold independently
    read on all three new defaults. Both subsequent timed refunds succeeded. Final fake
    balances: maker 115 devkit/6 space; taker 6 devkit/115 space. 256 issued−14 fees=242 retained.
  • Real Macadamia↔cashu.cz: existing homes only; both timed refunds succeeded.
    Maker Macadamia 116→114; taker cashu.cz 104→104; 2 real sats in fees.
  • Nutshell/0.21.0 refund witness: cashu.cz 2/2 outgoing proofs SPENT; JSON-string HTLC
    witnesses with preimage empty and one signature each. No missing/invalid/PENDING/UNSPENT
    proof. Secret material and signatures redacted; raw-wire and pinned-parser audits agree.
  • The real recover harness timed out because the old fenced Minibits withdrawal remained
    non-terminal after the new swap refunded. Independent read-only audit verified success;
    the original timeout and reconciled outcome are both retained, not hidden.

Final real sat accounting and sweep

Minibits returned at 18:21 UTC. The original withdrawal
3c1baf7b-c5cd-4577-b499-7f7ca1a636ef was inspected UNPAID and resumed with its exact
invoice to unpaid_released, zero inputs/debit. Its original journal row is preserved.

Five completed sweeps returned 257 sats to the explicitly selected Minibits wallet:
29 Minibits, 2+110 Macadamia, 18+98 cashu.cz. Sweep fees: 2 mint + 8 Lightning=10 sats.
Every debit, exact change and receiver credit was checked. Both Macadamia and Nutshell
withdrawals are now live-verified, not merely lab-covered.

An initial 21-sat cashu.cz invoice was refused before inputs/POST because that mint's reserve
was 5, not 2. The queue paused; the original authorization was retained until natural expiry,
then inspected UNPAID and reconciled unpaid_released. Only afterward were new 18/98-sat
plans authorized. No reserve relaxation, manual journal edit or silent replacement.

Home Minibits Macadamia cashu.cz
pair1-maker 3 2 0
pair1-taker 3 2 0
pair2-maker 3 0 3
pair2-taker 3 0 3

Designated wallet:9125; retained homes:22; confirmed cumulative fees:22
(10 prior +2 round-four refund +10 sweeps). 9169=9125+22+22, no unexplained sats.
The 22 retained sats are tool-constrained dust under observed reserves/positive-change
rules, not burned value. All homes and naturally expired authorizations remain preserved.

All real-home authorizations are terminal. Final read-only NUT-07 audit confirmed all
retained home proofs and all 9125 designated-wallet sats UNSPENT, zero locally held proofs.
Public accounting excludes unrelated wallet mints, which this work did not use.

Reviewer focus and known limits

Receipt-gated admission versus actual mint commits; durable retry budgets; withdrawal exact
change/reservation ordering; quarantine/settlement integration; fresh refund evidence and
missing-witness holds. No withdrawal-cancel command exists: an unaffordable unsent quote
can require waiting for expiry. Live Minibits HTLC refund, 24-hour relay retention, every
crash/power-loss boundary, pre-fix journal migration, malicious issuer behavior, key rotation,
adversarial fee changes and late server processing remain unproven. Offchain missed some
live ACKs despite later readback; the cause is unverified. Not production certification.

CI/Vercel green on this exact head (root workspace only; corrected in round 7: no job covered crates/maxplayer-trade). All eight CI jobs passed; the sole background watcher exited 0. Vercel and Vercel Preview Comments passed. Head, MakePrisms ownership and draft state were read back together with every successful check.

Round 5 — final-review fixes (2026-10-09)

Commit: b3372b18b4016d89a31a2dea159df7aa9f8d7c88 (ordinary push atop round-four evidence commit bb7b81e; evidence files unchanged). PR remains draft. All mappings below refer to this commit; tests are in crates/maxplayer-trade/tests/round5.rs unless qualified.

Finding Fix / regression
H1 Pinned sender-funded claim fee equality in both claim paths; caps enforced at admission. r5_pinned_sender_fee_claims_even_with_legacy_receiver_cap, r5_probe_maker_cap_rejects_before_quote_or_lock, r5_taker_incoming_fee_cap_before_acceptance
H2 Bounded message handling and CDK calls; own-mint refund before counterparty claim. r5_refund_precedes_stalled_claim, r5_detached_serve_stalled_mint_and_info_less_refund
M1 Invalid/lost quote without reserved inputs becomes terminal refused; same invoice retry allowed. r5_probe_reserve_refusal_terminal_and_same_invoice_retry, r5_lost_quote_and_near_expiry_are_terminal_without_inputs
Reserve / max-debit Ceiling max(32 sat, ceil(2% invoice)); total debit bound. r5_hundred_thousand_at_two_percent_and_max_debit (100,000 sat at 2% accepted), reserve refusal test above
M2 Numeric NUT 4xx final replies; identical journaled request replay for ambiguous replies; >60-second first-POST margin. r5_nut_error_final_and_proxy_failure_replays_identical_request, lost/near-expiry test above
M3 Only explicit withdraw can advance QuoteCreated; passive recovery cannot authorize payment. r5_recover_never_authorizes_quote_created (no POST, no inputs, unchanged balance asserted before return-value check)
M4 Quote requires requested state; terminal swaps immutable. r5_probe_late_quote_never_resurrects_expired_taker
M5 / S5 Intentionally dropped per Bob: no mint rating, verification gate, witness-verified flag or refuse-to-list flag. README/skill explicitly explain mint witness dependency and user responsibility for mint choice.
L1 / L4 Unpaid funding expiry and issuance of paid quote without fresh-exposure preflight; retained keyset/DLEQ validation. r5_expired_unpaid_funding_and_paid_issuance_without_preflight
L2 Publication abandonment distinct from unresolved money; pending-only publication scan. r5_publication_exhaustion_not_unresolved_money_and_scan_pruned
L3 / 2.1 Maker known-preimage claim survives refund quarantine; taker still reaches terminal refund quarantine. r5_refund_quarantine_keeps_known_preimage_claim_live; review_regressions::probe_taker_persistent_invalid_dleq, probe_maker_persistent_invalid_dleq
L5 Unbounded inbox with per-peer rate limiting. r5_inbox_buffers_more_than_256_messages_across_peers
L6 Refund clock fallback when info unavailable. Detached stalled-mint/info-less refund test above
Exit-code nits RecoveryIncomplete=3, terminal manual recovery=4, non-final withdrawal nonzero. r5_cli_nonfinal_withdraw_is_exit_three, r5_cli_terminal_quarantine_is_exit_four
Dedupe nit Payment-hash dedupe across invoice case and mints. r5_payment_hash_dedupes_case_and_mints
Preflight nits NUT-11 plus per-command NUT-20/04/05; diagnostics to stderr. r5_withdraw_preflight_requires_nut05 and existing preflight coverage
Read-only nit Lock-free read-only status/balance. cli::balance_and_status_work_while_writer_owns_home
Diagnostic nit Retain money recovery error in diagnostic (no silent discard); recovery suites cover continuation.
S1–S4 / S6 README and repository skill/references updated: seller max-fees example, blocked/unresolved recovery, keep serve running second_locked→settling, pre-POST failed withdraw cannot later auto-pay, reserve/debit/exit codes and witness dependency. cli::skill_commands_and_flags_match_binary_help

No other findings intentionally skipped. Recovery may continue an already-posted authorization; that is explicitly distinguished from an unsubmitted failed withdrawal.

Verification receipts

  • cargo fmt --check, default/lab clippy (--locked --all-targets --no-deps) passed.
  • Default suite: 90 passed. Lab components: unit 22, CLI 5, e2e 11, money 17, pinned quote 1, relays 7; repaired review regressions 46/46, round-five 19/19. The initial full lab run had two DLEQ regressions; both were repaired and the affected full 46-test target rerun successfully. No claim of a fresh monolithic lab run after that repair.
  • Final-source M3 focused test: 1/1 passed after assertion reordering and restoring mutation source.
  • Six mutations caught at labelled SAFETY: assertions: H1, H2 refund-before-claim order, M1, M3, M4, DLEQ-refund. Disposable mutation copies only; final source rebuilt afterward. Local receipts: round5/mutations.json, mutation-*.log under workspace .openclaw/tmp.
  • Final-binary detached fake-mint refund: 1/1 passed, setsid PID=PGID=SID 3769729, alive until state=refunded, no_manual_recover=true. Audited balances: maker A=112 plus 16 reserved for the independent second lot (initial 128), maker B=0, taker A=0. Daemon deliberately SIGKILLed only after the successful refund assertion. Receipt: round5/post-mutation-detached.log.
  • Fake/test mints only; no real wallets, real payments, Maxplayer jobs, or merges.
  • Five post-push repeat rounds and exact-head CI/Vercel: pending; results will be appended after completion. No new independent reviewer sign-off claimed.

Post-push repeat verification at b3372b18b4016d89a31a2dea159df7aa9f8d7c88: 5/5 rounds passed, 19 tests each (95/95), zero failures; existing lab binary, no source changes or rebuilds during repeats.

@vercel

vercel Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

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

Project Deployment Actions Updated
maxplayer Ready Ready Preview Oct 9, 2026 4:24pm UTC

Request Review

N1: mint::validate pins the quoted lock split (total == gross, input fee ==
claim_fee) so a non-canonical sender split is rejected before the receiver
locks its own leg, instead of leaving a live claim that always fails the
pinned-fee check.

N2: split the maker tick into separately budgeted refund and claim phases
(50 s each). Own-mint NUT-07 failures in the refund phase are logged, never
propagated, so an own-mint outage or black hole cannot skip a live claim.

L1: an expired, never-submitted quote_created withdrawal is classified
Refused (retryable with the same invoice), not unpaid_released.

L2: a submitted, non-terminal withdrawal whose resolution errors exits 3
(unresolved work), never 1. Docs: exit 1 is never proof a submitted
withdrawal was refused.

Tests: tests/round5.rs r6_* (5 regressions) plus fixture faults
reject_checkstate / blackhole_checkstate / die_after_melt.
…N-b tests

L-a: replace the two fixed 50 s phase budgets in advance_inner with one 100 s
deadline. Refund work is capped at min(now+50 s, end); the counterparty claim
runs under timeout_at(end) and inherits whatever the refund did not use. The
comment now names both enclosing budgets (120 s item, 60 s message path).
Lab-only override scales the budgets for tests.

Tests:
- round7.rs r7_slow_counterparty_claim_inherits_unused_refund_budget: slow-but-live
  counterparty mint (per-request delay fault), fast refund, claim needs more than
  the refund cap but less than the deadline; SAFETY: claim journaled and lands.
- N-a: r7_noncanonical_second_lock_rejected_before_taker_claims (taker validates
  the maker's second lock against q.give; forged non-canonical split refused,
  canonical lock still accepted).
- N-b: both r6 own-mint outage tests now clear the fault and assert the swap
  reaches complete (refund postponed, not lost); P4 r7_own_mint_fully_dead_still_claims.
- partial_claim_fixture/wait_past moved to tests/support (shared with round7).
…ording (N-c)

crates/maxplayer-trade is its own cargo workspace and no CI job built or tested
it. New job maxplayer-trade installs protoc and runs, with --locked against the
crate manifest: cargo fmt --check, clippy default + lab with -D warnings (five
pre-existing lint classes allowed by name), the default suite and the full lab
suite (TRADE_LAB_SECONDS=1). rust-cache keyed on the crate's target.

N-c: README/SKILL exit 1 = command error, pre-submission refusal, or definitive
terminal unpaid_released.

This branch was successfully deployed

1 active deployment
Preview — a0058a03 Deployed Oct 9, 2026 by vercel[bot]
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