132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 1 | # Macltok timeline repair handoff |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 2 | |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 3 | ## Publication status |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 4 | |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 5 | The SDK API is published on the user fork's `macltok` bookmark at `9b9b16982dcab5dd499547bb87e121b9d0cba6b5`. It includes durable reseeding, room clear cleanup, and support for replacement snapshots in existing UI timelines. `RoomEventCache::reseed(events, prev_batch)` takes events oldest first. Reverse a backward `/messages` chunk and pass its `end` token. A missing token means the beginning of accessible history. |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 6 | |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 7 | Macltok is published on the user fork's `vapour` bookmark at `80381e06a573f253c11a8b4c89366a9aa299ca55`, with the SDK revision above pinned in its manifest and lockfile. It is based on current `vapour`, whose head had not advanced during the final fetch and rebase. Update both `Cargo.toml` and `crates/malice-worker/Cargo.toml`, then regenerate their applicable lockfiles. Keep both transports on the same published revision. |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 8 | |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 9 | The repair action restores access to recent history while the cause of the missing interval remains under investigation. It does not fix the underlying gap loss. |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 10 | |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 11 | ## Command and transport API |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 12 | |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 13 | The shared command is `Command::HistoryRepair(HistoryRepairCommand)`. Its variants are `Start { room_id, policy, budget }`, `Continue { room_id, budget }`, `Cancel { room_id }`, `StartRecent { room_id }`, `GetPolicy`, and `SetPolicy(policy)`. `Start` accepts an optional one off policy override. Omitting it uses the saved policy. |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 14 | |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 15 | The policy variants are `StartRecent`, `Bridge`, and `BridgeShortGaps { threshold_ms }`. A threshold is an integer number of milliseconds. Zero disables automatic bridging. The default policy is `StartRecent`. |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 16 | |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 17 | Serde uses externally tagged enums. A `HistoryRepairCommand` start value has this shape. The outer `Command` adds its `HistoryRepair` tag. |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 18 | |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 19 | ```json |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 20 | { |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 21 | "Start": { |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 22 | "room_id": "!room:example.org", |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 23 | "policy": { |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 24 | "BridgeShortGaps": { |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 25 | "threshold_ms": 15000 |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 26 | } |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 27 | }, |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 28 | "budget": { |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 29 | "max_pages": 10, |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 30 | "max_events": 1000, |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 31 | "max_duration_ms": 15000 |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 32 | } |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 33 | } |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 34 | } |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 35 | ``` |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 36 | |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 37 | The corresponding `ClientHandle` methods are `history_repair`, `continue_history_repair`, `cancel_history_repair`, `start_recent_history`, `history_repair_policy`, and `set_history_repair_policy`. The report separates requested policy, selected strategy, coverage duration, threshold evaluation, bridge progress, recent availability, continuity, stop reason, and failure. |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 38 | |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 39 | Repair requires an open room. A successful command response can still contain a paused report with `failure` or `stop` set. Inspect `recent_available` before announcing restored history. `Verified` means a server page chain reached the retained event anchor. `AccessibleStart` means the server reached the beginning of history visible to this account. `Unresolved` must retain the gap explanation even when recent history is available. Permission and rate limit details remain in `failure.server`, while transport rejection remains a command error. Undecryptable events use the existing timeline item representation and key recovery flow. |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 40 | |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 41 | ## Progress publication |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 42 | |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 43 | Consumers can restore the latest report from `State.repairs`, keyed by room ID. `Event::HistoryRepairChanged` carries progress. The final `Event::HistoryRepairPublished` is a hidden internal acknowledgement barrier. The mirror folds it into `State.repairs` and emits the same visible history repair update. Its acknowledgement field is skipped by serde, so transports should not expose it as application data. |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 44 | |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 45 | ## Runtime behavior and limits |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 46 | |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 47 | The initial recent fetch is independent of the existing cache pagination cursor and is capped at 50 events. The SDK reseed takes events oldest first with a cursor for normal pagination into earlier history. Each repair budget accepts 1 to 100 pages, 50 to 10000 events, and 1 to 60000 milliseconds. Defaults are 10 pages, 1000 events, and 15000 milliseconds. |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 48 | |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 49 | The account `SyncService` pauses for the bounded initial recent fetch and cache install, then resumes while bridge pages are fetched. It pauses again for a bounded final head catchup. Repair closes cached thread timelines and pinned timelines, which must be reopened afterward. |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 50 | |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 51 | Continuation staging lives in actor memory. It clears when the room closes or the worker restarts. The installed recent history remains durable, and a new repair can be started afterward. |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 52 | |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 53 | Only one repair runs per room. Cancel signals the active operation, whose original command then returns a paused report. Await that result before requesting Continue or StartRecent. StartRecent abandons staged bridging and keeps the installed recent window. Fetch budgets restart for each continuation, while staged history is capped at 10000 events. Replacement also fences earlier pagination results. A final head that cannot overlap the staged range leaves it separate and reports unavailable history rather than joining disconnected events. |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 54 | |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 55 | ## Coverage threshold limitation |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 56 | |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 57 | The sync position and `/messages` pagination cursor do not provide a trustworthy event time for the gap boundary. Receipt timestamps are also unreliable. The implementation therefore leaves `coverage_duration_ms` as `None` and `threshold_evaluated` as `false`. `BridgeShortGaps` starts at recent messages until upstream timing support can measure coverage reliably. A user can still explicitly choose `Bridge` for a repair. |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 58 | |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 59 | ## Remaining Malice work |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 60 | |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 61 | Finish the room menu action and saved repair settings. The settings need policy lookup and update, the millisecond threshold, and a one off policy override for the room action. The room action needs busy and cancel states, plus continue bridging and start recent actions when a bridge pauses or cannot finish. Extend the shared frontend transport contract, the HTTP command adapter, and the worker command adapter together. Fold repair reports into the frontend room state and preserve them in snapshots. |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 62 | |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 63 | After a normal timeline reset, restore the visible scroll anchor. Preserve the composer draft when jumping to recent history and keep the composer usable under the existing room readiness rules. Keep recent history restoration distinct from continuity repair in the result shown to the user. |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 64 | |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 65 | ## Verification |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 66 | |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 67 | Seven focused native integration tests passed for fresh cursor selection, failed fetch preservation, valid older pagination, bridge budget continuation, cancellation, all policy overlap paths, unknown coverage fallback, and mirror publication ordering. Seven focused unit tests passed for threshold boundaries, saved policy and coverage, old inbox compatibility, serde, and publication acknowledgement. The SDK live timeline regression passed with a pending local echo preserved through reseeding. The unit tests and locked IndexedDB WebAssembly check passed against the published SDK pin, with no local dependency patches. |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 68 | |
132eeceeb362 | atagen | 2026-10-25 03:34 UTC | 69 | Browser runtime, encrypted room recovery, and complete worker restart end to end verification remain for Malice integration. A page refresh is not a full worker restart. Check that the encryption identity, pending sends, and composer draft survive. Exercise the reported offline gap using persistent stores and distinguish recent access from proven continuity. Investigating discarded gap markers and adding startup, subscription, and sync diagnostics remains prevention work. Full gates were intentionally not run. |