Skip to content

Model B: DIRECT messages retry until delivered (proof-wait timeout)#94

Merged
torlando-tech merged 5 commits into
mainfrom
fix/model-b-direct-delivery-proof
Jun 20, 2026
Merged

Model B: DIRECT messages retry until delivered (proof-wait timeout)#94
torlando-tech merged 5 commits into
mainfrom
fix/model-b-direct-delivery-proof

Conversation

@torlando-tech

Copy link
Copy Markdown
Owner

Problem

The opportunistic delivery-proof fix (#93) left the DIRECT path with the same latent bug: a small-packet DIRECT message was dequeued at .sent and relied solely on the in-memory proof callback, so a lost link proof — or the NE being suspended/jetsammed during the proof window — stranded it at a single checkmark. DIRECT is Columba's large-message fallback, so this had to be fixed before shipping.

Fix (LXMF-swift 72c4496, this PR bumps the pin)

Brings DIRECT to python parity (LXMRouter.py:2596-2673, LXMessage.py:471-484,613-618):

  • processOutbound's .direct case keeps the small-packet message in pendingOutbound at .sent with nextDeliveryAttempt = now + DELIVERY_RETRY_WAIT (full-record persist). While awaiting the proof it's skipped by shouldAttemptDelivery (no duplicate during the wait — matches python's "waiting for proof"). When the window elapses and it's still .sent, it tears down the link (closeAndRemoveDeliveryLinkLink.close(.timeout) + transport.unregisterLink), reverts .sent.outbound, and re-sends over a fresh link — mirroring python's __link_packet_timed_out teardown + re-establish. Removed only on .delivered or MAX_DELIVERY_ATTEMPTS.
  • loadPendingOutbound now reloads DIRECT .sent (not just opportunistic), so a proof missed during NE jetsam recovers on relaunch. Still excludes PROPAGATED .sent (terminal); DIRECT RESOURCE persists .outbound so it's never double-handled.
  • Post-send writeback is guarded on state != .delivered in both the DIRECT and opportunistic branches, so a proof landing during the send await isn't clobbered back to .sent.

Design: pure LXMF-swift, no reticulum-swift change. reticulum-swift has no set_timeout_callback primitive and RNS never retransmits link DATA — so python's DIRECT re-send is itself poll-driven by process_outbound; the swift poll is faithful, and a transport callback wouldn't survive NE suspension anyway. Two intentional divergences (no timeout-callback primitive; rtt*6 collapsed into DELIVERY_RETRY_WAIT) documented in port-deviations.md. Stricter-parity follow-ups (rtt-based fast dead-link detection, Link.setCloseCallback early-close) tracked on LXMF-swift issue #10.

Verification

  • Unit (executes production code): new testLoadPendingOutboundReloadScoping pins the reload filter — .outbound + OPPORTUNISTIC/DIRECT .sent reload, PROPAGATED .sent does not. All 35 router/delivery tests pass.
  • Device (iPhone 14, Model B): direct_echo smoke scenario passes — device sends DIRECT → Mac echo bot round-trips → device processes the delivery proof (delivery confirmed) and reaches .delivered within the proof-wait window (no spurious retry); NE boots clean, no crash.

🤖 Generated with Claude Code

Picks up the DIRECT small-packet delivery-proof fix: DIRECT messages now keep in
pendingOutbound at .sent and retry (link teardown + revert + fresh re-send) until
the proof advances them to .delivered or MAX_DELIVERY_ATTEMPTS, matching python
__link_packet_timed_out; DIRECT .sent reloads on NE relaunch. Closes the gap left
by the opportunistic fix (#93).

Verified on device: direct_echo smoke passes — DIRECT send round-trips and the
device processes the delivery proof (delivery confirmed); 35 LXMF-swift
router/delivery unit tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@greptile-apps

greptile-apps Bot commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR promotes the LXMF-swift dependency from the feat/lxmfdb-appgroup-sharing feature branch to main and advances the locked revision to 60186710, which carries the DIRECT-message retry/proof-wait implementation described in the PR. No application source files are changed — all logic lives in the upstream package.

  • project.pbxproj: SPM reference updated from branch = "feat/lxmfdb-appgroup-sharing" to branch = main; kind = branch is unchanged.
  • Package.resolved: Revision bumped from b2611b38 to 60186710; this is the commit that adds pendingOutbound persistence for DIRECT .sent messages and the proof-wait teardown/retry loop.

Confidence Score: 5/5

Safe to merge — the change is limited to promoting a tested feature branch into main and pinning the resulting commit in Package.resolved; no application source is modified.

Both changed files are Xcode project metadata. The Package.resolved commit-pins the specific LXMF-swift revision that carries the new DIRECT retry logic, and the PR description documents thorough unit and device verification. The only open question is long-term drift risk from tracking a branch instead of a tag, but the current build is well-defined by the pinned revision.

No files require special attention. Both files are Xcode dependency metadata and carry no executable logic themselves.

Important Files Changed

Filename Overview
Columba.xcodeproj/project.pbxproj Switches LXMF-swift SPM reference from feature branch to main; syntactically valid pbxproj change.
Columba.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved Resolves LXMF-swift to revision 60186710 on main; commit-pins the new code that adds DIRECT retry/proof-wait logic.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant App as Columba NE
    participant Router as LXMRouter
    participant Dest as Destination

    App->>Router: send DIRECT message
    Router->>Dest: establish link + send packet
    Router->>Router: "state = sent, nextDeliveryAttempt = now + RETRY_WAIT"

    alt Proof received within window
        Dest-->>Router: delivery proof callback
        Router->>Router: "state = delivered, remove from pendingOutbound"
    else Proof window elapses
        Router->>Router: shouldAttemptDelivery true
        Router->>Dest: closeAndRemoveDeliveryLink
        Router->>Router: state sent to outbound
        Router->>Dest: fresh link + re-send
        Note over Router,Dest: Repeat until delivered or MAX_DELIVERY_ATTEMPTS
    end

    Note over App,Router: loadPendingOutbound reloads DIRECT sent on relaunch
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant App as Columba NE
    participant Router as LXMRouter
    participant Dest as Destination

    App->>Router: send DIRECT message
    Router->>Dest: establish link + send packet
    Router->>Router: "state = sent, nextDeliveryAttempt = now + RETRY_WAIT"

    alt Proof received within window
        Dest-->>Router: delivery proof callback
        Router->>Router: "state = delivered, remove from pendingOutbound"
    else Proof window elapses
        Router->>Router: shouldAttemptDelivery true
        Router->>Dest: closeAndRemoveDeliveryLink
        Router->>Router: state sent to outbound
        Router->>Dest: fresh link + re-send
        Note over Router,Dest: Repeat until delivered or MAX_DELIVERY_ATTEMPTS
    end

    Note over App,Router: loadPendingOutbound reloads DIRECT sent on relaunch
Loading

Reviews (5): Last reviewed commit: "Bump LXMF-swift pin → 6018671 (issue #10..." | Re-trigger Greptile

@codecov

codecov Bot commented Jun 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

torlando-agent Bot and others added 4 commits June 20, 2026 00:40
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…#9 5/5)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The feat/lxmfdb-appgroup-sharing branch was deleted on merge; pin the
XCRemoteSwiftPackageReference requirement + Package.resolved to main @ 1f2bb31 so a
fresh resolve doesn't reference a missing branch ref.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… reaction)

PR #11 merged to LXMF-swift main. Device-verified: direct_echo + direct_attachment_echo
pass on the merged build (no regression from the Link.setCloseCallback wiring).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@torlando-tech torlando-tech merged commit 9484757 into main Jun 20, 2026
3 checks passed
@torlando-tech torlando-tech deleted the fix/model-b-direct-delivery-proof branch June 20, 2026 16:32
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