Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a0cffe-206f-7323-89d3-b20ca4cf4bf9 |
||
|---|---|---|
| .. | ||
| experiment.mjs | ||
| package-lock.json | ||
| package.json | ||
| provenance.json | ||
| README.md | ||
| result.json | ||
Matrix recovery experiment
Bounded implementation experiment, executed 2026-09-25. It runs the unmodified
published matrix-js-sdk@42.3.0 package with an injected fetch function. This tests
real SDK state transitions against a synthetic receiver, not Element UI or a
real Matrix homeserver. No messages leave the process and no inference is used.
Question: can caller-visible request failure disagree with acceptance evidence, and what happens to identity and local state on retry or early remote echo?
Hypothesis: request promises, pending-event status and authoritative event evidence are distinct. A counterexample would be a late error regressing an already reconciled event, or a retry changing the transaction identity/payload.
Reproduce
Node >=22 is required by the pinned SDK; recorded run used Node 24.11.1. From this directory, install the locked dependencies and execute:
npm ci --ignore-scripts --no-audit --no-fund
npm test
Alternatively install the same locked dependencies outside the repo, then set
FEP_MATRIX_SDK_DIR to that installation's node_modules/matrix-js-sdk directory
when invoking node experiment.mjs. The script checks the version and reports hashes
of the loaded SDK files, its own source and the dependency lock. Compare them with
result.json; the alternate path alone does not establish provenance.
Do not overwrite the recorded result with a new run; retain new evidence separately.
package-lock.json pins package integrity and transitive versions. provenance.json separates the published runtime package from the Element source/SDK pairing. The Element lockfile does match the previously inspected SDK commit, but this published package is not claimed to be that exact build.
Controls and results
| Case | Observed SDK behavior | Synthetic receiver observation |
|---|---|---|
| Accept, lose response, resend same event | NOT_SENT retains content; resend preserves transaction/path/body; echo leaves one timeline entry | Two requests, one stored acceptance |
| Fresh identity after uncertain outcome | Fresh send initially blocked by pending queue; explicit local cancellation permits a new send | Same content accepted twice under different identities |
| Echo before successful response | Pending entry reconciled once; later success does not duplicate it | One acceptance |
| Echo before transport error | Send promise rejects, but reconciled event remains non-pending with one timeline entry | One acceptance |
All four assertions passed in the recorded run. The negative control confirms that the fixture distinguishes identity reuse from replacement; it does not demonstrate a production duplication incident. Receiver deduplication is programmed into this fixture, so its correctness on a real server remains an assumption.
Automatic scheduler retries are disabled to expose the failed attempt. Remote echo is injected through Room.addLiveEvents; no real /sync loop, encryption, browser UI, storage restart, device change, authorization failure or server retention is tested. The fake response loss is a thrown transport error after fixture acceptance, not a real packet drop. No runtime conclusion about Zulip follows from this SDK experiment.
Interpretation
The strongest result is the disagreement between a rejected request promise and an already reconciled event. Treat promises as attempt results, not complete domain outcomes. Preserve operation identity and submitted content across retry. Local cancellation removes local tracking; it cannot undo an accepted remote operation.
This supports parts of Mutation Outcome Tracking. It does not prove that its exact four-state vocabulary recurs independently or improves architecture decisions. See editorial review.