refactor(mobile): make outbox ownership checks explicit - #10107
Conversation
Created with GPT-6 Astra in Codex.
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — This is a focused mobile outbox persistence refactor that makes partial-load ownership explicit while preserving readable messages and blocking unsafe cleanup or account transitions. The production logic is localized, persisted formats and defaults are unchanged, and targeted tests cover the new failure paths. You can add or adjust custom eligibility rules. Learn more. |
Thread transfer impact✅ Thread transfer remains within every enforced ceiling.
Baseline: Scenario and decoded snapshot size10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed. |
|
Note 🤖 Claude Fable 5.1 responding on behalf of Theo Closing. On main, thread-outbox-manager load() already returns true only for a complete load, and every caller in use-composer-drafts.ts and use-thread-outbox-drain.ts already treats false as "do not clean up or change accounting". The storage directory read is all-or-nothing, so the new incomplete-with-recovered-messages path never carries messages. This is a type reshuffle with no behavior change on the mobile persistence path. |
The outbox load API hid partial recovery behind a boolean. Cleanup and account changes had to interpret that result separately.
Storage now reports readable messages and whether ownership is complete. Cleanup, sign-out archives, account restore, and environment removal require complete ownership. Readable messages stay available. Failed account changes keep the load error as their cause. Draft flushing owns hydration before writes.
The saved formats and image writer are unchanged. The file-backed writer remains in #9727, held for a new native runtime on each platform with compatible embedded readers and storage guards. The source comment now states that condition.
Verification
tsc --noEmitpassed.No UI layout, native code, or runtime configuration changed. No device or browser check ran.
Created with GPT-6 Astra in Codex.
Note
Replace outbox errors-array contract with explicit complete/incomplete hydration result
errorsarray and boolean success return onThreadOutboxStorage.loadand the manager load operation with a discriminatedThreadOutboxLoadResult/ThreadOutboxHydrationResultunion carryingstatusand a single error object onincomplete.expoThreadOutboxStorage.loadno longer rejects on unreadable records or directory failures; it returns recovered messages plusincompletestatus and an error, retrying on the next call.use-composer-drafts.ts(releaseUnusedComposerAttachmentFiles,archiveCloudComposerDrafts,restoreCloudComposerDrafts) now inspect the structured outbox status and abort destructive or state-changing operations before running when hydration isincomplete, surfacing the hydration error as the thrown cause.useThreadOutboxDrainandclearEnvironmentswitch from boolean/errors checks to the newincompletestatus, triggering the unreadable-record alert and retry path and blocking environment clear respectively.ThreadOutboxStorageimplementation must adopt the newcomplete/incompleteload contract; the formererrorsarray is gone. Existing storage mocks across tests are updated to the new shape.Macroscope summarized f003089.