Files: directory re-index invalidates an open tus destination after a sibling Note write #627

Open
opened 2026-10-01 10:53:55 +00:00 by kayg · 22 comments
Owner

The full production Calendar e2e stops at calendar.mjs:1117 when its real tus replacement of the Daily note returns 412 instead of 201:

{"error":{"code":"conflict","message":"upload destination changed"}}

This reproduces on the #549 Round 4 server (419926805), after the Composer snapshot ACK regression is fixed. The request sends no If-Match. This response comes from the tus destination guard, rather than the Journal ETag guard or Notes room epoch code. The same full Calendar failure was already recorded before Round 4.

A bounded Rust reproduction opens a tus replacement of Notes/day.md, writes an unrelated Notes/other.md, then runs index::record for Notes before its final PATCH. The parent directory inode and target bytes are unchanged. This returns 412 instead of 204. Without that re-index step, the early Round 4 parent-mtime fix passed; it did not fix the real full flow.

Source evidence: Files prepare_index_write generates a new directory item ID when the full fingerprint changes. The final upload looks up its captured parent ID, which can then be absent. A directory child write changes the directory change token. Keep stale-path and replacement protection intact when fixing this. The current FileFingerprint contains device/inode/size/mtime; it does not carry birth time, so simply retaining directory IDs by device/inode is insufficient for recreated directories.

The narrow Round 4 parent-mtime exception was reverted after this finding. No existing e2e expectation was changed. This issue tracks the remaining pre-existing Calendar fixture stop and the directory identity contract. Preserve target content/hash preconditions, grants, directory replacement rejection and follow-parent rename behavior. Add a regression with a directory re-index between tus POST and PATCH.

The full production Calendar e2e stops at calendar.mjs:1117 when its real tus replacement of the Daily note returns 412 instead of 201: ``` {"error":{"code":"conflict","message":"upload destination changed"}} ``` This reproduces on the #549 Round 4 server (419926805), after the Composer snapshot ACK regression is fixed. The request sends no If-Match. This response comes from the tus destination guard, rather than the Journal ETag guard or Notes room epoch code. The same full Calendar failure was already recorded before Round 4. A bounded Rust reproduction opens a tus replacement of Notes/day.md, writes an unrelated Notes/other.md, then runs `index::record` for Notes before its final PATCH. The parent directory inode and target bytes are unchanged. This returns 412 instead of 204. Without that re-index step, the early Round 4 parent-mtime fix passed; it did not fix the real full flow. Source evidence: Files `prepare_index_write` generates a new directory item ID when the full fingerprint changes. The final upload looks up its captured parent ID, which can then be absent. A directory child write changes the directory change token. Keep stale-path and replacement protection intact when fixing this. The current FileFingerprint contains device/inode/size/mtime; it does not carry birth time, so simply retaining directory IDs by device/inode is insufficient for recreated directories. The narrow Round 4 parent-mtime exception was reverted after this finding. No existing e2e expectation was changed. This issue tracks the remaining pre-existing Calendar fixture stop and the directory identity contract. Preserve target content/hash preconditions, grants, directory replacement rejection and follow-parent rename behavior. Add a regression with a directory re-index between tus POST and PATCH.
Author
Owner

Starting #631 and #627 on branch job/files-631, based on 687ff70313 (origin/dev). I am tracing Tags Markdown projection failures and Files directory identity changes during tus uploads, then I will add the requested regressions and run the crate gates plus the adversarial and Calendar e2e checks.

Starting #631 and #627 on branch job/files-631, based on 687ff703136e71e89f8dfba139e93cd0788b25c1 (origin/dev). I am tracing Tags Markdown projection failures and Files directory identity changes during tus uploads, then I will add the requested regressions and run the crate gates plus the adversarial and Calendar e2e checks.
Author
Owner

The identity churn is confirmed: prepare_index_write reuses a directory item ID only when every fingerprint field (including size and mtime) matches. A child-entry change therefore mints a new ID and invalidates the tus upload's captured parent ID. I am adding persisted parent-directory fingerprint evidence: same-inode directory changes retain identity only when the parent token is unchanged; a changed parent token is replacement evidence. The existing full fingerprint check remains the stale-path guard.

The identity churn is confirmed: `prepare_index_write` reuses a directory item ID only when every fingerprint field (including size and mtime) matches. A child-entry change therefore mints a new ID and invalidates the tus upload's captured parent ID. I am adding persisted parent-directory fingerprint evidence: same-inode directory changes retain identity only when the parent token is unchanged; a changed parent token is replacement evidence. The existing full fingerprint check remains the stale-path guard.
Author
Owner

Fix committed locally in 970820261. Reproduction: a tus POST captures the folder ID, a sibling file write changes the folder fingerprint, and reconcile previously minted a new ID, so PATCH rejected the upload. Directory rows now save the parent fingerprint; same-inode directories keep the ID only when that parent token is unchanged. Tests cover POST/re-index/PATCH (204), actual directory replacement (412), and simulated inode reuse with changed parent evidence (412). Migration 0019 adds the parent token columns. Full crate suite had 148 passing tests and one stale expected migration count; the focused migration test passes after updating its count to 19. Final gates and live probes remain.

Fix committed locally in 970820261. Reproduction: a tus POST captures the folder ID, a sibling file write changes the folder fingerprint, and reconcile previously minted a new ID, so PATCH rejected the upload. Directory rows now save the parent fingerprint; same-inode directories keep the ID only when that parent token is unchanged. Tests cover POST/re-index/PATCH (204), actual directory replacement (412), and simulated inode reuse with changed parent evidence (412). Migration 0019 adds the parent token columns. Full crate suite had 148 passing tests and one stale expected migration count; the focused migration test passes after updating its count to 19. Final gates and live probes remain.
Author
Owner

#627 final report

Fixed Files directory identity across child writes. Directory rows now store the fingerprint of the direct parent. If a directory's own fingerprint changes, Files preserves its ID only when device/inode still match and the saved parent fingerprint is unchanged. A changed parent fingerprint in that case is replacement evidence. This keeps tus POST/PATCH stable across re-index while retaining replacement rejection, stale-path checks, grants, target content/hash preconditions, and parent-rename behavior.

Added migration 0019 and regression tests for POST → sibling write → re-index → PATCH 204, real directory replacement → PATCH 412, and simulated inode reuse. origin/dev had migrations through 0018; the one merge attempt reported Already up to date.

Files gates passed:

    Checking calternal-plugin-files v0.0.1 (/home/kayg/Developer/calternal-wt/files-631/crates/plugins/files)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 29.70s
test result: ok. 149 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 128.66s

   Doc-tests calternal_plugin_files

running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

The cross-user matrix passed: 335 operations classified, 159 replayed, 733 A-ID comparisons, and 0 denial failures across 97 Job/Mail/quota checks.

calendar.mjs passed beyond line 1117, then failed at line 1401 in the composer snapshot assertion: the send carries the snapshot: 01:20 nFrozen snapshot. No Calendar UI code changed in this job. The #631 restore assertion also returned 200; the same probe later found the already-open #623 stale Task projection, which I reported on #623.

The local debug upload profile ran under one-minute load 26.77. It measured 50 serial uploads at p50/p95 283.08/3039.73 ms and a 16-upload burst at 5724.78/8084.86 ms, with 444096512 bytes peak RSS. The existing files.entries read baseline is 1.8/3.1 ms and is not a comparable tus-write baseline.

Head: 0122162b0126f7f7518468d1c6a3a3c54d78e26f. The final commit after gates changes documentation comments only.

## #627 final report Fixed Files directory identity across child writes. Directory rows now store the fingerprint of the direct parent. If a directory's own fingerprint changes, Files preserves its ID only when device/inode still match and the saved parent fingerprint is unchanged. A changed parent fingerprint in that case is replacement evidence. This keeps tus POST/PATCH stable across re-index while retaining replacement rejection, stale-path checks, grants, target content/hash preconditions, and parent-rename behavior. Added migration 0019 and regression tests for POST → sibling write → re-index → PATCH 204, real directory replacement → PATCH 412, and simulated inode reuse. `origin/dev` had migrations through 0018; the one merge attempt reported `Already up to date.` Files gates passed: ```text Checking calternal-plugin-files v0.0.1 (/home/kayg/Developer/calternal-wt/files-631/crates/plugins/files) Finished `dev` profile [unoptimized + debuginfo] target(s) in 29.70s ``` ```text test result: ok. 149 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 128.66s Doc-tests calternal_plugin_files running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ``` The cross-user matrix passed: 335 operations classified, 159 replayed, 733 A-ID comparisons, and 0 denial failures across 97 Job/Mail/quota checks. `calendar.mjs` passed beyond line 1117, then failed at line 1401 in the composer snapshot assertion: `the send carries the snapshot: 01:20 nFrozen snapshot`. No Calendar UI code changed in this job. The #631 restore assertion also returned 200; the same probe later found the already-open #623 stale Task projection, which I reported on #623. The local debug upload profile ran under one-minute load 26.77. It measured 50 serial uploads at p50/p95 283.08/3039.73 ms and a 16-upload burst at 5724.78/8084.86 ms, with 444096512 bytes peak RSS. The existing `files.entries` read baseline is 1.8/3.1 ms and is not a comparable tus-write baseline. Head: `0122162b0126f7f7518468d1c6a3a3c54d78e26f`. The final commit after gates changes documentation comments only.
Author
Owner

Additional #627 decision, now documented in files/src/index.rs and migration 0019: legacy directory rows have no saved parent fingerprint. If the directory's target fingerprint has changed before its first refreshed Index write, Files assigns a new ID because device/inode alone cannot prove continuity. Stable legacy rows receive the parent token on that write; later child writes preserve the ID under the parent-token rule.

Updated head: 1752147b9f782acdb94b1df1ebbeb897430a34fd. This last commit changes documentation only; the final gates still apply to the same behavior.

Additional #627 decision, now documented in `files/src/index.rs` and migration 0019: legacy directory rows have no saved parent fingerprint. If the directory's target fingerprint has changed before its first refreshed Index write, Files assigns a new ID because device/inode alone cannot prove continuity. Stable legacy rows receive the parent token on that write; later child writes preserve the ID under the parent-token rule. Updated head: `1752147b9f782acdb94b1df1ebbeb897430a34fd`. This last commit changes documentation only; the final gates still apply to the same behavior.
Author
Owner

Deep-link audit evidence for this issue: file and folder routes use /f/<item-id> in apps/web/src/routes/f/[id]/+page.svelte:2-10. The route identity is stable in the URL, but the directory ID changes after child writes as this issue records. A copied folder link can therefore stop identifying the same folder. This also breaks the CLAUDE.md Deep links rule to use stable identities that survive writes and renames. Regression idea: copy a folder link, add or rename a child, then open the old link and verify that the same folder opens.

Deep-link audit evidence for this issue: file and folder routes use `/f/<item-id>` in `apps/web/src/routes/f/[id]/+page.svelte:2-10`. The route identity is stable in the URL, but the directory ID changes after child writes as this issue records. A copied folder link can therefore stop identifying the same folder. This also breaks the CLAUDE.md Deep links rule to use stable identities that survive writes and renames. Regression idea: copy a folder link, add or rename a child, then open the old link and verify that the same folder opens.
Author
Owner

Starting #627 on job/dirid-627, base 440e19dce23040ac8ebaae88f0469b6535b1afcb. Read the issue and all six current comments. Tracing directory continuity separately from mutable content fingerprints; the prior parent-token proposal can invalidate identities on sibling changes and upgrade. No pushes or deployments. The verification policy defers full Calendar e2e and adversarial matrices to the merge round.

Starting #627 on `job/dirid-627`, base `440e19dce23040ac8ebaae88f0469b6535b1afcb`. Read the issue and all six current comments. Tracing directory continuity separately from mutable content fingerprints; the prior parent-token proposal can invalidate identities on sibling changes and upgrade. No pushes or deployments. The verification policy defers full Calendar e2e and adversarial matrices to the merge round.
Author
Owner

Finding: directory size/mtime are mutable content evidence, not continuity evidence; using the parent fingerprint also lets an unrelated sibling change invalidate identity. The implementation reads Linux STATX_BTIME from the safely opened directory and saves device/inode/birth evidence in Files migration 0019. Reads and reconciliation use the same directory identity rule; file content/hash checks retain their existing full fingerprint. Existing IDs adopt missing birth evidence on upgrade with matching device/inode. This unavoidable upgrade assumption and the conservative no-birth-time fallback are documented in DESIGN §26 and the Index module. Added router regressions for tus re-index, 100 child writes, pins, Share resolution, restart, rename/move, actual replacement, simulated inode reuse and a populated 0018 upgrade. Compiling the first focused test run now.

Finding: directory size/mtime are mutable content evidence, not continuity evidence; using the parent fingerprint also lets an unrelated sibling change invalidate identity. The implementation reads Linux STATX_BTIME from the safely opened directory and saves device/inode/birth evidence in Files migration 0019. Reads and reconciliation use the same directory identity rule; file content/hash checks retain their existing full fingerprint. Existing IDs adopt missing birth evidence on upgrade with matching device/inode. This unavoidable upgrade assumption and the conservative no-birth-time fallback are documented in DESIGN §26 and the Index module. Added router regressions for tus re-index, 100 child writes, pins, Share resolution, restart, rename/move, actual replacement, simulated inode reuse and a populated 0018 upgrade. Compiling the first focused test run now.
Author
Owner

Filesystem evidence committed in 56be70c528545a459949b17aa9d7c166c689a30e after the calternal-fs gates passed. The local filesystem provides directory birth time; the real Root regression confirms that it survives child writes and rename and changes on recreation. Gates: cargo fmt --check exited 0 with no output; calternal-fs Clippy with -D warnings passed; unit tests: 52 passed; storage integration tests: 42 passed. The Files gates are running now.

Filesystem evidence committed in `56be70c528545a459949b17aa9d7c166c689a30e` after the calternal-fs gates passed. The local filesystem provides directory birth time; the real Root regression confirms that it survives child writes and rename and changes on recreation. Gates: cargo fmt --check exited 0 with no output; calternal-fs Clippy with -D warnings passed; unit tests: 52 passed; storage integration tests: 42 passed. The Files gates are running now.
Author
Owner

Files Clippy was interrupted by shared compiler-cache infrastructure before reaching the Files crate. Verbatim error: sccache: error: Failed to create temp dir and No such file or directory (os error 2) under another job’s deleted authfix/target/tmp. No source diagnostic was reported. Bypassing the shared cache with RUSTC_WRAPPER= for this job and rerunning the interrupted Files check, followed by the one Files crate test run. The passing filesystem gates remain valid.

Files Clippy was interrupted by shared compiler-cache infrastructure before reaching the Files crate. Verbatim error: `sccache: error: Failed to create temp dir` and `No such file or directory (os error 2)` under another job’s deleted `authfix/target/tmp`. No source diagnostic was reported. Bypassing the shared cache with `RUSTC_WRAPPER=` for this job and rerunning the interrupted Files check, followed by the one Files crate test run. The passing filesystem gates remain valid.
Author
Owner

Files crate gates: Clippy passes. The suite reports 149 passed, 1 failed, 1 ignored. All four #627 regressions pass. The existing atomic-write/reconcile storm hit its unchanged 300-second deadline at lib.rs:5119 (Elapsed(())); a writer then reported entry not found at lib.rs:5093 during cancellation/cleanup. Running that one test alone once to distinguish repeatable failure from shared-host contention. No existing deadline or assertion has been changed.

Files crate gates: Clippy passes. The suite reports 149 passed, 1 failed, 1 ignored. All four #627 regressions pass. The existing atomic-write/reconcile storm hit its unchanged 300-second deadline at lib.rs:5119 (`Elapsed(())`); a writer then reported `entry not found` at lib.rs:5093 during cancellation/cleanup. Running that one test alone once to distinguish repeatable failure from shared-host contention. No existing deadline or assertion has been changed.
Author
Owner

#627 report

Built: separate directory identity from mutable content fingerprints. Persist Linux directory birth time with device/inode; use it for Index writes and live identity checks. Carry creation evidence through Trash/restore. Retain file content/hash preconditions, grants, pending namespace/install guards and follow-parent rename.

Files: crates/calternal-fs/src/{root.rs,lib.rs}; crates/plugins/files/src/{index.rs,lib.rs,tests/directory_identity.rs}; crates/plugins/files/migrations/0019_directory_birth.sql; docs/DESIGN.md §26.

Decisions: use STATX_BTIME from the same opened inode. Upgrade adopts missing creation evidence for matching device/inode and keeps existing IDs. Legacy rows cannot prove pre-upgrade inode reuse. Without filesystem birth time, retain conservative full-fingerprint validation rather than grant access to an ambiguous replacement. The two added SQL columns reduce batches to 56 rows to preserve the historical bind limit. Only the existing applied-migration maximum assertion changes from 18 to 19, because #627 adds migration 0019; no HTTP or content expectation changes.

UX gaps closed: folder Copy link resolver, sidebar pin resolver, Share access and open tus destination no longer fail on child writes on birth-time-capable filesystems. Tests cover 100 children, restart, rename/move, true replacement, simulated inode reuse and populated migration-0018 upgrade.

Known gaps / UX gaps left: filesystems without STATX_BTIME retain the conservative guard, so child changes can still invalidate folder IDs there. Legacy inode reuse before token adoption cannot be distinguished without historical creation evidence. Browser rendering is unchanged; the production browser walk remains for the merge round.

For the merge round: cd apps/web && bun run test:e2e:calendar must pass the tus Daily note replacement at calendar.mjs:1117 and complete the suite. Run tests/adversarial/run-split.sh once on the combined branch to verify XUser/authz/robustness matrices and replacement/grant isolation. Walk /f/<item-id> after 100 child writes, restart and rename and verify the real not-found state after delete/recreate. Full browser suites, adversarial matrices, release/staging/Mac checks and performance measurements were deferred under the 2026-10-02 verification policy.

Head: 3159d5d484f0fb22d7d5657b30b7414374f26255 on job/dirid-627. Fetched and merged origin/dev once (c4faf184df726a9375ae0c13bdfb6018ac2cf57e) before final gates. Migration 0019 was free at that point. Atomic commits: DESIGN contract, FS evidence, nullable schema, then Files identity and router regressions. No push, deploy or issue close.

Gate output (verbatim excerpts):

cargo fmt --check: no output, exit 0.

cargo clippy -p calternal-fs --all-targets -- -D warnings

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 19m 46s

cargo test -p calternal-fs

    Finished `test` profile [unoptimized + debuginfo] target(s) in 4m 29s
test result: ok. 52 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 115.22s
test result: ok. 42 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 52.37s
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

cargo clippy -p calternal-plugin-files --all-targets -- -D warnings

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 20m 30s

cargo test -p calternal-plugin-files -- --test-threads=2

    Finished `test` profile [unoptimized + debuginfo] target(s) in 45m 08s
test tests::directory_identity::recreated_folder_rejects_old_links_grants_and_uploads ... ok
test tests::directory_identity::tus_parent_reindex_keeps_destination ... ok
test tests::directory_identity::upgrade_adopts_directory_birth_without_changing_existing_id ... ok
test tests::directory_identity::folder_links_pins_and_shares_survive_children_restart_and_rename ... ok
writes, reconcile scans, and watcher adoption complete within five minutes: Elapsed(())
atomic write 384 failed: entry not found
test result: FAILED. 149 passed; 1 failed; 1 ignored; 0 measured; 0 filtered out; finished in 781.46s
error: test failed, to rerun pass `-p calternal-plugin-files --lib`

Gate caveat: the original Files suite is not green. Its unchanged storm test timed out at 300 seconds, then a writer reported entry not found during cancellation/cleanup. Shared-host contention is a hypothesis; the isolated retry result follows. The shared sccache also failed during an initial Clippy invocation because its temporary directory belonged to another deleted worktree; the final Clippy passed with RUSTC_WRAPPER unset. A new regression test borrow mismatch was fixed before final Clippy. Existing HTTP/content assertions and storm deadline are unchanged.

Isolated retry: cargo test -p calternal-plugin-files internal_temp_paths_never_enter_index_during_atomic_write_reconcile_storm -- --test-threads=1

    Finished `test` profile [unoptimized + debuginfo] target(s) in 2m 43s
writes, reconcile scans, and watcher adoption complete within five minutes: Elapsed(())
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 150 filtered out; finished in 381.82s
error: test failed, to rerun pass `-p calternal-plugin-files --lib`

The isolated retry also hit the unchanged deadline, with no additional assertion/error. Host load during this retry: load average: 62.59, 63.00, 70.15. This is recorded as an unresolved timing gate, not a passing suite. For the merge round, run the same focused command to prove 1,000 atomic writes, four scans and watcher adoption complete within the existing deadline. No further retries or full suite repeats were run.

Cleanup: cargo clean output:

     Removed 8931 files, 3.5GiB total

No web build output existed. Re-read the changed module/function comments and checked the final diff. Worktree is clean.

# #627 report Built: separate directory identity from mutable content fingerprints. Persist Linux directory birth time with device/inode; use it for Index writes and live identity checks. Carry creation evidence through Trash/restore. Retain file content/hash preconditions, grants, pending namespace/install guards and follow-parent rename. Files: crates/calternal-fs/src/{root.rs,lib.rs}; crates/plugins/files/src/{index.rs,lib.rs,tests/directory_identity.rs}; crates/plugins/files/migrations/0019_directory_birth.sql; docs/DESIGN.md §26. Decisions: use STATX_BTIME from the same opened inode. Upgrade adopts missing creation evidence for matching device/inode and keeps existing IDs. Legacy rows cannot prove pre-upgrade inode reuse. Without filesystem birth time, retain conservative full-fingerprint validation rather than grant access to an ambiguous replacement. The two added SQL columns reduce batches to 56 rows to preserve the historical bind limit. Only the existing applied-migration maximum assertion changes from 18 to 19, because #627 adds migration 0019; no HTTP or content expectation changes. UX gaps closed: folder Copy link resolver, sidebar pin resolver, Share access and open tus destination no longer fail on child writes on birth-time-capable filesystems. Tests cover 100 children, restart, rename/move, true replacement, simulated inode reuse and populated migration-0018 upgrade. Known gaps / UX gaps left: filesystems without STATX_BTIME retain the conservative guard, so child changes can still invalidate folder IDs there. Legacy inode reuse before token adoption cannot be distinguished without historical creation evidence. Browser rendering is unchanged; the production browser walk remains for the merge round. For the merge round: `cd apps/web && bun run test:e2e:calendar` must pass the tus Daily note replacement at calendar.mjs:1117 and complete the suite. Run `tests/adversarial/run-split.sh` once on the combined branch to verify XUser/authz/robustness matrices and replacement/grant isolation. Walk `/f/<item-id>` after 100 child writes, restart and rename and verify the real not-found state after delete/recreate. Full browser suites, adversarial matrices, release/staging/Mac checks and performance measurements were deferred under the 2026-10-02 verification policy. Head: `3159d5d484f0fb22d7d5657b30b7414374f26255` on `job/dirid-627`. Fetched and merged `origin/dev` once (`c4faf184df726a9375ae0c13bdfb6018ac2cf57e`) before final gates. Migration 0019 was free at that point. Atomic commits: DESIGN contract, FS evidence, nullable schema, then Files identity and router regressions. No push, deploy or issue close. Gate output (verbatim excerpts): `cargo fmt --check`: no output, exit 0. `cargo clippy -p calternal-fs --all-targets -- -D warnings` ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 19m 46s ``` `cargo test -p calternal-fs` ```text Finished `test` profile [unoptimized + debuginfo] target(s) in 4m 29s test result: ok. 52 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 115.22s test result: ok. 42 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 52.37s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ``` `cargo clippy -p calternal-plugin-files --all-targets -- -D warnings` ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 20m 30s ``` `cargo test -p calternal-plugin-files -- --test-threads=2` ```text Finished `test` profile [unoptimized + debuginfo] target(s) in 45m 08s test tests::directory_identity::recreated_folder_rejects_old_links_grants_and_uploads ... ok test tests::directory_identity::tus_parent_reindex_keeps_destination ... ok test tests::directory_identity::upgrade_adopts_directory_birth_without_changing_existing_id ... ok test tests::directory_identity::folder_links_pins_and_shares_survive_children_restart_and_rename ... ok writes, reconcile scans, and watcher adoption complete within five minutes: Elapsed(()) atomic write 384 failed: entry not found test result: FAILED. 149 passed; 1 failed; 1 ignored; 0 measured; 0 filtered out; finished in 781.46s error: test failed, to rerun pass `-p calternal-plugin-files --lib` ``` Gate caveat: the original Files suite is not green. Its unchanged storm test timed out at 300 seconds, then a writer reported entry not found during cancellation/cleanup. Shared-host contention is a hypothesis; the isolated retry result follows. The shared sccache also failed during an initial Clippy invocation because its temporary directory belonged to another deleted worktree; the final Clippy passed with RUSTC_WRAPPER unset. A new regression test borrow mismatch was fixed before final Clippy. Existing HTTP/content assertions and storm deadline are unchanged. Isolated retry: `cargo test -p calternal-plugin-files internal_temp_paths_never_enter_index_during_atomic_write_reconcile_storm -- --test-threads=1` ```text Finished `test` profile [unoptimized + debuginfo] target(s) in 2m 43s writes, reconcile scans, and watcher adoption complete within five minutes: Elapsed(()) test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 150 filtered out; finished in 381.82s error: test failed, to rerun pass `-p calternal-plugin-files --lib` ``` The isolated retry also hit the unchanged deadline, with no additional assertion/error. Host load during this retry: `load average: 62.59, 63.00, 70.15`. This is recorded as an unresolved timing gate, not a passing suite. For the merge round, run the same focused command to prove 1,000 atomic writes, four scans and watcher adoption complete within the existing deadline. No further retries or full suite repeats were run. Cleanup: `cargo clean` output: ```text Removed 8931 files, 3.5GiB total ``` No web build output existed. Re-read the changed module/function comments and checked the final diff. Worktree is clean.
Author
Owner

Resuming #627 on job/dirid-627, HEAD 796523a62. The surviving worktree contains an in-progress merge of origin/job/merge-round-7a at 61222f456 with working resolutions in four files; checking these before completing it. Migration is moved to 0023 as requested, keeping deployed 7a migrations 0019 and 0020.

Fetch is currently blocked by a shared repository ref: fatal: bad object refs/heads/job/moneyfu-984. A targeted fetch with HEAD negotiation fails with the same error. Cached origin/dev is 4a871b383 (already merged); cached 7a is the requested 61222f456. I will continue the authorized merge with these objects and report this fetch limitation; I will not delete another job's ref.

Resuming #627 on job/dirid-627, HEAD 796523a62. The surviving worktree contains an in-progress merge of origin/job/merge-round-7a at 61222f456 with working resolutions in four files; checking these before completing it. Migration is moved to 0023 as requested, keeping deployed 7a migrations 0019 and 0020. Fetch is currently blocked by a shared repository ref: `fatal: bad object refs/heads/job/moneyfu-984`. A targeted fetch with HEAD negotiation fails with the same error. Cached origin/dev is 4a871b383 (already merged); cached 7a is the requested 61222f456. I will continue the authorized merge with these objects and report this fetch limitation; I will not delete another job's ref.
Author
Owner

7a merge resolution is committed at 4ff17a880; directory birth evidence is migration 0023. Both nullable parent columns (deployed 0019) and folder reconcile migration 0020 remain. No migration 0021/0022 is added here; those numbers are reserved by the owner for round 7b.

Review found an additional continuity bypass: child completion calls record_preserve on its parent. The preserve flag previously reused even a replaced folder's ID. Restricted that writer override to files; folders always require device/inode/birth continuity. The replacement regression now invokes the actual refresh_parent path and retains all original 404/412/new-ID expectations. Updated stale parent-fingerprint comments from 7a; its existing test assertions are unchanged. Upgrade regression now starts from the deployed 0020 schema and checks the current link before lazy adoption.

7a merge resolution is committed at 4ff17a880; directory birth evidence is migration 0023. Both nullable parent columns (deployed 0019) and folder reconcile migration 0020 remain. No migration 0021/0022 is added here; those numbers are reserved by the owner for round 7b. Review found an additional continuity bypass: child completion calls record_preserve on its parent. The preserve flag previously reused even a replaced folder's ID. Restricted that writer override to files; folders always require device/inode/birth continuity. The replacement regression now invokes the actual refresh_parent path and retains all original 404/412/new-ID expectations. Updated stale parent-fingerprint comments from 7a; its existing test assertions are unchanged. Upgrade regression now starts from the deployed 0020 schema and checks the current link before lazy adoption.
Author
Owner

The new rename/PATCH race passes all 32 rounds. The new replacement/PATCH race found a test-fixture cleanup error: it used the Files Trash API to create Index rows, then called Root::empty_trash to remove only bytes. The next cycle reused the Trash name while the old primary-key row remained, so the API returned 500. This mixes filesystem-only cleanup with API-managed Security state; it is not the production empty-Trash path. Changed only the new test cleanup to POST /trash/empty, which removes both. No existing HTTP expectation changed. The corrected focused regression will run before final gates.

The fetch limitation is resolved: an isolated Git ref namespace fetched directly into the shared object store without deleting or editing another job's broken ref. Current remote dev is 4a871b383 and 7a is 61222f456; both merges report Already up to date.

The new rename/PATCH race passes all 32 rounds. The new replacement/PATCH race found a test-fixture cleanup error: it used the Files Trash API to create Index rows, then called Root::empty_trash to remove only bytes. The next cycle reused the Trash name while the old primary-key row remained, so the API returned 500. This mixes filesystem-only cleanup with API-managed Security state; it is not the production empty-Trash path. Changed only the new test cleanup to POST /trash/empty, which removes both. No existing HTTP expectation changed. The corrected focused regression will run before final gates. The fetch limitation is resolved: an isolated Git ref namespace fetched directly into the shared object store without deleting or editing another job's broken ref. Current remote dev is 4a871b383 and 7a is 61222f456; both merges report `Already up to date.`
Author
Owner

Identity fix committed at 5bdaf8607. Files suite: test result: FAILED. 161 passed; 2 failed; 2 ignored; 0 measured; 0 filtered out; finished in 479.52s. All original #627 regressions and the new 32-round rename race passed. The new replacement fixture cleanup is corrected; the focused identity test group is rebuilding now.

The other failure is the unchanged atomic-write/reconcile storm: writes, reconcile scans, and watcher adoption complete within five minutes: Elapsed(()), followed by atomic write 795 failed: entry not found during cancellation/cleanup. The prior run on this branch recorded the same sequence at write 384 under load 62.59. Current shared-host one-minute load was 32.06 after the suite. No deadline or existing assertion was changed; the suite remains an unresolved timing gate. No full-suite retry loop will run.

The 10,000-cycle campaign is running under flock on the perf VM HDD (ext4 /dev/sda1). Its case and production code are unchanged by the local replacement-fixture cleanup. The locked run records load average and follows the stress with the inode-reuse and tus POST/re-index/PATCH regressions.

Identity fix committed at 5bdaf8607. Files suite: `test result: FAILED. 161 passed; 2 failed; 2 ignored; 0 measured; 0 filtered out; finished in 479.52s`. All original #627 regressions and the new 32-round rename race passed. The new replacement fixture cleanup is corrected; the focused identity test group is rebuilding now. The other failure is the unchanged atomic-write/reconcile storm: `writes, reconcile scans, and watcher adoption complete within five minutes: Elapsed(())`, followed by `atomic write 795 failed: entry not found` during cancellation/cleanup. The prior run on this branch recorded the same sequence at write 384 under load 62.59. Current shared-host one-minute load was 32.06 after the suite. No deadline or existing assertion was changed; the suite remains an unresolved timing gate. No full-suite retry loop will run. The 10,000-cycle campaign is running under flock on the perf VM HDD (ext4 /dev/sda1). Its case and production code are unchanged by the local replacement-fixture cleanup. The locked run records load average and follows the stress with the inode-reuse and tus POST/re-index/PATCH regressions.
Author
Owner

Corrected focused identity group passes:

    Finished `test` profile [unoptimized + debuginfo] target(s) in 6m 15s
test result: ok. 6 passed; 0 failed; 1 ignored; 0 measured; 158 filtered out; finished in 46.80s

This includes 32 concurrent rename/PATCH rounds and 32 Trash/recreate/PATCH rounds. The fixture uses POST /trash/empty; the prior 500 no longer occurs. Existing ID, 404, 412, target-byte and schema expectations remain intact except the requested migration maximum 23. The HDD campaign has passed its first 1,000 cycles (3,000 child operations with checks after every operation). Files and filesystem final Clippy/tests are still running. The full Files storm timing gate remains unresolved as already reported.

Corrected focused identity group passes: ``` Finished `test` profile [unoptimized + debuginfo] target(s) in 6m 15s test result: ok. 6 passed; 0 failed; 1 ignored; 0 measured; 158 filtered out; finished in 46.80s ``` This includes 32 concurrent rename/PATCH rounds and 32 Trash/recreate/PATCH rounds. The fixture uses POST /trash/empty; the prior 500 no longer occurs. Existing ID, 404, 412, target-byte and schema expectations remain intact except the requested migration maximum 23. The HDD campaign has passed its first 1,000 cycles (3,000 child operations with checks after every operation). Files and filesystem final Clippy/tests are still running. The full Files storm timing gate remains unresolved as already reported.
Author
Owner

Head 92416e3334. Atomic follow-ups: 5bdaf8607 fixes folder parent refresh continuity; 92416e333 adds the two 32-round namespace races, the 10,000-cycle stress case and its command in the existing bench profile.

All final scoped checks pass: cargo fmt --check (no output, exit 0), Files and filesystem Clippy, six focused identity tests, and the full filesystem suite. The full Files suite's existing storm timing gate remains unresolved; its one run is reported above. No full-suite loop ran. The remote HDD campaign has passed 4,000 cycles (12,000 operations plus per-operation owner/Share/isolation checks) and continues under flock. No latency benchmark was run: this is a correctness run with a debug test binary under the current verification policy.

cargo clippy -p calternal-plugin-files --all-targets -- -D warnings

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 7m 52s

cargo test -p calternal-plugin-files directory_identity -- --test-threads=3

    Finished `test` profile [unoptimized + debuginfo] target(s) in 6m 15s
test result: ok. 6 passed; 0 failed; 1 ignored; 0 measured; 158 filtered out; finished in 46.80s

cargo clippy -p calternal-fs --all-targets -- -D warnings

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 52.56s

cargo test -p calternal-fs -- --test-threads=3

    Finished `test` profile [unoptimized + debuginfo] target(s) in 29.40s
test result: ok. 60 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 123.70s
test result: ok. 43 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 48.12s
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
Head 92416e33348971c9062738f2aac90169fe90399d. Atomic follow-ups: 5bdaf8607 fixes folder parent refresh continuity; 92416e333 adds the two 32-round namespace races, the 10,000-cycle stress case and its command in the existing bench profile. All final scoped checks pass: cargo fmt --check (no output, exit 0), Files and filesystem Clippy, six focused identity tests, and the full filesystem suite. The full Files suite's existing storm timing gate remains unresolved; its one run is reported above. No full-suite loop ran. The remote HDD campaign has passed 4,000 cycles (12,000 operations plus per-operation owner/Share/isolation checks) and continues under flock. No latency benchmark was run: this is a correctness run with a debug test binary under the current verification policy. `cargo clippy -p calternal-plugin-files --all-targets -- -D warnings` ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 7m 52s ``` `cargo test -p calternal-plugin-files directory_identity -- --test-threads=3` ```text Finished `test` profile [unoptimized + debuginfo] target(s) in 6m 15s test result: ok. 6 passed; 0 failed; 1 ignored; 0 measured; 158 filtered out; finished in 46.80s ``` `cargo clippy -p calternal-fs --all-targets -- -D warnings` ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 52.56s ``` `cargo test -p calternal-fs -- --test-threads=3` ```text Finished `test` profile [unoptimized + debuginfo] target(s) in 29.40s test result: ok. 60 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 123.70s test result: ok. 43 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 48.12s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ```
Author
Owner

HDD correctness campaign: 5,000 child write/rename/delete cycles passed in 1665.449966526s. This is 15,000 child operations and re-index passes, with owner link, Share link and unrelated-User denial checks after each operation. The same folder ID remains throughout. The run holds /root/perf.lock and uses ext4 /dev/sda1; recorded start load averages were 0.06, 0.01, 0.00.

Head is now c544b2dd93. This final documentation commit records the already-tested parent-refresh guarantee in DESIGN §26; runtime and test code are identical to 92416e333, whose scoped passing outputs are above. Local cargo clean completed: Removed 9155 files, 3.5GiB total. No web build output existed. Remote campaign and its inode-reuse/tus follow-ups continue; final report follows completion.

HDD correctness campaign: 5,000 child write/rename/delete cycles passed in 1665.449966526s. This is 15,000 child operations and re-index passes, with owner link, Share link and unrelated-User denial checks after each operation. The same folder ID remains throughout. The run holds /root/perf.lock and uses ext4 /dev/sda1; recorded start load averages were 0.06, 0.01, 0.00. Head is now c544b2dd934f535ecd0cb833b29ffa5ee85bf4ee. This final documentation commit records the already-tested parent-refresh guarantee in DESIGN §26; runtime and test code are identical to 92416e333, whose scoped passing outputs are above. Local cargo clean completed: `Removed 9155 files, 3.5GiB total`. No web build output existed. Remote campaign and its inode-reuse/tus follow-ups continue; final report follows completion.
Author
Owner

Finished the #627 folder identity fix on job/dirid-627. Head: c544b2dd934f535ecd0cb833b29ffa5ee85bf4ee. The last commit changes DESIGN text only; runtime and test code match the passing scoped checks at 92416e333.

Built: directory IDs use device, inode and filesystem birth time, separately from mutable size/mtime. Child writes and re-index keep the current ID. Upgrade adopts birth evidence lazily without changing current IDs. A replacement, including a reused inode with different birth evidence, gets a new ID. Child completion now checks folder continuity even when its file writer uses the preserve flag. File content/hash preconditions, grants and follow-parent rename remain intact. Trash/restore carry birth evidence.

Merged origin/dev (4a871b383) and requested 7a (61222f456). A broken shared ref initially blocked fetch; an isolated ref namespace fetched into the existing object store without changing another job's ref. Both remote SHAs were verified before final checks. Migration 0023 follows deployed 7a 0019/0020; 0021 is reserved for noext-851 and 0022 for webdav-lock-476. Old migration SQL stays unchanged. No dropmd-719 identity approach was used.

Files:

  • crates/calternal-fs/src/root.rs and lib.rs
  • crates/plugins/files/src/index.rs, lib.rs and tests/directory_identity.rs
  • crates/plugins/files/migrations/0023_directory_birth.sql
  • bench/files-directory-identity-627.mjs (documents the correctness profile; executable code unchanged)
  • docs/DESIGN.md §26

Verification: six focused identity regressions pass. They cover the populated 7a upgrade, sibling write between tus POST and PATCH (204), folder links/pins/Share/restart/rename/move, real replacement and simulated inode reuse. Added 32 concurrent rename/PATCH rounds and 32 concurrent Trash/recreate/PATCH rounds. The new replacement fixture initially mixed API Trash with filesystem-only cleanup and returned 500 on a duplicate fixture key; it now uses POST /trash/empty and passes. No existing HTTP/content expectation changed. The migration maximum changes to the requested 23.

On the perf VM HDD, the locally built debug test binary passed 10,000 child write/rename/delete cycles: 30,000 operations and re-index passes, with owner link resolution, Share link resolution and unrelated-User denial checked after each operation (90,000 resolver checks). The folder ID stayed unchanged. The run held /root/perf.lock; temporary data was on ext4 /dev/sda1. Start load averages: 0.06, 0.01, 0.00. The inode-reuse/replacement and tus sibling-write/re-index/PATCH regressions then passed on that VM. The lock is released and the remote test files are removed. This was a correctness run, not a release latency benchmark; latency/CPU/RSS profile measurements remain outside this non-performance job under the verification policy.

Gate output (verbatim excerpts): cargo fmt --check and node --check bench/files-directory-identity-627.mjs produced no output and exited 0.

cargo clippy -p calternal-plugin-files --all-targets -- -D warnings

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 7m 52s

cargo test -p calternal-plugin-files directory_identity -- --test-threads=3

    Finished `test` profile [unoptimized + debuginfo] target(s) in 6m 15s
test result: ok. 6 passed; 0 failed; 1 ignored; 0 measured; 158 filtered out; finished in 46.80s

cargo clippy -p calternal-fs --all-targets -- -D warnings

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 52.56s

cargo test -p calternal-fs -- --test-threads=3

    Finished `test` profile [unoptimized + debuginfo] target(s) in 29.40s
test result: ok. 60 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 123.70s
test result: ok. 43 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 48.12s
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

HDD focused correctness campaign:

#627: 10000 child write/rename/delete cycles passed in 3054.012939542s
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 164 filtered out; finished in 3054.51s
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 164 filtered out; finished in 1.14s
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 164 filtered out; finished in 1.42s

Unresolved Files suite gate: the one full crate run reported:

test result: FAILED. 161 passed; 2 failed; 2 ignored; 0 measured; 0 filtered out; finished in 479.52s

One failure was the new fixture cleanup error, now fixed and verified by the focused group. The other is the existing storm's unchanged five-minute deadline:

writes, reconcile scans, and watcher adoption complete within five minutes: Elapsed(())
atomic write 795 failed: entry not found

The writer error followed timeout cancellation/cleanup. The prior branch run recorded the same sequence. The shared-host one-minute load after this run was 32.06. This remains an unresolved timing gate, not a passing full suite. No deadline or existing assertion was changed and no full-suite retry loop ran.

Decisions: preserve a file ID only after its existing content checks; the preserve flag cannot bypass folder creation evidence. Retain deployed migration SQL and unused parent columns. Use nullable birth evidence and matching device/inode for legacy adoption so upgrade keeps CURRENT IDs. Without filesystem birth time, keep the conservative full-fingerprint guard. The Rust campaign uses a bounded disposable Home and copies its binary to the VM instead of building there. These choices are documented in module comments, the migration and DESIGN §26.

UX gaps closed: folder Copy link, pin resolution, Share access and open tus destinations survive child writes, re-index, restart and recorded rename/move. A replacement folder cannot inherit a grant or an old upload through parent refresh. Both namespace race orders preserve the intended destination.

Known gaps / UX gaps left: filesystems without birth time can still lose stable folder IDs after child changes; a durable creation token is future work in DESIGN §26. Legacy inode reuse before birth adoption cannot be distinguished. The original storm timing gate remains open. No UI rendering changed; browser evidence is for the merge round.

For the merge round:

  • cd apps/web && bun run test:e2e:calendar: prove the real Calendar tus Daily note replacement passes calendar.mjs:1117 and the suite completes.
  • tests/adversarial/run-split.sh: run the combined XUser/authz/robustness matrices, including replacement/grant isolation.
  • cargo test -p calternal-plugin-files internal_temp_paths_never_enter_index_during_atomic_write_reconcile_storm -- --test-threads=1: prove the original 1,000-write/four-scan/watcher test finishes within its unchanged deadline.
  • Walk a copied /f/<item-id> and Share after child edits, restart and rename; verify not-found after delete/recreate. Full web, server integration, release/staging and Mac checks stay with that round under the verification policy.

Cleanup output:

     Removed 9155 files, 3.5GiB total

No web build output remained. Re-read changed doc comments and checked the final diff. The worktree is clean. No push, deploy, issue close or promotion merge.

Finished the #627 folder identity fix on `job/dirid-627`. Head: `c544b2dd934f535ecd0cb833b29ffa5ee85bf4ee`. The last commit changes DESIGN text only; runtime and test code match the passing scoped checks at 92416e333. **Built:** directory IDs use device, inode and filesystem birth time, separately from mutable size/mtime. Child writes and re-index keep the current ID. Upgrade adopts birth evidence lazily without changing current IDs. A replacement, including a reused inode with different birth evidence, gets a new ID. Child completion now checks folder continuity even when its file writer uses the preserve flag. File content/hash preconditions, grants and follow-parent rename remain intact. Trash/restore carry birth evidence. Merged origin/dev (4a871b383) and requested 7a (61222f456). A broken shared ref initially blocked fetch; an isolated ref namespace fetched into the existing object store without changing another job's ref. Both remote SHAs were verified before final checks. Migration **0023** follows deployed 7a 0019/0020; 0021 is reserved for noext-851 and 0022 for webdav-lock-476. Old migration SQL stays unchanged. No dropmd-719 identity approach was used. **Files:** - crates/calternal-fs/src/root.rs and lib.rs - crates/plugins/files/src/index.rs, lib.rs and tests/directory_identity.rs - crates/plugins/files/migrations/0023_directory_birth.sql - bench/files-directory-identity-627.mjs (documents the correctness profile; executable code unchanged) - docs/DESIGN.md §26 **Verification:** six focused identity regressions pass. They cover the populated 7a upgrade, sibling write between tus POST and PATCH (204), folder links/pins/Share/restart/rename/move, real replacement and simulated inode reuse. Added 32 concurrent rename/PATCH rounds and 32 concurrent Trash/recreate/PATCH rounds. The new replacement fixture initially mixed API Trash with filesystem-only cleanup and returned 500 on a duplicate fixture key; it now uses POST /trash/empty and passes. No existing HTTP/content expectation changed. The migration maximum changes to the requested 23. On the perf VM HDD, the locally built debug test binary passed **10,000 child write/rename/delete cycles**: 30,000 operations and re-index passes, with owner link resolution, Share link resolution and unrelated-User denial checked after each operation (90,000 resolver checks). The folder ID stayed unchanged. The run held `/root/perf.lock`; temporary data was on ext4 `/dev/sda1`. Start load averages: 0.06, 0.01, 0.00. The inode-reuse/replacement and tus sibling-write/re-index/PATCH regressions then passed on that VM. The lock is released and the remote test files are removed. This was a correctness run, not a release latency benchmark; latency/CPU/RSS profile measurements remain outside this non-performance job under the verification policy. **Gate output (verbatim excerpts):** `cargo fmt --check` and `node --check bench/files-directory-identity-627.mjs` produced no output and exited 0. `cargo clippy -p calternal-plugin-files --all-targets -- -D warnings` ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 7m 52s ``` `cargo test -p calternal-plugin-files directory_identity -- --test-threads=3` ```text Finished `test` profile [unoptimized + debuginfo] target(s) in 6m 15s test result: ok. 6 passed; 0 failed; 1 ignored; 0 measured; 158 filtered out; finished in 46.80s ``` `cargo clippy -p calternal-fs --all-targets -- -D warnings` ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 52.56s ``` `cargo test -p calternal-fs -- --test-threads=3` ```text Finished `test` profile [unoptimized + debuginfo] target(s) in 29.40s test result: ok. 60 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 123.70s test result: ok. 43 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 48.12s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ``` HDD focused correctness campaign: ```text #627: 10000 child write/rename/delete cycles passed in 3054.012939542s test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 164 filtered out; finished in 3054.51s test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 164 filtered out; finished in 1.14s test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 164 filtered out; finished in 1.42s ``` **Unresolved Files suite gate:** the one full crate run reported: ```text test result: FAILED. 161 passed; 2 failed; 2 ignored; 0 measured; 0 filtered out; finished in 479.52s ``` One failure was the new fixture cleanup error, now fixed and verified by the focused group. The other is the existing storm's unchanged five-minute deadline: ```text writes, reconcile scans, and watcher adoption complete within five minutes: Elapsed(()) atomic write 795 failed: entry not found ``` The writer error followed timeout cancellation/cleanup. The prior branch run recorded the same sequence. The shared-host one-minute load after this run was 32.06. This remains an unresolved timing gate, not a passing full suite. No deadline or existing assertion was changed and no full-suite retry loop ran. **Decisions:** preserve a file ID only after its existing content checks; the preserve flag cannot bypass folder creation evidence. Retain deployed migration SQL and unused parent columns. Use nullable birth evidence and matching device/inode for legacy adoption so upgrade keeps CURRENT IDs. Without filesystem birth time, keep the conservative full-fingerprint guard. The Rust campaign uses a bounded disposable Home and copies its binary to the VM instead of building there. These choices are documented in module comments, the migration and DESIGN §26. **UX gaps closed:** folder Copy link, pin resolution, Share access and open tus destinations survive child writes, re-index, restart and recorded rename/move. A replacement folder cannot inherit a grant or an old upload through parent refresh. Both namespace race orders preserve the intended destination. **Known gaps / UX gaps left:** filesystems without birth time can still lose stable folder IDs after child changes; a durable creation token is future work in DESIGN §26. Legacy inode reuse before birth adoption cannot be distinguished. The original storm timing gate remains open. No UI rendering changed; browser evidence is for the merge round. **For the merge round:** - `cd apps/web && bun run test:e2e:calendar`: prove the real Calendar tus Daily note replacement passes calendar.mjs:1117 and the suite completes. - `tests/adversarial/run-split.sh`: run the combined XUser/authz/robustness matrices, including replacement/grant isolation. - `cargo test -p calternal-plugin-files internal_temp_paths_never_enter_index_during_atomic_write_reconcile_storm -- --test-threads=1`: prove the original 1,000-write/four-scan/watcher test finishes within its unchanged deadline. - Walk a copied `/f/<item-id>` and Share after child edits, restart and rename; verify not-found after delete/recreate. Full web, server integration, release/staging and Mac checks stay with that round under the verification policy. Cleanup output: ```text Removed 9155 files, 3.5GiB total ``` No web build output remained. Re-read changed doc comments and checked the final diff. The worktree is clean. No push, deploy, issue close or promotion merge.
Author
Owner

Coordination from #857: folder identity code is untouched. Notes retains an Index identity map linked to existing Files item IDs. A small batched hook in files/src/index.rs attaches already-indexed Notes to newly assigned Files IDs; no changes to folder ID generation or rename tracking.

Coordination from #857: folder identity code is untouched. Notes retains an Index identity map linked to existing Files item IDs. A small batched hook in files/src/index.rs attaches already-indexed Notes to newly assigned Files IDs; no changes to folder ID generation or rename tracking.
Author
Owner

#857 integration is committed at 54456bd10b5c10abee4b9b90158aba3e6f440b2a. Files Markdown records bind retained Note IDs to Files item IDs inside the existing write transaction; the predicate requires file MIME and a visible Markdown path, so .md directories cannot claim old Note IDs. Folder move responses adopt Notes after Files tracking commits. Folder ID generation/rename tracking is unchanged. The focused regression passes folder move + replay and replacement of a stale Note with a .md directory. IndexWrite::is_note_file reuses the allocation-free path predicate shared with visible_markdown_path; this is the only small guard refactor in Files lib.

#857 integration is committed at `54456bd10b5c10abee4b9b90158aba3e6f440b2a`. Files Markdown records bind retained Note IDs to Files item IDs inside the existing write transaction; the predicate requires file MIME and a visible Markdown path, so `.md` directories cannot claim old Note IDs. Folder move responses adopt Notes after Files tracking commits. Folder ID generation/rename tracking is unchanged. The focused regression passes folder move + replay and replacement of a stale Note with a `.md` directory. `IndexWrite::is_note_file` reuses the allocation-free path predicate shared with `visible_markdown_path`; this is the only small guard refactor in Files lib.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/calternal#627
No description provided.