MWP-8 / #58 Spot Check — deep verification of wire protocol MVP goal-of-done
Per-claim breakdown of #58's 5-point MVP definition of done, with concrete /tmp CLI recipes against staging and cross-cutting risk analysis across MWP-1..MWP-8.
Task: Spot Check MWP — deep verification of #58's "definition of MVP done"
Background
Issue #58 — "Muse Wire Protocol MVP hardening" — lists 8 sub-tickets (MWP-1..MWP-8), all now closed with green test suites:
| Sub-ticket | Repo | Fixes | Status |
|---|---|---|---|
| MWP-1 | musehub#106 | RC-1 (gen-0 fallback corrupts fetch walk) | ✅ closed |
| MWP-2 | musehub#107 | RC-2 (_walk_commit_delta no fallback) |
✅ closed |
| MWP-3 | musehub#108 | RC-3 (job enqueue drops back-to-back pushes) | ✅ closed |
| MWP-4 | musehub#109 | RC-4 (prebuild/index ordering race) | ✅ closed |
| MWP-5 | muse#59 | RC-5 (client doesn't retry on 503) | ✅ closed |
| MWP-6 | musehub+muse | RC-6 (wire suite disabled) | ✅ closed |
| MWP-7 | muse#62 | RC-7 (#55 sibling-ref negotiation, #32 dry-run) | ✅ closed |
| MWP-8 | musehub#111 | RC-8 (repair/force-push don't bust fetch cache) | ✅ closed |
Every sub-ticket shipped with unit/integration tests that pass in isolation (commit-by-commit, phase-by-phase). What has not been independently proven is the compound claim in #58's "Goal — definition of MVP done": that a real developer, running the real CLI against real staging, in the order they'd actually use it, gets correct behavior every time — including at the seams between fixes (e.g. does MWP-8's cache invalidation interact correctly with MWP-3/4's job-ordering fix? does MWP-5's retry loop actually fire against a real 503 from staging, not a mocked one?).
This is the gap this spot-check closes. We are not re-reviewing whether each MWP's unit tests are well-written — they are. We are asking: does the system, as a whole, running as a black box against staging, satisfy the five numbered claims in #58's goal section? Only after this is true do we bring in aaronrene.
Goal — definition of MVP done (verbatim from #58)
aaronrene (or any dev) can, against staging, reliably:
muse clone <url>— get a complete, correct working tree every time, including immediately after a push (with bounded client retry on 503).muse push— upload only the true delta; never re-upload objects already on the remote via any ref; survive back-to-back pushes.muse fetch/muse pull— receive exactly the new commits/blobs and converge.- Do all of the above repeatedly with no stale clones, no phantom large uploads, no manual cache-busting.
- The wire regression suite is re-enabled and green as the proof.
Each claim below is broken into: what fixed it, what's already proven
(from the sub-ticket's own test suite), the residual gap (what unit tests
can't tell us), and the concrete /tmp CLI recipe that closes the gap
against live staging.
Claim 1 — muse clone is always complete and correct, including immediately after a push
Fixed by: MWP-1 (gen-0 authority), MWP-2 (DAG-walk fallback), MWP-5 (bounded 503 retry), MWP-8 (cache never stale after repair/force-push).
Already proven (unit/integration level):
- MWP1_14 — push→clone→push→clone E2E gate (musehub, in-process).
- MWP2_12 — fallback alone ships a complete clone even with repair patched out.
- MWP5 real-urllib E2E against a live localhost server (retry loop fires on real 503).
- EX_02 (MWP-8) — clone-after-repair E2E,
@pytest.mark.wire.
Residual gap:
- All of the above run against localhost or in-process fixtures, not staging (real network latency, real R2, real multi-second prebuild time). The 503→retry window on localhost may not exercise the same timing as staging's actual prebuild latency.
- No test proves clone correctness chained across a push→clone→push→clone cycle that also crosses a force-push or repair in the middle — i.e. the MWP-1/2 fix and the MWP-8 fix have never been exercised in the same sequence.
- No test proves clone works correctly for a brand-new repo that has never been pushed to before against staging specifically (first-ever clone, cold cache, real MISS→prebuild→retry→HIT path end to end).
/tmp recipe:
# 1a — cold clone of a never-touched repo (first MISS, real prebuild latency)
cd /tmp && rm -rf mwp-qa-1a && mkdir mwp-qa-1a && cd mwp-qa-1a
muse init --json
echo "hello" > README.md && muse code add README.md
muse commit -m "init" --agent-id claude-code --model-id claude-sonnet-4-6 --sign
muse remote add staging https://staging.musehub.ai/gabriel/mwp-qa-1a
muse push staging main --json # first push to a brand-new repo
cd /tmp && rm -rf mwp-qa-1a-clone
time muse clone https://staging.musehub.ai/gabriel/mwp-qa-1a mwp-qa-1a-clone --json
# expect: complete tree, README.md present, exit 0 — measure how long the
# 503-retry loop actually waited (proves MWP-5's bounded poll against real
# staging timing, not a mock)
# 1b — push then immediate clone (the exact MWP-1/RC-1 regression)
cd /tmp/mwp-qa-1a
echo "v2" >> README.md && muse code add README.md
muse commit -m "v2" --agent-id claude-code --model-id claude-sonnet-4-6 --sign
muse push staging main --json
cd /tmp && rm -rf mwp-qa-1b-clone
muse clone https://staging.musehub.ai/gabriel/mwp-qa-1a mwp-qa-1b-clone --json
diff /tmp/mwp-qa-1a/README.md /tmp/mwp-qa-1b-clone/README.md # must be identical, must contain "v2"
Claim 2 — muse push uploads only the true delta, never re-uploads objects reachable via any ref, survives back-to-back pushes
Fixed by: MWP-3 (job enqueue reflects latest tip), MWP-4 (prebuild/index ordering), MWP-7 (sibling-ref have-negotiation, dry-run parity).
Already proven:
- MWP3_10/11 — two-push full drain, N=10 stress partial drain (in-process job queue simulation).
- MWP4_11/12 — E2E claim loop + N=10 stress, zero
FetchNotIndexedError. - MWP-7 Phase 3 (VS) — real staging push, 17-commit dev + 1-commit main,
commits_sent=1, objects_sent=1.
Residual gap:
- MWP-3/4's stress tests simulate concurrent job claiming in-process — they
do not prove that a human issuing two real
muse pushcommands back to back (i.e. two separate CLI processes, two separate HTTP round-trips) against staging converges correctly. Real back-to-back means real race conditions in the async worker, not simulated ones. - No test proves the cross-branch dedup claim ("never re-upload objects
already on the remote via any ref") for a third sibling branch beyond the
two-branch case MWP-7 tested. If
feature-a,feature-b, anddevall share a base andfeature-bis pushed last, does it dedup against both siblings or just the most-recently-pushed one? --dry-runparity was fixed for a single scenario (MWP-7 Phase 4/5) — needs re-verification against a different topology (e.g. a rebased branch) to rule out a narrow fix.
/tmp recipe:
# 2a — literal back-to-back push (two real CLI invocations, no artificial delay)
cd /tmp/mwp-qa-1a
echo "a" >> README.md && muse code add README.md
muse commit -m "a" --agent-id claude-code --model-id claude-sonnet-4-6 --sign
muse push staging main --json &
echo "b" >> README.md && muse code add README.md # NOTE: run after push A's mpack-presign step ideally overlaps; simplest form below
wait
echo "b" >> README.md && muse code add README.md
muse commit -m "b" --agent-id claude-code --model-id claude-sonnet-4-6 --sign
muse push staging main --json # push B immediately after A returns
cd /tmp && rm -rf mwp-qa-2a-clone && muse clone https://staging.musehub.ai/gabriel/mwp-qa-1a mwp-qa-2a-clone --json
tail -3 mwp-qa-2a-clone/README.md # must show both "a" and "b"
# 2b — three-sibling-branch dedup
cd /tmp/mwp-qa-1a
muse checkout -b feature-a && echo "fa" > fa.txt && muse code add fa.txt
muse commit -m "feature a" --agent-id claude-code --model-id claude-sonnet-4-6 --sign
muse push staging feature-a --json
muse checkout main && muse checkout -b feature-b && echo "fb" > fb.txt && muse code add fb.txt
muse commit -m "feature b" --agent-id claude-code --model-id claude-sonnet-4-6 --sign
muse push staging feature-b --json --json | jq '.objects_sent' # should exclude blobs already on staging via feature-a's shared base
# 2c — dry-run parity on a rebased topology
muse rebase main --dry-run --json # compare counts to a real rebase + push
Claim 3 — muse fetch / muse pull receive exactly the new commits/blobs and converge
Fixed by: MWP-1/2 (correct generation walk), MWP-7 (sibling-ref
negotiation applies to fetch's have set too).
Already proven:
- Fetch-side coverage is implied by the same MWP-1/2 test suite (fetch and
clone share
_walk_commit_delta).
Residual gap:
- No sub-ticket wrote a dedicated fetch/pull convergence test against
staging — all direct evidence is clone-shaped (
have=[]).fetch/pullwith a non-emptyhaveset exercise a materially different code path (delta walk, not cache HIT) that has not been the subject of an explicit E2E in this campaign. pull= fetch + merge/ff — the merge/ff correctness after a fetch has never been explicitly re-tested post-MWP-8 (does apullafter a force-pushed remote branch behave correctly, or does it silently diverge?).
/tmp recipe:
# 3a — fetch convergence: two clones, one pushes, other fetches
cd /tmp && rm -rf mwp-qa-3a-x mwp-qa-3a-y
muse clone https://staging.musehub.ai/gabriel/mwp-qa-1a mwp-qa-3a-x --json
muse clone https://staging.musehub.ai/gabriel/mwp-qa-1a mwp-qa-3a-y --json
cd /tmp/mwp-qa-3a-x
echo "from-x" >> README.md && muse code add README.md
muse commit -m "from x" --agent-id claude-code --model-id claude-sonnet-4-6 --sign
muse push staging main --json
cd /tmp/mwp-qa-3a-y
muse fetch staging main --json # non-empty `have` — exercises delta walk, not cache HIT
muse log --json | jq '.commits[0].message' # should NOT yet show "from x" (fetch != merge)
muse pull staging main --json
grep "from-x" README.md # NOW should be present — proves pull = fetch + merge converges
# 3b — pull after a force-push (interaction with MWP-8)
cd /tmp/mwp-qa-1a
muse reset HEAD~1 --json # local-only rewrite, still on main — DO NOT run --hard without asking gabriel first
# (coordinate with gabriel before any reset/force-push against a shared staging repo — see Safety notes)
Claim 4 — Repeatable with no stale clones, no phantom large uploads, no manual cache-busting
Fixed by: all of MWP-1..MWP-8 in combination; MWP-8 specifically removes the last known manual-cache-bust scenario (repair).
Already proven: each sub-ticket proves its own slice is real-time
self-healing (no UPDATE musehub_fetch_mpack_cache ... needed).
Residual gap — this is the important one:
- No test runs the full loop N times in sequence (push, clone, push, clone, repair, clone, force-push, clone) and asserts zero manual intervention across the whole sequence. Each MWP proved its own trigger in isolation; nothing proves the composition.
- "No phantom large uploads" has only been checked at the byte-count level for two-branch topologies (MWP-7). A repeated-push loop (claim 4) should also confirm upload size stays flat/small across many iterations, not just correct on push #2.
/tmp recipe:
# 4a — the full repeated loop, one repo, ~10 iterations, watch for growth
cd /tmp && rm -rf mwp-qa-4a && mkdir mwp-qa-4a && cd mwp-qa-4a
muse init --json
muse remote add staging https://staging.musehub.ai/gabriel/mwp-qa-4a
for i in $(seq 1 10); do
echo "iteration $i" >> log.txt
muse code add log.txt
muse commit -m "iter $i" --agent-id claude-code --model-id claude-sonnet-4-6 --sign
push_out=$(muse push staging main --json)
echo "$push_out" | jq '{i: '"$i"', objects_sent, blobs_sent, size_bytes}'
rm -rf /tmp/mwp-qa-4a-clone-$i
muse clone https://staging.musehub.ai/gabriel/mwp-qa-4a /tmp/mwp-qa-4a-clone-$i --json
tail -1 /tmp/mwp-qa-4a-clone-$i/log.txt # must equal "iteration $i" every time, no staleness
done
# expect: objects_sent/blobs_sent stay ~1 per iteration (not growing), every clone's tail matches
Claim 5 — Wire regression suite is re-enabled and green
Fixed by: MWP-6.
Already proven: 55 tests under pytest -m wire green (47 in-process + 8
slow subprocess E2E); MWP6_00 gate enforces no re-introduction of flux-skips.
Residual gap:
- This claim is the most rigorously proven of the five — but it should be re-run right now, post-MWP-8-merge-to-main, to confirm nothing in the final merge sequence broke it. This is cheap and should be step 0 of the spot-check, not step 5.
Recipe:
cd ~/ecosystem/musehub
python3 -m pytest -m wire -q --tb=short
cd ~/ecosystem/muse
python3 -m pytest -m wire -q --tb=short
Cross-cutting risks not captured by any single MWP's test suite
These are the seams between fixes — the reason a "deeper than surface" review matters more than re-reading each ticket's own tests:
- MWP-3/4 (job ordering/idempotency) × MWP-8 (cache invalidation
enqueues its own prebuild job) —
_enqueue_repair_prebuildcalls the sameenqueue_jobthat MWP-3 hardened for push-triggered prebuilds. Has the repair-triggered enqueue path been checked against MWP-3's dedup-by-mpack_keylogic? A repair followed immediately by a push could enqueue two prebuild jobs — does MWP-3's fix correctly coalesce them, or does one get silently dropped (regressing RC-3 in a new trigger)? - MWP-1/2 (generation authority) × MWP-7 (sibling-ref dedup) — MWP-7's dedup subtracts a sibling tip's full manifest. If that sibling's own generation was ever backfilled by MWP-1's on-demand repair, does the manifest lookup still resolve correctly, or could a repaired-generation commit be mis-scoped out of a dedup calculation?
- MWP-5 (client retry) × MWP-4 (prebuild ordering) — MWP-5's bounded retry budget (120s default) was tuned against MWP-4's fixed ordering guarantee. If a repo is large enough that index+prebuild together exceed 120s, does the client fail with a clear, actionable error, or a confusing timeout?
- Real R2 vs local MinIO — several sub-tickets' "best-effort R2 delete"
paths (MWP-8's
invalidate_fetch_mpack_cache) were only tested against a mocked backend. Staging uses real Cloudflare R2. Confirm the delete call shape matches R2's actual API (auth headers, error codes on 404-already- gone) rather than the mock's simplified contract. - Concurrent agents on the same repo — aaronrene will not be the only person pushing to shared repos. No MWP ticket tested two different client machines (not just two CLI invocations from one machine) pushing to the same branch concurrently. This is the actual onboarding scenario.
Safety notes for this QA pass
- All QA repos are scratch repos under
gabriel/mwp-qa-*on staging — never reusegabriel/museorgabriel/musehubthemselves for destructive operations (force-push, reset --hard, repair-*). - Per workspace hard rules: no
--forceflag, noreset --hard, nocheckout --ours/--theirswithout gabriel's explicit go-ahead in the conversation, even inside a scratch repo — ask first if a recipe step needs one. - Every
/tmpdirectory created here is disposable; clean up with a plainrm -rfwhen done (not a muse operation, so no special permission needed). - If any staging repair endpoint needs to be exercised (Claim 1's repair× clone interaction), coordinate the exact repo/commit with gabriel before running it — repair mutates content-addressed rows in place.
Sign-off checklist before aaronrene onboards
- Claim 1 recipes (1a, 1b) run clean against staging
- Claim 2 recipes (2a, 2b, 2c) run clean against staging
- Claim 3 recipes (3a; 3b coordinated with gabriel) run clean
- Claim 4 recipe (4a, 10-iteration loop) shows flat upload size, zero staleness
- Claim 5 —
pytest -m wiregreen in both repos, run fresh today - Cross-cutting risks 1–5 above each explicitly checked or explicitly deferred with a written reason
- All scratch repos (
gabriel/mwp-qa-*) cleaned up / deleted from staging - Findings written back into this file; any new bugs filed as their own musehub/muse tickets (not silently patched)
- gabriel gives explicit go-ahead to send aaronrene the staging URL