101 lines
7.5 KiB
Markdown
101 lines
7.5 KiB
Markdown
|
|
# Frontend recovery implementation review
|
|||
|
|
|
|||
|
|
Codex, 2026-09-25. Static source inspection at pinned commits, not runtime or fault
|
|||
|
|
injection. Selection: two independently developed chat frontends with inspectable
|
|||
|
|
draft and retry code. Chat sends broaden evidence for proposal lifecycles; they do
|
|||
|
|
not validate transactional approval, version checking or offline note durability.
|
|||
|
|
Exact file hashes and URLs: [source manifest](FrontendRecoverySources.json).
|
|||
|
|
|
|||
|
|
## Revisions and independence
|
|||
|
|
|
|||
|
|
- SRC-0013 Zulip: `5b06fa3d34f28fa01f459fbf3ba053e3c0858e9c`.
|
|||
|
|
- SRC-0014 Element Web: `60b54fc8446ad1a88963660927cd7e1865905e63`.
|
|||
|
|
- SRC-0015 Matrix JS SDK: `c0cf1015980b48a6f1332701cd731740d3f58272`.
|
|||
|
|
- SRC-0016 [Matrix client-server specification v1.15](https://spec.matrix.org/v1.15/client-server-api/#transaction-identifiers), Transaction identifiers; accessed 2026-09-25.
|
|||
|
|
|
|||
|
|
Element's [package declaration](https://github.com/element-hq/element-web/blob/60b54fc8446ad1a88963660927cd7e1865905e63/apps/web/package.json#L84)
|
|||
|
|
references SDK develop. The separately pinned SDK is an inspected mechanism snapshot,
|
|||
|
|
not a verified lockfile resolution for this Element build. Element and its SDK count
|
|||
|
|
as one implementation family, never two independent uses. No production release or
|
|||
|
|
installed behavior is inferred from repository HEAD.
|
|||
|
|
|
|||
|
|
## Located observations
|
|||
|
|
|
|||
|
|
**R01 — Zulip drafts.** [compose_actions.hide_box](https://github.com/zulip/zulip/blob/5b06fa3d34f28fa01f459fbf3ba053e3c0858e9c/web/src/compose_actions.ts#L90)
|
|||
|
|
saves the draft before hiding composition. [draft storage](https://github.com/zulip/zulip/blob/5b06fa3d34f28fa01f459fbf3ba053e3c0858e9c/web/src/drafts.ts#L207)
|
|||
|
|
writes through its local-storage wrapper; [restore_message](https://github.com/zulip/zulip/blob/5b06fa3d34f28fa01f459fbf3ba053e3c0858e9c/web/src/drafts.ts#L388)
|
|||
|
|
reconstructs compose arguments. This supports separating unsent intent from sent
|
|||
|
|
messages. It does not prove crash durability or base/draft/current merge behavior.
|
|||
|
|
|
|||
|
|
**R02 — Zulip failed send and later evidence.** [resend_message](https://github.com/zulip/zulip/blob/5b06fa3d34f28fa01f459fbf3ba053e3c0858e9c/web/src/echo.ts#L162)
|
|||
|
|
retains content, marks a resend, snapshots the request and submits again. Its
|
|||
|
|
[event handling](https://github.com/zulip/zulip/blob/5b06fa3d34f28fa01f459fbf3ba053e3c0858e9c/web/src/echo.ts#L540) matches local IDs, replaces temporary identity,
|
|||
|
|
and can clear a failure indication when the server event arrives. The
|
|||
|
|
[error path](https://github.com/zulip/zulip/blob/5b06fa3d34f28fa01f459fbf3ba053e3c0858e9c/web/src/echo.ts#L641) sets failed_request; this client flag is not a proof
|
|||
|
|
of server non-commit. [transmit](https://github.com/zulip/zulip/blob/5b06fa3d34f28fa01f459fbf3ba053e3c0858e9c/web/src/transmit.ts#L33) distinguishes acknowledgement
|
|||
|
|
from later event receipt and restarts event polling if an acknowledged event is late.
|
|||
|
|
These paths support asynchronous reconciliation, not a proven server deduplication
|
|||
|
|
contract. No claim that Zulip duplicates messages or guarantees duplicate prevention
|
|||
|
|
follows from these selected files.
|
|||
|
|
|
|||
|
|
**R03 — Element drafts and handoff.** [SendMessageComposer](https://github.com/element-hq/element-web/blob/60b54fc8446ad1a88963660927cd7e1865905e63/apps/web/src/components/views/rooms/SendMessageComposer.tsx#L514)
|
|||
|
|
saves/restores editor state with a room/thread key using localStorage; unmount saves
|
|||
|
|
state. Its [send path](https://github.com/element-hq/element-web/blob/60b54fc8446ad1a88963660927cd7e1865905e63/apps/web/src/components/views/rooms/SendMessageComposer.tsx#L479)
|
|||
|
|
hands content to sendMessage and clears reply context while retry is delegated to
|
|||
|
|
the queued message. Retaining recoverable intent need not mean retaining composer
|
|||
|
|
text. Storage errors, crash windows and complete queue persistence were not tested.
|
|||
|
|
|
|||
|
|
**R04 — Element retry entry.** [Resend](https://github.com/element-hq/element-web/blob/60b54fc8446ad1a88963660927cd7e1865905e63/apps/web/src/Resend.ts#L16) selects NOT_SENT pending
|
|||
|
|
events and passes the existing event to client.resendEvent. Its success branch
|
|||
|
|
announces message_sent; its failure branch logs the failure. This is a real frontend
|
|||
|
|
retry entry, but says nothing by itself about authoritative rejection.
|
|||
|
|
|
|||
|
|
**R05 — SDK identity and transport outcome.** [resendEvent](https://github.com/matrix-org/matrix-js-sdk/blob/c0cf1015980b48a6f1332701cd731740d3f58272/src/client.ts#L2528)
|
|||
|
|
reuses the event and changes its local status. [sendEventHttpRequest](https://github.com/matrix-org/matrix-js-sdk/blob/c0cf1015980b48a6f1332701cd731740d3f58272/src/client.ts#L3120)
|
|||
|
|
uses its existing transaction ID or assigns one, then places it in the ordinary
|
|||
|
|
room-event PUT path. State-event paths differ: do not generalize this ID behavior to
|
|||
|
|
all writes. The [send catch](https://github.com/matrix-org/matrix-js-sdk/blob/c0cf1015980b48a6f1332701cd731740d3f58272/src/client.ts#L3004) sets NOT_SENT after an error;
|
|||
|
|
that label alone cannot distinguish rejection from a lost response.
|
|||
|
|
[Room remote-echo handling](https://github.com/matrix-org/matrix-js-sdk/blob/c0cf1015980b48a6f1332701cd731740d3f58272/src/models/room.ts#L2916) merges the remote event into
|
|||
|
|
the local event and removes transaction tracking. The SDK snapshot supports these
|
|||
|
|
mechanisms, not the end-to-end correctness of a particular deployed client/server.
|
|||
|
|
|
|||
|
|
**R06 — Protocol contract.** Matrix v1.15 specifies that retransmissions with matching
|
|||
|
|
transaction identity and request path should return the original response. Scope is
|
|||
|
|
device and endpoint; a new device changes that scope. This supplies a protocol
|
|||
|
|
basis for ordinary event retries, distinct from local-echo matching. It does not
|
|||
|
|
establish a tested server implementation, indefinite result retention, payload-change
|
|||
|
|
rules for our approval application, or full frontend recovery after restart.
|
|||
|
|
|
|||
|
|
## Synthesis and candidate decisions
|
|||
|
|
|
|||
|
|
Local Draft State has two independent partial code uses (R01/R03) for unsent intent
|
|||
|
|
separation. Neither implements the full base/draft/current contract of VC-01 in the
|
|||
|
|
inspected paths. Keep hypothesis maturity and separate core-mechanism recurrence from
|
|||
|
|
complete-pattern recurrence.
|
|||
|
|
|
|||
|
|
Mutation Outcome Tracking has two partial recovery uses (R02/R04–R05). Neither proves
|
|||
|
|
an explicit four-state model with unknown separated from rejected. Retain it as a
|
|||
|
|
proposed review model for now, not an established implementation taxonomy. Add a
|
|||
|
|
rule: preserve intent through a defined composer-to-pending handoff; classify states
|
|||
|
|
by evidence rather than names in an enum. Idempotency, correlation and acceptance
|
|||
|
|
must each have their own evidence.
|
|||
|
|
|
|||
|
|
No new pattern is needed. Version-Checked Mutation, Local Commit Boundary and offline
|
|||
|
|
reconciliation gain no direct implementation confirmation here. Optimistic display
|
|||
|
|
is visible in the inspected messaging mechanisms, but approval-specific safety and
|
|||
|
|
independent full-pattern review remain missing; its standalone draft stays deferred.
|
|||
|
|
|
|||
|
|
## Review boundary and next experiment
|
|||
|
|
|
|||
|
|
A second-model critique of frozen walkthroughs ran through llm-connect; see
|
|||
|
|
[its editorial disposition](RecoveryWalkthroughReview.md). It is a separate model
|
|||
|
|
opinion, not independent human review, runtime evidence or a controlled usefulness
|
|||
|
|
comparison. All original inputs and outputs are retained.
|
|||
|
|
|
|||
|
|
Next under FEP-WP-0002 T02: choose one exact client/SDK/server combination and replay
|
|||
|
|
acceptance-with-lost-response plus delayed echo, checking operation identity and
|
|||
|
|
content preservation across retry. Under T03: compare blinded, matched baseline and
|
|||
|
|
pattern-guided decisions on new variants with an independent reviewer. The present
|
|||
|
|
self-authored cases cannot establish that names improve decisions.
|