Conversation
…wn' polling
- sleep() left its AbortSignal "abort" listener attached after a normal
(non-abort) timer fire; {once: true} only clears it when abort actually
fires. Over a multi-hour hydration (one sleep() per poll, same long-lived
signal) this accumulated one listener per poll and would eventually trigger
MaxListenersExceededWarning. Now removed explicitly on normal resolution.
- hydrateFile polled forever if getCloudFileStatus kept returning "unknown"
(e.g. fswin failing to load/read), since hydrateFile intentionally has no
default timeout. Now gives up and rejects after 5 consecutive "unknown"
polls, while a transient "unknown" that recovers does not trip it.
addCustomKeys() exports every non-blacklisted file property into the IMDI <Keys> element, including the internal mediaStatsCache cache blob (probed ffprobe/ExifReader stats + size/mtime), which is bookkeeping, not archival metadata. Export the property key constant from File.ts and blacklist it. RO-Crate export was checked and does not have the same issue (it only iterates folder.metadataFile properties filtered by isCustom, never enumerates arbitrary File properties). CustomFieldsTable already excludes it too, since it also filters on isCustom.
… never blocks
Real testing against a genuine OneDrive Files-On-Demand folder showed the old
hydrateFile was broken on real placeholders: it triggered hydration with an
async fs.promises read, which throws "UNKNOWN: unknown error, read"
(errno -4094) on a real placeholder -- libuv's overlapped I/O can't satisfy the
cloud recall. The error escaped before polling even began, so
File.makeAvailableOffline() failed immediately with a cryptic message. The unit
tests missed it because they read a real *local* temp file, never an actual
placeholder.
Only a synchronous, blocking read reliably triggers the recall and blocks until
the bytes arrive -- but for a multi-GB file on a slow link that blocks for
hours, so it must never run on the renderer/UI thread. hydrateFile now runs that
read inside a worker_thread (eval Worker, no separate bundled entry):
- Reads the whole file in 4 MB chunks with fs.readSync, so completion guarantees
the file is fully local, and reports real byte progress via onProgress.
- Retries the transient cloud-recall UNKNOWN/-4094 error with exponential
backoff (6 tries) then fails cleanly, instead of crashing. A slow-but-working
download never throws (readSync just blocks), so there is still no default
timeout.
- Main thread only awaits worker messages; timeoutMs/signal terminate the worker
and reject with a timeout/AbortError.
Validated live: main thread stays responsive during the worker read (~3000
heartbeat ticks, max gap ~100ms over a 180s read); detection, timeout, abort and
the UNKNOWN-retry failure paths all behave correctly.
Adds an injectable setHydrationRunnerForTests() seam so specs don't need a real
worker; options shape is now { timeoutMs?, signal?, onProgress? } (dropped
pollIntervalMs -- there is no more attribute polling).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ckmarks; user doc - Refresh cloudStatus right after readMetadataFile()'s sync read hydrates a dehydrated metadata file, so the row stops showing the cloud icon/grey name the moment the session becomes readable (with regression test). - Comment out (not remove) the Explorer-style green checkmarks for locally-available files, per John -- may be re-enabled later. - Add readme-onedrive.md: plain-language user documentation for the OneDrive status icons, the request-file checkbox, auto-fetch setting, and offline behavior. - Locale catalogs cleaned of strings removed during the UI iterations. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add readme-images/ with four captures from the live app: the file-list status icons (online-only, downloading, local), the OneDrive Status card in its resting, Waiting, and offline states. Embed each in the matching section of readme-onedrive.md. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Extract revealInFolderLabel() so the file-list context menu and the cloud status card use the same platform-appropriate wording, and add a reveal-in- folder button to the cloud status card. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
When a cloud sync provider (OneDrive/Dropbox/Nextcloud) is down or
rate-limiting, lameta's load-time metadata reads fail: File.readMetadataFile()
does a synchronous read of each .session/.person/.meta sidecar to force
on-demand hydration, and on a broken provider that read throws
(errno -4094 / code UNKNOWN). Previously each failure produced two lameta
toasts plus the provider's own native modal per file, and could abort the
whole project load.
Now:
- cloudReadGuard: a per-load circuit breaker. On the first failed cloud read
it trips and skips both pinning and reading of the remaining placeholders,
so we stop hammering a broken provider (~1 provider modal instead of N).
- readMetadataFile soft-fails on a cloud read failure: record the file, mark
it cloudMetadataUnavailable, no per-file toast, and don't throw -- the
project keeps loading. Genuine (non-cloud) file errors keep the original
notify-and-rethrow behavior.
- CloudUnavailableBanner: one persistent, dismissible banner
("couldn't download N files from <provider>") with Retry, which re-reads
just the failed files via Project.retryFailedCloudReads().
- save() refuses to overwrite a file whose real metadata we never read, so a
soft-failed placeholder can't be clobbered with empty content (and synced
back to the cloud) on the next blur/quit save.
Also: prefer-const cleanup in normalizeIncomingDateString.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
hatton
commented
Jul 10, 2026
hatton
commented
Jul 10, 2026
Member
Author
|
[Claude Opus 4.8] Consulted Devin on 2026-07-10 14:49 MDT up to commit Result: 0 bugs, 2 Investigate flags, 3 informational (skipped). The 2 Investigate flags were mirrored as review threads above:
Note: Devin reviewed the entire 13-commit |
…logs E (MediaStats.tsx): the media-stats probe called getStatsFromFileAsync().then() with no .catch(). The new cloud flow re-fires the probe when a file hydrates, so a failing ffprobe (corrupt file, unsupported codec, failed hydration) left the panel stuck on "Processing..." forever. Add a .catch() that logs and shows a "could not read media information" status instead of swallowing the rejection. Also drop a dead `eslint-disable react-hooks/exhaustive-deps` directive (the plugin is not registered in eslint.config.mjs, so it errored). F (locale/en/fields.po, vocabularies.po): these were accidentally emptied in an earlier commit. They are generated build artifacts (yarn strings:extract-json, from archive-configurations/**/*.json5), so regenerate them from the current JSON source of truth rather than restoring stale content: 118 field strings and 49 vocabulary strings. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Implement the macOS side of cloud-sync support and harden the whole
feature against the boundary conditions cloud placeholders introduce.
macOS provider (cloudFileStatus.ts):
- MacCloudFileProvider detects dataless placeholders (size>0, blocks==0)
under a sync root; one-shot materialization via brctl (iCloud) or a
reader child process (FileProvider). capabilities gains canFetch
(a real provider exists) distinct from canPin (durable pin; Windows
only). Sync-root discovery from ~/Library/CloudStorage/*, home-dir
symlink aliases, and iCloud Drive incl. Desktop & Documents sync.
- Path compares fold to NFC so decomposed macOS names still match.
- macOS Download-button UI (no durable pin), disabled while offline;
auto-fetch skipped while offline.
Load reliability & UX:
- Parallel prefetch of cloud-evicted metadata at project load, so a
fully-evicted project opens in ~seconds instead of minutes of serial
on-demand hydration (cloudMetadataPrefetch.ts).
- All project-open paths route through the async loader + modal
progress dialog ("Getting project information from <provider>...");
the trigger now also fires for cloud-evicted projects, not just large
ones, so the renderer no longer freezes on open.
- Corrupt/truncated metadata (interrupted sync) no longer risks
overwriting recoverable bytes: a failed parse sets metadataReadFailed
and blocks the save. Sync-conflict duplicate files load harmlessly.
Testing:
- FakeCloudFileProvider (E2E_FAKE_CLOUD_PROVIDER manifest) + e2e/
cloudSync.e2e.ts exercise the cloud UI on any machine, no account.
- Unit tests for the mac provider, prefetch, corrupt metadata, offline
behavior, and read-failure signatures.
- readme-cloud-testing.md: manual test plan for human testers.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Rename reliability (PatientFS): - Roll back per-file renames when the final folder rename exhausts its retry budget, so a failed rename always leaves a fully consistent old state (previously: folder kept the old name while files inside carried the new prefix, and the next load silently reverted the user's rename). - Remove the rename-out-and-back "trial run": torture testing showed it could strand the folder under the NEW name when a handle opened mid-flight blocked the rename-back. With rollback in place the precheck was redundant as well as risky; the directory is now renamed exactly once. - Drop the graceful-fs monkey-patch and dependency: its Windows rename retry only wraps the async fs.rename, and PatientFS is all-sync, so it contributed nothing. Comments now document the verified EBUSY/EPERM contention semantics. - Fix zombie metadata repair: the single-zombie case was skipped (`> 1` off-by-one) and the rename got a bare filename instead of a full path, so the repair had never worked. - Fix the .maybeLostInfoHere rescue path (Path.join misuse) and an unfinished error-dialog sentence. Vanished files must not wound the app: - New File.fileMissing soft-fail flag: saving a file whose folder was deleted/renamed outside lameta (e.g. a collaborator's change applied by OneDrive/Dropbox) now warns once and skips, instead of popping an ENOENT toast on every save trigger; self-heals if the folder returns. - Detail-pane ErrorBoundary gets resetKeys so a per-file render error recovers on selection change instead of wedging the pane until restart; selection changes survive a failed save of the outgoing folder. Never silently clobber a collaborator's edit: - File.save() now tracks each metadata file's on-disk mtime+size from read and after every write. If the file changed underneath us (another machine's sync, an external editor), the disk version is moved aside as "<name> (changed on another computer <date>).<ext>" before writing ours, with a single clear warning. Byte-identical mtime churn is ignored. This closes the verified silent-data-loss vector where B's stale in-memory save reverted A's synced-down edit with no trace. Tests: LockedFileScenarios (rollback, proven failing-without-fix), ZombieMetadataRepair, VanishedFile, ExternallyChangedFile unit specs; renameContention + vanishedSession e2e; RenameContention.stress.spec (opt-in LAMETA_STRESS torture harness with a lock-meddler process, plus real-provider mode) and twoUserSync e2e (opt-in LAMETA_EXPERIMENT two-user hazard harness). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Draft / WIP. This is the long-running
OneDrivebranch for making lameta cooperate with cloud file-on-demand sync providers (OneDrive, Dropbox, Nextcloud, …). Opened as a draft so the review bots run against the branch.Most recent preflight run focused on handling a broken/unreachable cloud provider at project load:
cloudReadGuard) so a down/rate-limiting provider is hit ~once, not once-per-file.Project.retryFailedCloudReads).save()now refuses to overwrite a file whose real metadata was never read (prevents empty-content data loss syncing back to the cloud).Plus a small pre-existing refactor already on the branch: a shared
revealInFolderLabel()and a "reveal in folder" button on the cloud status card.🤖 Generated with Claude Code