Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a0cffe-206f-7323-89d3-b20ca4cf4bf9
109 lines
8 KiB
Markdown
109 lines
8 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.
|
||
|
||
## Follow-up — source pairing and execution
|
||
|
||
The [Element lockfile](https://github.com/element-hq/element-web/blob/60b54fc8446ad1a88963660927cd7e1865905e63/pnpm-lock.yaml#L663)
|
||
resolves SDK commit c0cf1015980b48a6f1332701cd731740d3f58272, closing the earlier
|
||
source pairing gap. A [separate published SDK experiment](MatrixRecoveryExperiment.md)
|
||
now exercises recovery with a synthetic receiver. It is not the locked Element
|
||
build or a production server test. Earlier statements of static-only evidence
|
||
above describe the original inspection scope.
|