Voice recordings go to Documents/Voice Memos (Title Case); migrate the existing 'Voice memos' folder and links #618

Open
opened 2026-10-01 10:10:20 +00:00 by kayg · 34 comments
Owner

Owner request (2026-10-01): "attachments should go to Documents > Voice Memos (not small m)"

Today: crates/calternal-notes-core/src/attachments.rs (lines ~28, ~87) and DESIGN line ~1881 use Documents/Voice memos.
Fix:

  • Use Documents/Voice Memos (Title Case, like Apple's Voice Memos) everywhere: the attachment router, DESIGN, CONTEXT, tests.
  • Migrate existing Homes: if Documents/Voice memos/ exists, rename it to Documents/Voice Memos/ through calternal-fs (case-only rename: rename via a temporary name so case-insensitive WebDAV/Finder clients and APFS-backed sync see one consistent move). Rewrite existing attachment links in Log entries and Notes so nothing breaks. Do it idempotently, logged, with a merge if both folders exist.
  • Keep the stable item IDs, so deep links survive (§33).
    Test: a Rust test for the new path; a migration test with an existing Voice memos folder and linked attachments → renamed + links rewritten + idempotent second run. Per-crate gates.
## Owner request (2026-10-01): "attachments should go to Documents > Voice Memos (not small m)" **Today:** `crates/calternal-notes-core/src/attachments.rs` (lines ~28, ~87) and DESIGN line ~1881 use `Documents/Voice memos`. **Fix:** - Use **`Documents/Voice Memos`** (Title Case, like Apple's Voice Memos) everywhere: the attachment router, DESIGN, CONTEXT, tests. - **Migrate existing Homes:** if `Documents/Voice memos/` exists, rename it to `Documents/Voice Memos/` through `calternal-fs` (case-only rename: rename via a temporary name so case-insensitive WebDAV/Finder clients and APFS-backed sync see one consistent move). Rewrite existing attachment links in Log entries and Notes so nothing breaks. Do it idempotently, logged, with a merge if both folders exist. - Keep the stable item IDs, so deep links survive (§33). **Test:** a Rust test for the new path; a migration test with an existing `Voice memos` folder and linked attachments → renamed + links rewritten + idempotent second run. Per-crate gates.
Author
Owner

Starting work on job/voicememos-618, based on 9a6c38c3b7c8bbbdad9919cd2419f773d9c34b6e (origin/dev, currently seven commits ahead of the branch). I am tracing the Files API, WebDAV provider, calternal-fs rename journal, and Notes link-rewrite paths before implementing the Title Case migration and case-twin repair.

Starting work on `job/voicememos-618`, based on `9a6c38c3b7c8bbbdad9919cd2419f773d9c34b6e` (`origin/dev`, currently seven commits ahead of the branch). I am tracing the Files API, WebDAV provider, `calternal-fs` rename journal, and Notes link-rewrite paths before implementing the Title Case migration and case-twin repair.
Author
Owner

Finding: crates/plugins/files/src/uploads.rs::create_impl takes the exact folder returned by attachment_folder() and calls mkdir_p on its parent. After a client renames Documents/Voice memos to Documents/Voice Memos, the old spelling is not resolved before the next recording, so Linux can create a second sibling folder. Both the Files API rename route and WebDAV MOVE call move_indexed, which performs one Index subtree update after the filesystem move. calternal-fs::Root::move_path currently journals one direct rename, with no intermediate name for case-only moves. I will fix these shared points and add a startup, retry-safe merge for voice memo case twins.

Finding: `crates/plugins/files/src/uploads.rs::create_impl` takes the exact folder returned by `attachment_folder()` and calls `mkdir_p` on its parent. After a client renames `Documents/Voice memos` to `Documents/Voice Memos`, the old spelling is not resolved before the next recording, so Linux can create a second sibling folder. Both the Files API rename route and WebDAV MOVE call `move_indexed`, which performs one Index subtree update after the filesystem move. `calternal-fs::Root::move_path` currently journals one direct rename, with no intermediate name for case-only moves. I will fix these shared points and add a startup, retry-safe merge for voice memo case twins.
Author
Owner

Post-merge gate finding: cargo test -p calternal-plugin-notes reports 166 passed and one failure in tests::daily_and_composer_preserve_unrelated_bytes (from origin/dev). Its GET /journal/2026-09-24 assertion receives 404 instead of 200 at crates/plugins/notes/src/lib.rs:9502. The merged snapshot-backed journal_snapshot returns “Daily note not indexed” when its snapshot table has no row. The test expectation is unchanged; I am continuing the requested gates and will report this as a known gap.

Post-merge gate finding: `cargo test -p calternal-plugin-notes` reports 166 passed and one failure in `tests::daily_and_composer_preserve_unrelated_bytes` (from `origin/dev`). Its GET `/journal/2026-09-24` assertion receives 404 instead of 200 at `crates/plugins/notes/src/lib.rs:9502`. The merged snapshot-backed `journal_snapshot` returns “Daily note not indexed” when its snapshot table has no row. The test expectation is unchanged; I am continuing the requested gates and will report this as a known gap.
Author
Owner

Local Voice Memos profile result (shared host; no Voice Memos baseline exists in docs/perf/baseline.json):

  • A 1,000-file fixture and then a 256-file fixture with 64 conflicts did not log migration completion within 300 seconds.
  • The completed reduced run used two 64-file samples, then 128 old-folder files plus 8 conflict files and 16 linked Notes, followed by 16 uploads at concurrency 8.
  • Average migration: p50 6,645 ms, p95 6,875 ms; mean server CPU 3.43 s; mean RSS 121,956,270 bytes; peak RSS 176,627,712 bytes.
  • Reduced worst merge: 136 moved paths, 8 conflict copies, 16 linked Notes; migration 134,307 ms; server CPU 12.35 s; mean RSS 230,617,587 bytes; peak RSS 243,101,696 bytes.
  • Upload burst: p50 6,916.52 ms, p95 11,787.37 ms; CPU 1.61 s; mean RSS 251,385,362 bytes; peak RSS 255,242,240 bytes.
  • Load average (1/5/15 minutes) moved from 23.59/23.42/19.85 to 27.75/25.42/21.35. Results are local debug measurements on the shared host and are not a baseline comparison.

The larger fixture timeouts and completed measurements are being recorded in docs/perf/2026-10-02-voice-memos.md.

Local Voice Memos profile result (shared host; no Voice Memos baseline exists in `docs/perf/baseline.json`): - A 1,000-file fixture and then a 256-file fixture with 64 conflicts did not log migration completion within 300 seconds. - The completed reduced run used two 64-file samples, then 128 old-folder files plus 8 conflict files and 16 linked Notes, followed by 16 uploads at concurrency 8. - Average migration: p50 6,645 ms, p95 6,875 ms; mean server CPU 3.43 s; mean RSS 121,956,270 bytes; peak RSS 176,627,712 bytes. - Reduced worst merge: 136 moved paths, 8 conflict copies, 16 linked Notes; migration 134,307 ms; server CPU 12.35 s; mean RSS 230,617,587 bytes; peak RSS 243,101,696 bytes. - Upload burst: p50 6,916.52 ms, p95 11,787.37 ms; CPU 1.61 s; mean RSS 251,385,362 bytes; peak RSS 255,242,240 bytes. - Load average (1/5/15 minutes) moved from 23.59/23.42/19.85 to 27.75/25.42/21.35. Results are local debug measurements on the shared host and are not a baseline comparison. The larger fixture timeouts and completed measurements are being recorded in `docs/perf/2026-10-02-voice-memos.md`.
Author
Owner

#618 complete — branch job/voicememos-618, HEAD df30c35a487a0a3eb9aedacbf102beec79e0050a.

Built

  • Voice memo attachments now use Documents/Voice Memos. The router reuses an existing case-folded folder spelling.
  • calternal-fs journals case-only moves as one replayable operation through a temporary sibling.
  • Files startup repair merges case-twin folders, preserves stable Item IDs, keeps a conflict copy, updates the Files Index and rewrites Notes and Log attachment links. Pending move recovery completes link rewrites after a crash.
  • Added Files web and WebDAV case-only move tests, migration/idempotence and conflict tests, router lookup tests, a real-server adversarial probe, and a benchmark profile.

Files

CONTEXT.md; apps/web/e2e/composer.mjs; bench/voice-memo-migration-618.py; crates/calternal-fs/src/{file_ops.rs,journal.rs,lib.rs,path.rs}; crates/calternal-fs/tests/storage.rs; crates/calternal-notes-core/src/{attachments.rs,lib.rs,links.rs}; crates/plugins/files/src/{index.rs,lib.rs,uploads.rs}; crates/plugins/notes/src/lib.rs; docs/DESIGN.md; docs/perf/{README.md,2026-10-02-voice-memos.md}; tests/adversarial/{run.sh,voice_memos.py}.

Gates

cargo fmt --check passed with no output.

Clippy passed for each changed Rust crate and calternal-server:

calternal-fs:     Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.86s
calternal-notes-core: Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.38s
calternal-plugin-files: Finished `dev` profile [unoptimized + debuginfo] target(s) in 19.33s
calternal-plugin-notes: Finished `dev` profile [unoptimized + debuginfo] target(s) in 18.90s
calternal-server: Finished `dev` profile [unoptimized + debuginfo] target(s) in 2m 21s

Rust test output:

calternal-fs: test result: ok. 52 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 14.57s
test result: ok. 44 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 4.82s
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
calternal-notes-core: test result: ok. 521 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.17s
test result: ok. 19 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 3.38s
test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.04s
test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.52s
test result: ok. 12 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
calternal-plugin-files: test result: ok. 153 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 138.12s
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
calternal-plugin-notes: test result: FAILED. 166 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 74.25s
calternal-server: test result: ok. 107 passed; 0 failed; 3 ignored; 0 measured; 0 filtered out; finished in 11.43s

The Notes failure is tests::daily_and_composer_preserve_unrelated_bytes: the merged origin/dev snapshot-backed daily route returned HTTP 404 where the existing test expects 200 (crates/plugins/notes/src/lib.rs:9502). That test is present on origin/dev; I kept its expectation unchanged and reported the finding earlier.

Web gates passed:

svelte-check found 0 errors and 0 warnings
 Test Files  153 passed (153)
      Tests  1053 passed (1053)

bun run build and cargo build -p calternal-server passed. The single local real-server adversarial round passed:

Voice Memos adversarial checks passed: Files rename, WebDAV MOVE, uploads, Index rows, bytes, malformed metadata, and 16 concurrent recordings

Cleanup output:

Removed 18590 files, 10.4GiB total

Performance

The completed reduced local profile is recorded in docs/perf/2026-10-02-voice-memos.md. On the shared host, load averages (1/5/15 minutes) were 23.59/23.42/19.85 before and 27.75/25.42/21.35 after. Two 64-file samples measured migration p50/p95 6,645/6,875 ms, mean CPU 3.43 s, mean RSS 121,956,270 bytes, and peak RSS 176,627,712 bytes. The reduced merge used 136 moved paths, 8 conflict copies and 16 linked Notes; migration took 134,307 ms, CPU 12.35 s, mean RSS 230,617,587 bytes, peak RSS 243,101,696 bytes. A 16-upload burst at concurrency 8 measured p50/p95 6,916.52/11,787.37 ms, CPU 1.61 s, and peak RSS 255,242,240 bytes.

The 1,000-file fixture and a 256-file fixture with 64 conflicts did not reach the migration log within 300 seconds. The successful measurements use the reduced conflict set and are not a quiet-host baseline. docs/perf/baseline.json has no matching Voice Memos scenario.

Decisions not specified in DESIGN

  • If the exact Voice Memos directory exists, it remains primary and keeps its Item ID. If it does not exist, the newest case-folded candidate directory becomes primary.
  • For file conflicts, filesystem modification time with nanosecond precision chooses the winner. At an exact tie, the existing canonical target wins. The other file remains under a deterministic conflict-copy name derived from its stable Item ID; a number handles a name collision.

No issue was closed. No push or deploy was performed.

#618 complete — branch `job/voicememos-618`, HEAD `df30c35a487a0a3eb9aedacbf102beec79e0050a`. ## Built - Voice memo attachments now use `Documents/Voice Memos`. The router reuses an existing case-folded folder spelling. - `calternal-fs` journals case-only moves as one replayable operation through a temporary sibling. - Files startup repair merges case-twin folders, preserves stable Item IDs, keeps a conflict copy, updates the Files Index and rewrites Notes and Log attachment links. Pending move recovery completes link rewrites after a crash. - Added Files web and WebDAV case-only move tests, migration/idempotence and conflict tests, router lookup tests, a real-server adversarial probe, and a benchmark profile. ## Files `CONTEXT.md`; `apps/web/e2e/composer.mjs`; `bench/voice-memo-migration-618.py`; `crates/calternal-fs/src/{file_ops.rs,journal.rs,lib.rs,path.rs}`; `crates/calternal-fs/tests/storage.rs`; `crates/calternal-notes-core/src/{attachments.rs,lib.rs,links.rs}`; `crates/plugins/files/src/{index.rs,lib.rs,uploads.rs}`; `crates/plugins/notes/src/lib.rs`; `docs/DESIGN.md`; `docs/perf/{README.md,2026-10-02-voice-memos.md}`; `tests/adversarial/{run.sh,voice_memos.py}`. ## Gates `cargo fmt --check` passed with no output. Clippy passed for each changed Rust crate and `calternal-server`: ```text calternal-fs: Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.86s calternal-notes-core: Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.38s calternal-plugin-files: Finished `dev` profile [unoptimized + debuginfo] target(s) in 19.33s calternal-plugin-notes: Finished `dev` profile [unoptimized + debuginfo] target(s) in 18.90s calternal-server: Finished `dev` profile [unoptimized + debuginfo] target(s) in 2m 21s ``` Rust test output: ```text calternal-fs: test result: ok. 52 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 14.57s test result: ok. 44 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 4.82s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s calternal-notes-core: test result: ok. 521 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.17s test result: ok. 19 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 3.38s test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.04s test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.52s test result: ok. 12 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s calternal-plugin-files: test result: ok. 153 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 138.12s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s calternal-plugin-notes: test result: FAILED. 166 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 74.25s calternal-server: test result: ok. 107 passed; 0 failed; 3 ignored; 0 measured; 0 filtered out; finished in 11.43s ``` The Notes failure is `tests::daily_and_composer_preserve_unrelated_bytes`: the merged `origin/dev` snapshot-backed daily route returned HTTP 404 where the existing test expects 200 (`crates/plugins/notes/src/lib.rs:9502`). That test is present on `origin/dev`; I kept its expectation unchanged and reported the finding earlier. Web gates passed: ```text svelte-check found 0 errors and 0 warnings Test Files 153 passed (153) Tests 1053 passed (1053) ``` `bun run build` and `cargo build -p calternal-server` passed. The single local real-server adversarial round passed: ```text Voice Memos adversarial checks passed: Files rename, WebDAV MOVE, uploads, Index rows, bytes, malformed metadata, and 16 concurrent recordings ``` Cleanup output: ```text Removed 18590 files, 10.4GiB total ``` ## Performance The completed reduced local profile is recorded in `docs/perf/2026-10-02-voice-memos.md`. On the shared host, load averages (1/5/15 minutes) were `23.59/23.42/19.85` before and `27.75/25.42/21.35` after. Two 64-file samples measured migration p50/p95 `6,645/6,875 ms`, mean CPU `3.43 s`, mean RSS `121,956,270 bytes`, and peak RSS `176,627,712 bytes`. The reduced merge used 136 moved paths, 8 conflict copies and 16 linked Notes; migration took `134,307 ms`, CPU `12.35 s`, mean RSS `230,617,587 bytes`, peak RSS `243,101,696 bytes`. A 16-upload burst at concurrency 8 measured p50/p95 `6,916.52/11,787.37 ms`, CPU `1.61 s`, and peak RSS `255,242,240 bytes`. The 1,000-file fixture and a 256-file fixture with 64 conflicts did not reach the migration log within 300 seconds. The successful measurements use the reduced conflict set and are not a quiet-host baseline. `docs/perf/baseline.json` has no matching Voice Memos scenario. ## Decisions not specified in DESIGN - If the exact `Voice Memos` directory exists, it remains primary and keeps its Item ID. If it does not exist, the newest case-folded candidate directory becomes primary. - For file conflicts, filesystem modification time with nanosecond precision chooses the winner. At an exact tie, the existing canonical target wins. The other file remains under a deterministic conflict-copy name derived from its stable Item ID; a number handles a name collision. No issue was closed. No push or deploy was performed.
Author
Owner

Independent review started on job/voicememos-review, base and review target df30c35a487a0a3eb9aedacbf102beec79e0050a. Scope: tests and code review only; no product edits. I will check byte and identity retention, link rewrite and replay, confinement, and startup cost. Findings and exact validation output will go in review-findings.md.

Independent review started on `job/voicememos-review`, base and review target `df30c35a487a0a3eb9aedacbf102beec79e0050a`. Scope: tests and code review only; no product edits. I will check byte and identity retention, link rewrite and replay, confinement, and startup cost. Findings and exact validation output will go in `review-findings.md`.
Author
Owner

Blocking finding at review target df30c35a487a0a3eb9aedacbf102beec79e0050a: a twin merge with a newer legacy recording and an older canonical recording redirects both Note links to the older conflict copy. The newer recording survives at the shared path with its original file ID, but its Note link no longer points to it.

Evidence: review_twin_merge_redirects_newer_recording_link_to_older_copy runs the production migration. It verifies both byte contents and IDs, then compares the entire Note against the incorrect observed output. CRLF, frontmatter order and unrelated UTF-8 text remain exact. The test passed (it is explicitly a defect characterization, not an acceptance test).

Cause: move_indexed rewrites each move immediately. migrate_voice_memo_home then rewrites the collected mappings again. The canonical shared path → conflict-copy mapping catches the link that the later legacy shared path → canonical shared path move just produced. This blocks GO before the owner's Home is touched. No product code changed in this review.

Blocking finding at review target `df30c35a487a0a3eb9aedacbf102beec79e0050a`: a twin merge with a newer legacy recording and an older canonical recording redirects both Note links to the older conflict copy. The newer recording survives at the shared path with its original file ID, but its Note link no longer points to it. Evidence: `review_twin_merge_redirects_newer_recording_link_to_older_copy` runs the production migration. It verifies both byte contents and IDs, then compares the entire Note against the incorrect observed output. CRLF, frontmatter order and unrelated UTF-8 text remain exact. The test passed (it is explicitly a defect characterization, not an acceptance test). Cause: `move_indexed` rewrites each move immediately. `migrate_voice_memo_home` then rewrites the collected mappings again. The canonical shared path → conflict-copy mapping catches the link that the later legacy shared path → canonical shared path move just produced. This blocks GO before the owner's Home is touched. No product code changed in this review.
Author
Owner

Further evidence at the same review target:

  • review_older_source_leaves_legacy_folder_until_second_run confirms that an older legacy recording's conflict copy remains in the legacy folder. First repair returns Directory not empty (os error 39) after removing that folder's Index row. A second run finishes; recording bytes survive.
  • review_two_legacy_twins_without_canonical_cannot_start confirms that Voice memos + VOICE MEMOS, without Voice Memos, returns name_conflict_case on both attempts. Bytes survive; repair cannot start.
  • review_encoded_and_reference_destinations_remain_stale confirms that percent-encoded destinations and reference-style Markdown destinations remain unchanged when the folder moves.
  • SIGKILL at the three durable case-rename namespace boundaries recovers recording bytes and inode identity. The partial Note/Log write fixture also recovers through a reopened Root and retains item IDs.

Per-crate fs and notes-core tests pass. These are distinct from a claim that every multi-file merge crash point has been tested. Final gate output and performance measurements will follow in the report.

Further evidence at the same review target: - `review_older_source_leaves_legacy_folder_until_second_run` confirms that an older legacy recording's conflict copy remains in the legacy folder. First repair returns `Directory not empty (os error 39)` after removing that folder's Index row. A second run finishes; recording bytes survive. - `review_two_legacy_twins_without_canonical_cannot_start` confirms that `Voice memos` + `VOICE MEMOS`, without `Voice Memos`, returns `name_conflict_case` on both attempts. Bytes survive; repair cannot start. - `review_encoded_and_reference_destinations_remain_stale` confirms that percent-encoded destinations and reference-style Markdown destinations remain unchanged when the folder moves. - SIGKILL at the three durable case-rename namespace boundaries recovers recording bytes and inode identity. The partial Note/Log write fixture also recovers through a reopened Root and retains item IDs. Per-crate fs and notes-core tests pass. These are distinct from a claim that every multi-file merge crash point has been tested. Final gate output and performance measurements will follow in the report.
Author
Owner

Second blocker confirmed by the extended fixture: review_older_source_loses_file_id_and_leaves_legacy_folder passes against the reviewed implementation. It verifies that the first failed repair leaves the older recording's conflict copy on disk but deletes its files_index row, Share, and public link. The next repair assigns a different file ID to that recording.

Cause: after the conflict copy is left inside the legacy folder, migrate_voice_memo_home calls recursive index::remove before remove_empty_user_dir. index::remove deletes descendant Index rows and Security state. Then physical folder removal fails because the conflict copy is still there. Recording bytes survive; stable deep links and Security state do not. This is a NO-GO data-integrity finding, not a SLOW finding.

Second blocker confirmed by the extended fixture: `review_older_source_loses_file_id_and_leaves_legacy_folder` passes against the reviewed implementation. It verifies that the first failed repair leaves the older recording's conflict copy on disk but deletes its `files_index` row, Share, and public link. The next repair assigns a different file ID to that recording. Cause: after the conflict copy is left inside the legacy folder, `migrate_voice_memo_home` calls recursive `index::remove` before `remove_empty_user_dir`. `index::remove` deletes descendant Index rows and Security state. Then physical folder removal fails because the conflict copy is still there. Recording bytes survive; stable deep links and Security state do not. This is a NO-GO data-integrity finding, not a SLOW finding.
Author
Owner

The bounded exact-target local profile is complete. With 100,000 flat files in the legacy Voice Memos folder and an empty canonical twin, the repair reached its 30-second bound at 30,008.512 ms after moving 7 files. 99,993 remained in the legacy folder; all 100,000 entries were still present. Kernel read-byte delta was 0 (cached fixture); write-byte delta was 2,555,904, including 491,520 cancelled write bytes. The full test, including fixture creation and cleanup, used 11.616 s user CPU, 8.111 s system CPU and 98,112 KiB peak RSS. This does not establish a full completion time or every file's hash/ID.

For 100,000 unrelated files and an empty legacy folder, first repair took 4,806.097 ms and the canonical-only retry took 0.241 ms. No matching Voice Memos baseline exists. These are local debug measurements on the busy shared host. The perf VM was available under its lock, but no verified exact-target shared release server was available. No build or deployment occurred there. The SLOW result does not add a merge blocker; the two confirmed data-integrity defects remain the NO-GO basis.

The bounded exact-target local profile is complete. With 100,000 flat files in the legacy Voice Memos folder and an empty canonical twin, the repair reached its 30-second bound at 30,008.512 ms after moving 7 files. 99,993 remained in the legacy folder; all 100,000 entries were still present. Kernel read-byte delta was 0 (cached fixture); write-byte delta was 2,555,904, including 491,520 cancelled write bytes. The full test, including fixture creation and cleanup, used 11.616 s user CPU, 8.111 s system CPU and 98,112 KiB peak RSS. This does not establish a full completion time or every file's hash/ID. For 100,000 unrelated files and an empty legacy folder, first repair took 4,806.097 ms and the canonical-only retry took 0.241 ms. No matching Voice Memos baseline exists. These are local debug measurements on the busy shared host. The perf VM was available under its lock, but no verified exact-target shared release server was available. No build or deployment occurred there. The SLOW result does not add a merge blocker; the two confirmed data-integrity defects remain the NO-GO basis.
Author
Owner

Final independent review: NO-GO.

Branch: job/voicememos-review. Final head: 9200c49b516148d6b78a70650b0443ec4539fbf4. Reviewed product target: df30c35a487a0a3eb9aedacbf102beec79e0050a. Five atomic review commits; tests and report only. All final per-crate gates passed. The passing characterization tests confirm defects; they do not approve the product repair. Build output was cleaned. No push, deployment or owner-data edit.

Voice Memos data-integrity review

Verdict: NO-GO for #618/#621 at
df30c35a487a0a3eb9aedacbf102beec79e0050a.
Do not run this repair on the owner's Home until the link-identity defect and
recording identity / Security state deletion are fixed. This review changes
tests and this report only. It makes no product fix.

Files: crates/plugins/files/src/lib.rs, move_indexed,
move_voice_memo_path, and migrate_voice_memo_home.

Fixture: both Voice Memos spellings contain shared.m4a. The legacy file has
newer bytes and modification time. The canonical file has older bytes. A Note
has one link to each file.

The repair keeps the older recording at a conflict-copy path. It moves the newer
recording to the canonical shared path. Both byte contents and both file IDs
survive. But both Note links end at the older conflict-copy path. The link
that named the newer recording now plays the older recording.

Cause: move_indexed rewrites links after each move. At the end,
migrate_voice_memo_home applies the collected mappings again. The second
canonical shared path to conflict-copy mapping catches a link that the legacy
shared path to canonical shared path move already changed.

Evidence: review_twin_merge_redirects_newer_recording_link_to_older_copy in
crates/plugins/files/src/tests/voice_memos_review.rs. The test compares the
whole Note with the observed incorrect output. It also checks file bytes, IDs,
CRLF, frontmatter order, unrelated text, and a second run.

Required fix: define one replay-safe link transaction that retains the original
recording identity. Remove the repeated application of overlapping move
mappings. Test both modification-time orders and a restart during each Note
write. Do not clear a move intent until its link changes and Index updates are
complete.

Other findings

  1. Blocking: an older source loses Index identity and Security state.
    Its conflict copy is made in the legacy folder. The merge does not visit that new entry. It then removes
    the folder's Index row and tries to remove the nonempty folder. The call
    fails with Directory not empty (os error 39). The Index deletion is
    recursive: it also removes the conflict copy's file row, Shares and public
    links. Bytes survive, but a second run must assign a new recording ID.
    Security state cannot be rebuilt from recording bytes. The extended test
    checks all three deletions and the changed ID:
    review_older_source_loses_file_id_and_leaves_legacy_folder. The test passed.
    Keep the conflict copy at its final destination before folder removal. Do not delete any live descendant's
    identity or grants.
  2. Two legacy twins without the canonical spelling cannot migrate. The
    chosen primary folder's rename meets the normal sibling case-conflict gate.
    Both attempts return name_conflict_case. Neither recording changes.
    Test: review_two_legacy_twins_without_canonical_cannot_start. The recovery
    path must handle this existing state without weakening the normal new-name
    gate.
  3. Two Markdown destination forms remain stale. Percent-encoded paths
    such as Documents/Voice%20memos/a.m4a and reference definitions such as
    [audio]: <Documents/Voice memos/a.m4a> do not change. Their recording can
    move while the link retains the legacy destination. Test:
    review_encoded_and_reference_destinations_remain_stale. Extend the shared
    scanner and test the decoded component boundary before the repair runs.
  4. The repair has no hash-based file deduplication. A file collision always
    keeps a conflict copy, even for identical content. This avoids an unchecked
    deletion. The Index deletion defect above can still lose file IDs. The condition “dedupe only when hashes match”
    is met because this merge deletes no colliding file. Do not describe this
    merge as hash-based deduplication. Merged source directory IDs are removed;
    the tested ID guarantee applies to recordings, not to both twin folders.
  5. Legacy invalid new names stop a merge. New-name normalization rejects
    trailing spaces and dots. The merge passes each existing child name to this
    policy. It can therefore stop on imported names. A decomposed name can also
    fail when it is used as a new destination without NFC normalization. This
    is a safe abort, not evidence of escape or byte loss. These merge branches
    were inspected; the name-policy tests exercise the normalization boundary.
  6. There is no durable “done once” flag. Each FilesState::reconcile_all
    calls the repair. A canonical-only Home incurs a directory check and no
    link scan. A completed repair is cheap to retry, but it is not permanently
    disabled. A later legacy folder can trigger it again.

Confirmed behavior and limits

  • Distinct same-name recording bytes and file IDs survive the tested merge
    when the legacy recording is newer. The existing twin-merge test and the new link-identity test check this.
  • Pure inline Markdown rewrites preserve CRLF, frontmatter order, Unicode,
    unrelated links, code examples, labels, query strings and anchors in the
    fixtures. The matching folder prefix has a component boundary. A simple
    folder rename is idempotent.
  • A restart after the physical folder rename and one of two Note writes
    completes both Note and Daily note Log links. The reopened Root and Files
    state retain folder and recording IDs. Repeated reconciliation preserves
    the resulting bytes. Test: review_partial_note_rewrite_replays_after_reopen.
  • A worker is killed with SIGKILL after journal publication, after the temporary
    rename, and after the final rename. Fresh Root recovery finishes each case,
    retains the recording bytes and inode, removes the temporary name, and is
    safe on a second replay. Test:
    review_sigkill_at_each_case_rename_boundary.
  • Root uses openat2 with BENEATH, NO_SYMLINKS and NO_MAGICLINKS.
    Namespace changes use held parent handles with renameat_with. The review
    found formatted relative names, but not an ambient filesystem move built
    from User input. RelPath/InternalPath validate these names before handle
    resolution. A legacy symlink is rejected and its external target is unchanged.
  • Folding is NFC, then default full non-Turkic Unicode case folding, not
    simple folding. The code documents it in calternal-fs/src/path.rs. Tests
    cover NFC/NFD equivalence, ß/SS, ASCII I/i, dotless ı, dotted İ,
    and trailing spaces/dots. This is not evidence from an APFS filesystem.
  • The repair holds the Home Notes lock and uses a content-hash checked update.
    It emits Notes invalidations, which the real Hub consumes as external edits.
    The live-room fixture passed: its live edit, last line, and rewritten
    attachment each appeared once after duplicate invalidations and a flush.
    A Hub test is not a browser typing test for all #634 scenarios.

This is not a proof of crash safety at every multi-file merge boundary.
There is no exhaustive SIGKILL matrix for conflict copies, Sidecars, all SQL
commit points, every Note write, or power failure during fsync. The three
case-rename namespace boundaries and the partial Note replay are covered.
The failing identity case alone is enough to block this repair.

Performance

Local debug measurement, shared host, one run with a cached fixture:
100,000 non-Markdown files in Archive and an empty legacy Voice Memos folder.
Fixture creation and normal Files indexing are outside the repair timer.

Repair phase Elapsed Kernel read bytes delta Kernel write bytes delta
First repair 4,806.097 ms 0 307,200
Canonical-only retry 0.241 ms 0 0

The process used 1.986 s user CPU and 5.023 s system CPU with 39,472 KiB peak
RSS. These process totals include fixture creation, schema setup and cleanup;
they are not repair-only CPU/RSS. The full test took 23.65 s. Initial load was
29.25 / 25.14 / 22.86; final load was 31.65 / 26.15 / 23.30. /proc/self/io
counts disk bytes charged to the process. Cached metadata operations are not
proof of zero filesystem work. This profile does not include 100k moved files,
linked Notes, conflicts, or a cold filesystem.

The affected-folder profile placed 100,000 flat files in the legacy Voice Memos
folder and an empty canonical twin beside it. It reached the 30-second bound
at 30,008.512 ms, with only 7 files moved and 99,993 still in the legacy
folder. All 100,000 directory entries remained present. The profile did not
complete the repair and did not claim to verify every file's hash or ID.
Kernel read-byte delta was 0; write-byte delta was 2,555,904, with 491,520
cancelled write bytes. Process totals, including fixture creation and cleanup:
11.616 s user CPU, 8.111 s system CPU, 98,112 KiB peak RSS, 53.85 s test time.
Final host load was 21.13 / 18.78 / 20.72. This is a local debug result from a
busy host, not a quiet release measurement. It does not support a claim that
repair is cheap for 100k affected files. This SLOW result is not itself a merge
blocker.

The perf VM lock check succeeded. No exact-target release server was available.
The host's shared release binary lacks this migration's completion marker, so
its target revision could not be verified and it was not used for this review.
No server was deployed or compiled on the perf VM.

docs/perf/baseline.json has no Voice Memos migration scenario. There is no
matching baseline or threshold comparison. The earlier job's local debug
profile in docs/perf/2026-10-02-voice-memos.md reports 134,307 ms for 128 legacy
files, 8 conflicts and 16 linked Notes; it is context, not this review's result.

Code review explains the scaling concern: each moved item calls the Notes
rewrite, which walks all visible Home entries. The merge also reads the target
folder for each child. A flat twin merge can require quadratic directory work
and repeated full Home scans. The final batch adds another scan.

Decisions

  • Keep product behavior unchanged. Record defects with explicitly named
    characterization tests. A passing defect test confirms the defect; it is
    not an acceptance gate. Replace its observed-defect assertion with the
    intended invariant when the implementation is fixed.
  • Use process kills only in disposable test Homes. Test partial Note replay
    through a fresh Root rather than add a product fault-injection API.
  • Bound the large twin workload. Do not wait for an unbounded 100k-file merge.
  • Use exact-target local measurements when the shared release does not contain
    the target change. Label all measurements and their limits.

UX gaps closed

None. This is a tests and code review job.

UX gaps left

The link-identity defect can make a Note play the wrong recording. The merge
abort cases leave repair incomplete. No UI was changed or visually reviewed.

Validation

The test head is 335a5fcfe821ddf28089e46fc7322b58b56d02a1.
The final report commit follows this head. Review branch: job/voicememos-review.

Before the final gates, git fetch origin succeeded and git merge origin/dev
returned, verbatim:

Already up to date.

The fetched dev head was c4a61e8cf090170f35b1bed3350d9de20c83ecd5, already an
ancestor of the reviewed target. No product merge commit was made.

All cargo commands used CARGO_PROFILE_DEV_DEBUG=line-tables-only,
CARGO_INCREMENTAL=0, CARGO_BUILD_JOBS=4 and this worktree's target/tmp for
TMPDIR. The preset CARGO_TARGET_DIR was not changed. No dependency version
or lockfile was changed. No web or server route code was changed.

cargo fmt --check: no output, exit 0. git diff --check: no output, exit 0.
An initial filesystem clippy run found a type error in the new child-worker
fixture. It was corrected before the filesystem tests. The corrected clippy
output appears below. No existing test expectation was changed.

The following are verbatim summary lines from the final gate logs. Complete
logs remain in the gitignored artifacts/ directory. These are per-crate gates,
not workspace gates. The large-Home profile ran alone as an explicit ignored
test. The ignored SIGKILL worker ran through its parent test. The existing
10k-file rclone opt-in test was not run.

cargo clippy -p calternal-fs --all-targets -- -D warnings (exit 0):

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

cargo test -p calternal-fs -- --test-threads=2 (exit 0):

test result: ok. 53 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 24.43s
test result: ok. 44 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 11.95s
test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.05s
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

cargo clippy -p calternal-notes-core --all-targets -- -D warnings (exit 0):

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

cargo test -p calternal-notes-core -- --test-threads=2 (exit 0):

test result: ok. 521 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.79s
test result: ok. 19 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 7.52s
test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.11s
test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.64s
test result: ok. 12 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.02s
test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
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 (exit 0):

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 1m 49s

cargo test -p calternal-plugin-files -- --test-threads=2 (exit 0):

test result: ok. 157 passed; 0 failed; 2 ignored; 0 measured; 0 filtered out; finished in 245.87s
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

cargo clippy -p calternal-collab --all-targets -- -D warnings (exit 0):

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 2m 01s

cargo test -p calternal-collab -- --test-threads=2 (exit 0):

test result: ok. 25 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 8.82s
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.38s
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 4.71s
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 73.91s
test result: ok. 11 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 10.88s
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.06s
test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 4.60s
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 11.31s
test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 4.10s
test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 47.70s
test result: ok. 15 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.06s
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.68s
test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 21.24s
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

Changed files

  • crates/calternal-fs/src/lib.rs: test-only module registration.
  • crates/calternal-fs/src/review_case_crash.rs: SIGKILL worker and replay test.
  • crates/calternal-fs/tests/voice_memos_review.rs: name classes and symlink check.
  • crates/calternal-notes-core/tests/voice_memos_review.rs: byte boundaries and stale forms.
  • crates/plugins/files/src/lib.rs: test-only module registration.
  • crates/plugins/files/src/tests/voice_memos_review.rs: merge defects, partial replay, profiles.
  • crates/calternal-collab/tests/voice_memos_review.rs: dirty-room external rewrite check.
  • review-findings.md: verdict, evidence, limits and exact gate summaries.

Module comments and the comments of each new test/helper were read again before
this report. No push, deployment, owner-data edit, screenshot or video was made.

Cleanup output, verbatim:

     Removed 10487 files, 6.2GiB total

No web build output was created.

Final independent review: **NO-GO**. Branch: `job/voicememos-review`. Final head: `9200c49b516148d6b78a70650b0443ec4539fbf4`. Reviewed product target: `df30c35a487a0a3eb9aedacbf102beec79e0050a`. Five atomic review commits; tests and report only. All final per-crate gates passed. The passing characterization tests confirm defects; they do not approve the product repair. Build output was cleaned. No push, deployment or owner-data edit. # Voice Memos data-integrity review Verdict: **NO-GO** for #618/#621 at `df30c35a487a0a3eb9aedacbf102beec79e0050a`. Do not run this repair on the owner's Home until the link-identity defect and recording identity / Security state deletion are fixed. This review changes tests and this report only. It makes no product fix. ## Blocking finding: a link changes recording identity Files: `crates/plugins/files/src/lib.rs`, `move_indexed`, `move_voice_memo_path`, and `migrate_voice_memo_home`. Fixture: both Voice Memos spellings contain `shared.m4a`. The legacy file has newer bytes and modification time. The canonical file has older bytes. A Note has one link to each file. The repair keeps the older recording at a conflict-copy path. It moves the newer recording to the canonical shared path. Both byte contents and both file IDs survive. But **both Note links end at the older conflict-copy path**. The link that named the newer recording now plays the older recording. Cause: `move_indexed` rewrites links after each move. At the end, `migrate_voice_memo_home` applies the collected mappings again. The second canonical shared path to conflict-copy mapping catches a link that the legacy shared path to canonical shared path move already changed. Evidence: `review_twin_merge_redirects_newer_recording_link_to_older_copy` in `crates/plugins/files/src/tests/voice_memos_review.rs`. The test compares the whole Note with the observed incorrect output. It also checks file bytes, IDs, CRLF, frontmatter order, unrelated text, and a second run. Required fix: define one replay-safe link transaction that retains the original recording identity. Remove the repeated application of overlapping move mappings. Test both modification-time orders and a restart during each Note write. Do not clear a move intent until its link changes and Index updates are complete. ## Other findings 1. **Blocking: an older source loses Index identity and Security state.** Its conflict copy is made in the legacy folder. The merge does not visit that new entry. It then removes the folder's Index row and tries to remove the nonempty folder. The call fails with `Directory not empty (os error 39)`. The Index deletion is recursive: it also removes the conflict copy's file row, Shares and public links. Bytes survive, but a second run must assign a new recording ID. Security state cannot be rebuilt from recording bytes. The extended test checks all three deletions and the changed ID: `review_older_source_loses_file_id_and_leaves_legacy_folder`. The test passed. Keep the conflict copy at its final destination before folder removal. Do not delete any live descendant's identity or grants. 2. **Two legacy twins without the canonical spelling cannot migrate.** The chosen primary folder's rename meets the normal sibling case-conflict gate. Both attempts return `name_conflict_case`. Neither recording changes. Test: `review_two_legacy_twins_without_canonical_cannot_start`. The recovery path must handle this existing state without weakening the normal new-name gate. 3. **Two Markdown destination forms remain stale.** Percent-encoded paths such as `Documents/Voice%20memos/a.m4a` and reference definitions such as `[audio]: <Documents/Voice memos/a.m4a>` do not change. Their recording can move while the link retains the legacy destination. Test: `review_encoded_and_reference_destinations_remain_stale`. Extend the shared scanner and test the decoded component boundary before the repair runs. 4. **The repair has no hash-based file deduplication.** A file collision always keeps a conflict copy, even for identical content. This avoids an unchecked deletion. The Index deletion defect above can still lose file IDs. The condition “dedupe only when hashes match” is met because this merge deletes no colliding file. Do not describe this merge as hash-based deduplication. Merged source directory IDs are removed; the tested ID guarantee applies to recordings, not to both twin folders. 5. **Legacy invalid new names stop a merge.** New-name normalization rejects trailing spaces and dots. The merge passes each existing child name to this policy. It can therefore stop on imported names. A decomposed name can also fail when it is used as a new destination without NFC normalization. This is a safe abort, not evidence of escape or byte loss. These merge branches were inspected; the name-policy tests exercise the normalization boundary. 6. **There is no durable “done once” flag.** Each `FilesState::reconcile_all` calls the repair. A canonical-only Home incurs a directory check and no link scan. A completed repair is cheap to retry, but it is not permanently disabled. A later legacy folder can trigger it again. ## Confirmed behavior and limits - Distinct same-name recording bytes and file IDs survive the tested merge when the legacy recording is newer. The existing twin-merge test and the new link-identity test check this. - Pure inline Markdown rewrites preserve CRLF, frontmatter order, Unicode, unrelated links, code examples, labels, query strings and anchors in the fixtures. The matching folder prefix has a component boundary. A simple folder rename is idempotent. - A restart after the physical folder rename and one of two Note writes completes both Note and Daily note Log links. The reopened Root and Files state retain folder and recording IDs. Repeated reconciliation preserves the resulting bytes. Test: `review_partial_note_rewrite_replays_after_reopen`. - A worker is killed with SIGKILL after journal publication, after the temporary rename, and after the final rename. Fresh Root recovery finishes each case, retains the recording bytes and inode, removes the temporary name, and is safe on a second replay. Test: `review_sigkill_at_each_case_rename_boundary`. - Root uses `openat2` with `BENEATH`, `NO_SYMLINKS` and `NO_MAGICLINKS`. Namespace changes use held parent handles with `renameat_with`. The review found formatted relative names, but not an ambient filesystem move built from User input. RelPath/InternalPath validate these names before handle resolution. A legacy symlink is rejected and its external target is unchanged. - Folding is **NFC, then default full non-Turkic Unicode case folding**, not simple folding. The code documents it in `calternal-fs/src/path.rs`. Tests cover NFC/NFD equivalence, `ß`/`SS`, ASCII `I`/`i`, dotless `ı`, dotted `İ`, and trailing spaces/dots. This is not evidence from an APFS filesystem. - The repair holds the Home Notes lock and uses a content-hash checked update. It emits Notes invalidations, which the real Hub consumes as external edits. The live-room fixture passed: its live edit, last line, and rewritten attachment each appeared once after duplicate invalidations and a flush. A Hub test is not a browser typing test for all #634 scenarios. This is **not** a proof of crash safety at every multi-file merge boundary. There is no exhaustive SIGKILL matrix for conflict copies, Sidecars, all SQL commit points, every Note write, or power failure during fsync. The three case-rename namespace boundaries and the partial Note replay are covered. The failing identity case alone is enough to block this repair. ## Performance Local debug measurement, shared host, one run with a cached fixture: 100,000 non-Markdown files in Archive and an empty legacy Voice Memos folder. Fixture creation and normal Files indexing are outside the repair timer. | Repair phase | Elapsed | Kernel read bytes delta | Kernel write bytes delta | |---|---:|---:|---:| | First repair | 4,806.097 ms | 0 | 307,200 | | Canonical-only retry | 0.241 ms | 0 | 0 | The process used 1.986 s user CPU and 5.023 s system CPU with 39,472 KiB peak RSS. These process totals include fixture creation, schema setup and cleanup; they are not repair-only CPU/RSS. The full test took 23.65 s. Initial load was 29.25 / 25.14 / 22.86; final load was 31.65 / 26.15 / 23.30. `/proc/self/io` counts disk bytes charged to the process. Cached metadata operations are not proof of zero filesystem work. This profile does not include 100k moved files, linked Notes, conflicts, or a cold filesystem. The affected-folder profile placed 100,000 flat files in the legacy Voice Memos folder and an empty canonical twin beside it. It reached the 30-second bound at **30,008.512 ms**, with only **7 files moved** and 99,993 still in the legacy folder. All 100,000 directory entries remained present. The profile did not complete the repair and did not claim to verify every file's hash or ID. Kernel read-byte delta was 0; write-byte delta was 2,555,904, with 491,520 cancelled write bytes. Process totals, including fixture creation and cleanup: 11.616 s user CPU, 8.111 s system CPU, 98,112 KiB peak RSS, 53.85 s test time. Final host load was 21.13 / 18.78 / 20.72. This is a local debug result from a busy host, not a quiet release measurement. It does not support a claim that repair is cheap for 100k affected files. This SLOW result is not itself a merge blocker. The perf VM lock check succeeded. No exact-target release server was available. The host's shared release binary lacks this migration's completion marker, so its target revision could not be verified and it was not used for this review. No server was deployed or compiled on the perf VM. `docs/perf/baseline.json` has no Voice Memos migration scenario. There is no matching baseline or threshold comparison. The earlier job's local debug profile in `docs/perf/2026-10-02-voice-memos.md` reports 134,307 ms for 128 legacy files, 8 conflicts and 16 linked Notes; it is context, not this review's result. Code review explains the scaling concern: each moved item calls the Notes rewrite, which walks all visible Home entries. The merge also reads the target folder for each child. A flat twin merge can require quadratic directory work and repeated full Home scans. The final batch adds another scan. ## Decisions - Keep product behavior unchanged. Record defects with explicitly named characterization tests. A passing defect test confirms the defect; it is not an acceptance gate. Replace its observed-defect assertion with the intended invariant when the implementation is fixed. - Use process kills only in disposable test Homes. Test partial Note replay through a fresh Root rather than add a product fault-injection API. - Bound the large twin workload. Do not wait for an unbounded 100k-file merge. - Use exact-target local measurements when the shared release does not contain the target change. Label all measurements and their limits. ## UX gaps closed None. This is a tests and code review job. ## UX gaps left The link-identity defect can make a Note play the wrong recording. The merge abort cases leave repair incomplete. No UI was changed or visually reviewed. ## Validation The test head is `335a5fcfe821ddf28089e46fc7322b58b56d02a1`. The final report commit follows this head. Review branch: `job/voicememos-review`. Before the final gates, `git fetch origin` succeeded and `git merge origin/dev` returned, verbatim: ```text Already up to date. ``` The fetched dev head was `c4a61e8cf090170f35b1bed3350d9de20c83ecd5`, already an ancestor of the reviewed target. No product merge commit was made. All cargo commands used `CARGO_PROFILE_DEV_DEBUG=line-tables-only`, `CARGO_INCREMENTAL=0`, `CARGO_BUILD_JOBS=4` and this worktree's `target/tmp` for `TMPDIR`. The preset `CARGO_TARGET_DIR` was not changed. No dependency version or lockfile was changed. No web or server route code was changed. `cargo fmt --check`: no output, exit 0. `git diff --check`: no output, exit 0. An initial filesystem clippy run found a type error in the new child-worker fixture. It was corrected before the filesystem tests. The corrected clippy output appears below. No existing test expectation was changed. The following are verbatim summary lines from the final gate logs. Complete logs remain in the gitignored `artifacts/` directory. These are per-crate gates, not workspace gates. The large-Home profile ran alone as an explicit ignored test. The ignored SIGKILL worker ran through its parent test. The existing 10k-file rclone opt-in test was not run. `cargo clippy -p calternal-fs --all-targets -- -D warnings` (exit 0): ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 3.39s ``` `cargo test -p calternal-fs -- --test-threads=2` (exit 0): ```text test result: ok. 53 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 24.43s test result: ok. 44 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 11.95s test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.05s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ``` `cargo clippy -p calternal-notes-core --all-targets -- -D warnings` (exit 0): ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 26.95s ``` `cargo test -p calternal-notes-core -- --test-threads=2` (exit 0): ```text test result: ok. 521 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.79s test result: ok. 19 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 7.52s test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.11s test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.64s test result: ok. 12 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.02s test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s 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` (exit 0): ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 1m 49s ``` `cargo test -p calternal-plugin-files -- --test-threads=2` (exit 0): ```text test result: ok. 157 passed; 0 failed; 2 ignored; 0 measured; 0 filtered out; finished in 245.87s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ``` `cargo clippy -p calternal-collab --all-targets -- -D warnings` (exit 0): ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 2m 01s ``` `cargo test -p calternal-collab -- --test-threads=2` (exit 0): ```text test result: ok. 25 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 8.82s test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.38s test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 4.71s test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 73.91s test result: ok. 11 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 10.88s test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.06s test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 4.60s test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 11.31s test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 4.10s test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 47.70s test result: ok. 15 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.06s test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.68s test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 21.24s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ``` ## Changed files - `crates/calternal-fs/src/lib.rs`: test-only module registration. - `crates/calternal-fs/src/review_case_crash.rs`: SIGKILL worker and replay test. - `crates/calternal-fs/tests/voice_memos_review.rs`: name classes and symlink check. - `crates/calternal-notes-core/tests/voice_memos_review.rs`: byte boundaries and stale forms. - `crates/plugins/files/src/lib.rs`: test-only module registration. - `crates/plugins/files/src/tests/voice_memos_review.rs`: merge defects, partial replay, profiles. - `crates/calternal-collab/tests/voice_memos_review.rs`: dirty-room external rewrite check. - `review-findings.md`: verdict, evidence, limits and exact gate summaries. Module comments and the comments of each new test/helper were read again before this report. No push, deployment, owner-data edit, screenshot or video was made. Cleanup output, verbatim: ```text Removed 10487 files, 6.2GiB total ``` No web build output was created.
Author
Owner

Round 2 started on job/voicememos-618, base df30c35a487a0a3eb9aedacbf102beec79e0050a. Imported the independent review tests from 9200c49b5 unchanged. Fixing repeated link mappings and conflict copies left under a removed Index subtree, then moving repair to bounded durable Jobs. No push or deploy.

Round 2 started on `job/voicememos-618`, base `df30c35a487a0a3eb9aedacbf102beec79e0050a`. Imported the independent review tests from `9200c49b5` unchanged. Fixing repeated link mappings and conflict copies left under a removed Index subtree, then moving repair to bounded durable Jobs. No push or deploy.
Author
Owner

Round 2 findings and decisions:

  • Removed the second application of overlapping move mappings. A landed move retains its pending intent through Note/Log rewrites and Tags, then commits Item ID and Share/public-link paths.
  • Conflict copies now use the final target directory. Physical empty-directory removal succeeds before recursive Index cleanup, so a nonempty source cannot lose recording identities or grants.
  • Existing twins without the canonical spelling merge before the final case rename. The ordinary new-name gate stays in force.
  • The review also exposed encoded and reference-style destinations; their unchanged fixtures now assert the repaired destination while retaining all unrelated-byte checks.
  • Tag metadata (.calternal.json) must not move ahead of its recordings. The existing Tags writer moves each key; the regression checks its source and Index assignment.
  • Decision: register files.voice-memos-repair in the existing durable Jobs runner, private to its User. Each batch allows at most eight primary moves (a collision may need one extra displacement), checks a two-second soft budget between atomic moves and releases the namespace lock. Completed move intents are the durable cursor, so no directory offset survives a mutation or restart. Startup only queues repair. The shared Jobs view supplies progress, stop/retry, deep links and Copy link.
  • A minimal public Notes helper accepts reconciled Markdown path hints. It reuses the existing hash-checked writer and live-room invalidations; ordinary Files moves retain their Home scan. Repair uses paged source listing and indexed Sidecar hints after reconciliation.

Validation is compiling on the shared host. No dependency version or migration number changed. No push or deploy.

Round 2 findings and decisions: - Removed the second application of overlapping move mappings. A landed move retains its pending intent through Note/Log rewrites and Tags, then commits Item ID and Share/public-link paths. - Conflict copies now use the final target directory. Physical empty-directory removal succeeds before recursive Index cleanup, so a nonempty source cannot lose recording identities or grants. - Existing twins without the canonical spelling merge before the final case rename. The ordinary new-name gate stays in force. - The review also exposed encoded and reference-style destinations; their unchanged fixtures now assert the repaired destination while retaining all unrelated-byte checks. - Tag metadata (`.calternal.json`) must not move ahead of its recordings. The existing Tags writer moves each key; the regression checks its source and Index assignment. - Decision: register `files.voice-memos-repair` in the existing durable Jobs runner, private to its User. Each batch allows at most eight primary moves (a collision may need one extra displacement), checks a two-second soft budget between atomic moves and releases the namespace lock. Completed move intents are the durable cursor, so no directory offset survives a mutation or restart. Startup only queues repair. The shared Jobs view supplies progress, stop/retry, deep links and Copy link. - A minimal public Notes helper accepts reconciled Markdown path hints. It reuses the existing hash-checked writer and live-room invalidations; ordinary Files moves retain their Home scan. Repair uses paged source listing and indexed Sidecar hints after reconciliation. Validation is compiling on the shared host. No dependency version or migration number changed. No push or deploy.
Author
Owner

Round 2 finding: delaying the repair exposed a recording failure while case twins remain. Tus creation used to reject the ambiguous folder with 409. The repair now persists the chosen folder Item ID in the queued Job, and routed recording uploads use that ID under the existing Home writer lock. Upload finalization already follows its stored parent Item ID across folder moves. Added a regression for both canonical-present and two-legacy-folder fixtures. No UI source or new endpoint is required; existing Background Work renders the registered Job.

Build validation is running with four compiler workers. The shared compiler cache caused long waits; this worktree now uses direct compiler calls.

Round 2 finding: delaying the repair exposed a recording failure while case twins remain. Tus creation used to reject the ambiguous folder with 409. The repair now persists the chosen folder Item ID in the queued Job, and routed recording uploads use that ID under the existing Home writer lock. Upload finalization already follows its stored parent Item ID across folder moves. Added a regression for both canonical-present and two-legacy-folder fixtures. No UI source or new endpoint is required; existing Background Work renders the registered Job. Build validation is running with four compiler workers. The shared compiler cache caused long waits; this worktree now uses direct compiler calls.
Author
Owner

Validation progress: Files compiled without reported Rust errors and reached test-binary linking. At 15:44 UTC, its linker chain was cc → collect2 → ld.lld (shell wrapper) → ld-wrapper.sh; the wrapper child showed 0 CPU time after about eight minutes elapsed. The shared host linker coordination remains in force. Per-crate gates and the real-server build are queued. Source includes regressions for Calendar attachment projection, stopped-repair recording routing, and empty-directory batch bounds.

Validation progress: Files compiled without reported Rust errors and reached test-binary linking. At 15:44 UTC, its linker chain was `cc → collect2 → ld.lld (shell wrapper) → ld-wrapper.sh`; the wrapper child showed 0 CPU time after about eight minutes elapsed. The shared host linker coordination remains in force. Per-crate gates and the real-server build are queued. Source includes regressions for Calendar attachment projection, stopped-repair recording routing, and empty-directory batch bounds.
Author
Owner

Head: 6c47ebb8e. Focused integrity validation is green. Both independent NO-GO fixtures now assert identity preservation, with their original byte-sensitive recording and Note fixtures retained. Also green: partial Note rewrite replay in both conflict orders, restart between batches, persisted primary identity after an mtime change, retained Tags and Calendar attachment projection, recording while queued or stopped, Notes inside the moved folder, and empty-directory batch bounds.

Command: cargo test -p calternal-plugin-files voice_memo -- --test-threads=2

test result: ok. 17 passed; 0 failed; 2 ignored; 0 measured; 147 filtered out; finished in 364.78s

The two ignored tests are explicit 100k-file profiles. Full per-crate gates, the process-kill filesystem replay suite and the real-server evidence build remain in progress. No push, deploy or merge.

Head: `6c47ebb8e`. Focused integrity validation is green. Both independent NO-GO fixtures now assert identity preservation, with their original byte-sensitive recording and Note fixtures retained. Also green: partial Note rewrite replay in both conflict orders, restart between batches, persisted primary identity after an mtime change, retained Tags and Calendar attachment projection, recording while queued or stopped, Notes inside the moved folder, and empty-directory batch bounds. Command: `cargo test -p calternal-plugin-files voice_memo -- --test-threads=2` ```text test result: ok. 17 passed; 0 failed; 2 ignored; 0 measured; 147 filtered out; finished in 364.78s ``` The two ignored tests are explicit 100k-file profiles. Full per-crate gates, the process-kill filesystem replay suite and the real-server evidence build remain in progress. No push, deploy or merge.
Author
Owner

Round 2 report — implemented; full validation incomplete at the four-hour limit.

Branch: job/voicememos-618. Head: 8f929eefc6d512c520f784a1ac63cd628f85b866.

Built:

  • Each recording move rewrites only its own link mapping. The final overlapping mapping replay is removed. Newer and older recording links retain their original Item ID targets.
  • An older source moves directly to a conflict name in the final directory. Physical folder removal succeeds before Index cleanup. Recording Item IDs, Shares, public links, Tags and Calendar attachment targets survive retry.
  • Startup queues a durable private files.voice-memos-repair Job. Small batches release the Home writer. Move intents and remaining source entries support restart. The chosen folder Item ID is persisted before work starts.
  • Recording uses that folder identity while repair is queued or stopped. Existing Background Work supplies the Job view, progress and controls. Markdown support now covers encoded and reference destinations without changing unrelated bytes.

The independent tests were imported unchanged from 9200c49b5 in 5aea05d05. Their defect-characterization expectations were then changed to the correct invariants required by this issue; original byte-sensitive fixtures and grant checks remain. No unrelated existing expectation was changed.

Files:

bench/voice-memo-batches-618.sh
crates/calternal-collab/tests/voice_memos_review.rs
crates/calternal-fs/src/lib.rs
crates/calternal-fs/src/review_case_crash.rs
crates/calternal-fs/tests/voice_memos_review.rs
crates/calternal-notes-core/src/links.rs
crates/calternal-notes-core/tests/voice_memos_review.rs
crates/plugins/files/src/index.rs
crates/plugins/files/src/lib.rs
crates/plugins/files/src/tests/voice_memos_review.rs
crates/plugins/files/src/uploads.rs
crates/plugins/notes/src/lib.rs
docs/DESIGN.md
docs/perf/2026-10-02-voice-memos-round2.md

Completed checks, with output verbatim:

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

cargo clippy -p calternal-notes-core --all-targets -- -D warnings:

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 8m 51s

cargo test -p calternal-notes-core:

test result: ok. 521 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.61s
test result: ok. 19 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 12.21s
test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.22s
test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 7.65s
test result: ok. 12 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s
test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
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 77m 54s

Focused Files integrity/replay tests:

test result: ok. 17 passed; 0 failed; 2 ignored; 0 measured; 147 filtered out; finished in 364.78s

100k-file bounded profile:

100k queue p50_ms=33.448 p95_ms=50.931; batch p50_ms=5942.611 p95_ms=14987.863; moved=4
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 165 filtered out; finished in 231.86s

Production web build completed:

✓ built in 6m 9s

Known gaps / remaining checks:

  • The full Files suite was still running at the time limit. No failure was reported in its output before it was stopped. This is not a full-suite pass.
  • Notes, Filesystem, Collab and Server per-crate gates remain incomplete. The imported filesystem SIGKILL replay suite and Collab live-room review test have not run. The plugin-level interrupted Note-write and restart tests are green.
  • The server build did not finish. No real-server adversarial round, real-server average/upload-burst profile, or macOS screenshot set was completed. Do not treat this branch as merge-validated.
  • The two-second batch budget is soft: one atomic move can exceed it. The 100k local profile indexes folders only, as the independent profile did; it includes lazy file adoption. It measures three batches, not full completion. There is no matched Voice Memos scenario in docs/perf/baseline.json, so no baseline regression can be established.

Performance: local shared host, load 134.09 before / 145.10 after. Whole-test CPU was 0.773 s user + 6.893 s system; sampled mean RSS 42,304,492 bytes, peak 43,962,368 bytes. Resources include fixture setup and cleanup. Details and limits are in docs/perf/2026-10-02-voice-memos-round2.md.

UX gaps closed: recording remains available during queued repair and after Stop; primary choice cannot oscillate after a restart; each committed move publishes Files refresh events. Calendar's attachment projection retains the recording target and Item ID in the regression.

UX gaps left: Jobs controls and layout still require a real production screenshot walk at phone, tablet and desktop widths in both themes with macOS rendering. The prepared screenshot runner is in ignored artifacts/voice-memo-jobs-macos.mjs; no screenshot artifacts were committed.

Decisions:

  • Reuse existing private Jobs and Background Work instead of adding a screen or endpoint.
  • Bound work by eight changes and a two-second check between atomic moves; count empty folder merges. A collision can require one extra displacement. Release the writer between batches.
  • Persist the destination Item ID at enqueue time; canonical spelling wins, otherwise use the newest folder. Stop controls repair, not recording availability.
  • Use reconciled Markdown/Sidecar hints for repair; ordinary moves retain their filesystem fallback. Keep non-replacing Tag writes inside the move intent; retain existing replacement ordering.

One git fetch origin / git merge origin/dev refresh was done before gates and returned Already up to date. No dependencies or migrations changed. No push, deploy, issue close or promotion was done. The shared compiler/linker queues consumed most of the time budget. Commits preserve completed source; some were made while full execution gates were pending, as reported during the job.

Round 2 report — implemented; full validation incomplete at the four-hour limit. Branch: `job/voicememos-618`. Head: `8f929eefc6d512c520f784a1ac63cd628f85b866`. Built: - Each recording move rewrites only its own link mapping. The final overlapping mapping replay is removed. Newer and older recording links retain their original Item ID targets. - An older source moves directly to a conflict name in the final directory. Physical folder removal succeeds before Index cleanup. Recording Item IDs, Shares, public links, Tags and Calendar attachment targets survive retry. - Startup queues a durable private `files.voice-memos-repair` Job. Small batches release the Home writer. Move intents and remaining source entries support restart. The chosen folder Item ID is persisted before work starts. - Recording uses that folder identity while repair is queued or stopped. Existing Background Work supplies the Job view, progress and controls. Markdown support now covers encoded and reference destinations without changing unrelated bytes. The independent tests were imported unchanged from `9200c49b5` in `5aea05d05`. Their defect-characterization expectations were then changed to the correct invariants required by this issue; original byte-sensitive fixtures and grant checks remain. No unrelated existing expectation was changed. Files: ```text bench/voice-memo-batches-618.sh crates/calternal-collab/tests/voice_memos_review.rs crates/calternal-fs/src/lib.rs crates/calternal-fs/src/review_case_crash.rs crates/calternal-fs/tests/voice_memos_review.rs crates/calternal-notes-core/src/links.rs crates/calternal-notes-core/tests/voice_memos_review.rs crates/plugins/files/src/index.rs crates/plugins/files/src/lib.rs crates/plugins/files/src/tests/voice_memos_review.rs crates/plugins/files/src/uploads.rs crates/plugins/notes/src/lib.rs docs/DESIGN.md docs/perf/2026-10-02-voice-memos-round2.md ``` Completed checks, with output verbatim: `cargo fmt --check`: exit 0, no output. `cargo clippy -p calternal-notes-core --all-targets -- -D warnings`: ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 8m 51s ``` `cargo test -p calternal-notes-core`: ```text test result: ok. 521 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.61s test result: ok. 19 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 12.21s test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.22s test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 7.65s test result: ok. 12 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s 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 77m 54s ``` Focused Files integrity/replay tests: ```text test result: ok. 17 passed; 0 failed; 2 ignored; 0 measured; 147 filtered out; finished in 364.78s ``` 100k-file bounded profile: ```text 100k queue p50_ms=33.448 p95_ms=50.931; batch p50_ms=5942.611 p95_ms=14987.863; moved=4 test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 165 filtered out; finished in 231.86s ``` Production web build completed: ```text ✓ built in 6m 9s ``` Known gaps / remaining checks: - The full Files suite was still running at the time limit. No failure was reported in its output before it was stopped. This is not a full-suite pass. - Notes, Filesystem, Collab and Server per-crate gates remain incomplete. The imported filesystem SIGKILL replay suite and Collab live-room review test have not run. The plugin-level interrupted Note-write and restart tests are green. - The server build did not finish. No real-server adversarial round, real-server average/upload-burst profile, or macOS screenshot set was completed. Do not treat this branch as merge-validated. - The two-second batch budget is soft: one atomic move can exceed it. The 100k local profile indexes folders only, as the independent profile did; it includes lazy file adoption. It measures three batches, not full completion. There is no matched Voice Memos scenario in `docs/perf/baseline.json`, so no baseline regression can be established. Performance: local shared host, load 134.09 before / 145.10 after. Whole-test CPU was 0.773 s user + 6.893 s system; sampled mean RSS 42,304,492 bytes, peak 43,962,368 bytes. Resources include fixture setup and cleanup. Details and limits are in `docs/perf/2026-10-02-voice-memos-round2.md`. UX gaps closed: recording remains available during queued repair and after Stop; primary choice cannot oscillate after a restart; each committed move publishes Files refresh events. Calendar's attachment projection retains the recording target and Item ID in the regression. UX gaps left: Jobs controls and layout still require a real production screenshot walk at phone, tablet and desktop widths in both themes with macOS rendering. The prepared screenshot runner is in ignored `artifacts/voice-memo-jobs-macos.mjs`; no screenshot artifacts were committed. Decisions: - Reuse existing private Jobs and Background Work instead of adding a screen or endpoint. - Bound work by eight changes and a two-second check between atomic moves; count empty folder merges. A collision can require one extra displacement. Release the writer between batches. - Persist the destination Item ID at enqueue time; canonical spelling wins, otherwise use the newest folder. Stop controls repair, not recording availability. - Use reconciled Markdown/Sidecar hints for repair; ordinary moves retain their filesystem fallback. Keep non-replacing Tag writes inside the move intent; retain existing replacement ordering. One `git fetch origin` / `git merge origin/dev` refresh was done before gates and returned `Already up to date.` No dependencies or migrations changed. No push, deploy, issue close or promotion was done. The shared compiler/linker queues consumed most of the time budget. Commits preserve completed source; some were made while full execution gates were pending, as reported during the job.
Author
Owner

Correction to the final report: the full Files log contains this failure, found during final log inspection:

test tests::internal_temp_paths_never_enter_index_during_atomic_write_reconcile_storm ... FAILED

The previous “no failure was reported” statement was wrong. The suite was interrupted before its captured failure diagnostics were printed. The failure remains unresolved and unclassified; it is not established as SLOW. Do not merge on the focused-test result. Full per-crate gates, filesystem SIGKILL / Collab review tests, server checks and visual evidence remain incomplete as listed above.

Cleanup completed: cargo clean output was Removed 9807 files, 4.0GiB total; verified generated web output was removed. Working tree is clean. Head remains 8f929eefc6d512c520f784a1ac63cd628f85b866. No test expectation was changed to hide this failure.

Correction to the final report: the full Files log contains this failure, found during final log inspection: ```text test tests::internal_temp_paths_never_enter_index_during_atomic_write_reconcile_storm ... FAILED ``` The previous “no failure was reported” statement was wrong. The suite was interrupted before its captured failure diagnostics were printed. The failure remains unresolved and unclassified; it is not established as SLOW. Do not merge on the focused-test result. Full per-crate gates, filesystem SIGKILL / Collab review tests, server checks and visual evidence remain incomplete as listed above. Cleanup completed: `cargo clean` output was ` Removed 9807 files, 4.0GiB total`; verified generated web output was removed. Working tree is clean. Head remains `8f929eefc6d512c520f784a1ac63cd628f85b866`. No test expectation was changed to hide this failure.
Author
Owner

Read-only review starts on job/rev2-voicememos-618, base 440e19dce23040ac8ebaae88f0469b6535b1afcb.

Target: origin/dev...8f929eefc in job/voicememos-618. Scope: recording identity in conflict moves and repair jobs. I will read code and tests only. The LIGHT review rule prohibits builds, tests, servers and browsers. I will commit audit-findings.md and review-voicememos-618.md in the review worktree.

Read-only review starts on `job/rev2-voicememos-618`, base `440e19dce23040ac8ebaae88f0469b6535b1afcb`. Target: `origin/dev...8f929eefc` in `job/voicememos-618`. Scope: recording identity in conflict moves and repair jobs. I will read code and tests only. The LIGHT review rule prohibits builds, tests, servers and browsers. I will commit `audit-findings.md` and `review-voicememos-618.md` in the review worktree.
Author
Owner

Independent read-only review completed. Target: 8f929eefc. Review head: c284a0dcbe53fb70d0fb3353d883d41410037292 on job/rev2-voicememos-618.

Request changes.

  • P1 — Same-process repair retry can delete recording identity and grants. crates/plugins/files/src/lib.rs:1446, :1607-1628; crates/plugins/files/src/index.rs:1436-1449. A rename can land before a Note rewrite fails. The Job retry does not replay its pending move. It can remove the empty legacy folder and delete the old recording row, Share and public link, then report success with the move still pending. Fix: reuse pending-move recovery under the namespace lock before retry and prevent source cleanup while intents remain. Test: fail one Note write after rename, retry without restart or full reconciliation, and assert the original item ID and grants. Existing restart fixtures miss this case. This evidence belongs to #618.
  • P2 — Folder merges invalidate active upload parents. crates/plugins/files/src/lib.rs:1619-1628, :1789-1803; crates/plugins/files/src/uploads.rs:1416-1430. A ticket opened against the legacy or a nested source folder loses its parent ID when repair merges that directory away. Its final PATCH returns 412. Fix: retain the source while uploads are active, or use a User-scoped merge mapping to update tickets under the writer lock; keep preconditions and authorization. Test POST → repair → final PATCH, including nested, target-collision and second-User cases. Filed as #904, after searching existing issues and reading #627.

Built/files: audit-findings.md and review-voicememos-618.md, committed in two atomic documentation commits. No product changes. No new cross-User access defect or weakened expectation found in the inspected diff. No P3 defect reported.

Gate output verbatim: none — no gate was run. The LIGHT contract prohibits builds, tests, servers and browsers. git diff --check returned exit 0 with no output. No push, deploy or merge ran. There was no build output to clean.

Known gaps: the two findings are source traces, not executed reproductions. They need focused regression tests and fixes. Performance and Apple-client checks did not run. UX gaps closed: none. UX gaps left: paused recording uploads can fail after a merge (P2).

Decisions: no new product design. P1 remains on #618. P2 is #904 because its active-upload merge fix differs from #627's re-index fix. Target DESIGN ends at §57; the brief's §58 is absent. Performance inspection used §§2, 6 and 40 and owner rules.

For the merge round, after adding regressions, run with the required Cargo environment:

cargo test -p calternal-plugin-files voice_memos_review
cargo test -p calternal-fs review_case_crash
cargo test -p calternal-notes-core --test voice_memos_review
cargo test -p calternal-collab --test voice_memos_review

Prove bytes, item IDs, Shares, public links, Note targets and live edits survive restart and same-process retry. The first command must include the new failed-move retry and paused-upload tests. The merge round owns full gates and server adversarial checks.

Independent read-only review completed. Target: `8f929eefc`. Review head: `c284a0dcbe53fb70d0fb3353d883d41410037292` on `job/rev2-voicememos-618`. Request changes. - **P1 — Same-process repair retry can delete recording identity and grants.** `crates/plugins/files/src/lib.rs:1446`, `:1607-1628`; `crates/plugins/files/src/index.rs:1436-1449`. A rename can land before a Note rewrite fails. The Job retry does not replay its pending move. It can remove the empty legacy folder and delete the old recording row, Share and public link, then report success with the move still pending. Fix: reuse pending-move recovery under the namespace lock before retry and prevent source cleanup while intents remain. Test: fail one Note write after rename, retry without restart or full reconciliation, and assert the original item ID and grants. Existing restart fixtures miss this case. This evidence belongs to #618. - **P2 — Folder merges invalidate active upload parents.** `crates/plugins/files/src/lib.rs:1619-1628`, `:1789-1803`; `crates/plugins/files/src/uploads.rs:1416-1430`. A ticket opened against the legacy or a nested source folder loses its parent ID when repair merges that directory away. Its final PATCH returns 412. Fix: retain the source while uploads are active, or use a User-scoped merge mapping to update tickets under the writer lock; keep preconditions and authorization. Test POST → repair → final PATCH, including nested, target-collision and second-User cases. Filed as [#904](https://git.kayg.org/kayg/calternal/issues/904), after searching existing issues and reading #627. Built/files: `audit-findings.md` and `review-voicememos-618.md`, committed in two atomic documentation commits. No product changes. No new cross-User access defect or weakened expectation found in the inspected diff. No P3 defect reported. Gate output verbatim: **none — no gate was run.** The LIGHT contract prohibits builds, tests, servers and browsers. `git diff --check` returned exit 0 with no output. No push, deploy or merge ran. There was no build output to clean. Known gaps: the two findings are source traces, not executed reproductions. They need focused regression tests and fixes. Performance and Apple-client checks did not run. UX gaps closed: none. UX gaps left: paused recording uploads can fail after a merge (P2). Decisions: no new product design. P1 remains on #618. P2 is #904 because its active-upload merge fix differs from #627's re-index fix. Target DESIGN ends at §57; the brief's §58 is absent. Performance inspection used §§2, 6 and 40 and owner rules. For the merge round, after adding regressions, run with the required Cargo environment: ```sh cargo test -p calternal-plugin-files voice_memos_review cargo test -p calternal-fs review_case_crash cargo test -p calternal-notes-core --test voice_memos_review cargo test -p calternal-collab --test voice_memos_review ``` Prove bytes, item IDs, Shares, public links, Note targets and live edits survive restart and same-process retry. The first command must include the new failed-move retry and paused-upload tests. The merge round owns full gates and server adversarial checks.
Author
Owner

Round 3 starts on job/voicememos-618, base 8f929eefc6d512c520f784a1ac63cd628f85b866. Read the independent review at c284a0dcbe53fb70d0fb3353d883d41410037292. Fix P1 retry recovery and P2 active-upload parent retention with focused regressions first. The latest verification policy assigns full e2e/adversarial matrices, release builds, Mac interop and non-performance-issue measurements to the merge round. No push or deployment.

Round 3 starts on `job/voicememos-618`, base `8f929eefc6d512c520f784a1ac63cd628f85b866`. Read the independent review at `c284a0dcbe53fb70d0fb3353d883d41410037292`. Fix P1 retry recovery and P2 active-upload parent retention with focused regressions first. The latest verification policy assigns full e2e/adversarial matrices, release builds, Mac interop and non-performance-issue measurements to the merge round. No push or deployment.
Author
Owner

Round 3 source findings:

  • P1: migrate_voice_memo_home walks disk entries without index::recover_moves. A rename followed by a failed Note write leaves the old Index prefix and grants under a now-empty source folder. A same-process retry can remove that prefix. The new fixture denies writes to Notes for one attempt and retries the real Job handler with the stored payload; it checks Item IDs, both grant kinds, bytes, Note targets and pending intents in an empty-target case and both conflict orders.
  • Folder reconciliation also needs recovery under its namespace lock. Full reconciliation drops that lock between move recovery and its scan; it must replay any newly failed move after it acquires the scan lock.
  • P2/#904: a Tus ticket retains parent_item_id. A directory merge removes that Index identity, so finalization cannot resolve the parent. Decision: retain a source subtree with active uploads and use the existing Job retry/backoff. Do not rewrite ticket identities or transfer a source folder grant to a broader target. The paused-upload fixture covers direct and nested parents, two Users, target collisions and source folder grants.

Merged origin/dev once as e5573dcb4. No dependency or migration change. Production web build passed. The regression build is still compiling; the shared-host load average reached 113.01. Compiler workers are capped at four. No executable fix claim yet. No push or deployment.

Round 3 source findings: - P1: `migrate_voice_memo_home` walks disk entries without `index::recover_moves`. A rename followed by a failed Note write leaves the old Index prefix and grants under a now-empty source folder. A same-process retry can remove that prefix. The new fixture denies writes to Notes for one attempt and retries the real Job handler with the stored payload; it checks Item IDs, both grant kinds, bytes, Note targets and pending intents in an empty-target case and both conflict orders. - Folder reconciliation also needs recovery under its namespace lock. Full reconciliation drops that lock between move recovery and its scan; it must replay any newly failed move after it acquires the scan lock. - P2/#904: a Tus ticket retains `parent_item_id`. A directory merge removes that Index identity, so finalization cannot resolve the parent. Decision: retain a source subtree with active uploads and use the existing Job retry/backoff. Do not rewrite ticket identities or transfer a source folder grant to a broader target. The paused-upload fixture covers direct and nested parents, two Users, target collisions and source folder grants. Merged `origin/dev` once as `e5573dcb4`. No dependency or migration change. Production web build passed. The regression build is still compiling; the shared-host load average reached 113.01. Compiler workers are capped at four. No executable fix claim yet. No push or deployment.
Author
Owner

Both independent findings reproduced before the fixes:

  • Same-process Job retry: the original Item ID lookup returned RowNotFound after the source prefix was removed.
  • Stale-folder reconciliation: it returned success after removing the old rows while a landed move still had a failed Note rewrite.
  • Paused upload: repair removed the ticket's stored parent Item ID (None instead of the original ID).

The fixes replay pending moves under the namespace lock before repair or folder scans and retain source subtrees while active uploads use them. Full scans repeat recovery after reacquiring their scan lock. Expired ordinary tickets do not hold a folder; pending installation intents do. No ticket identity, destination precondition or authorization check changes.

The Note-write fault now uses a file in place of its Version directory, so it fails for root as well as an ordinary operating-system User. No product fault hook was added.

Focused review command: cargo test -p calternal-plugin-files voice_memos_review -- --nocapture --test-threads=2

test result: ok. 13 passed; 0 failed; 2 ignored; 0 measured; 154 filtered out; finished in 115.11s

This includes empty-target and both conflict orders, same-process retry, stale scans, paused direct/nested upload parents, two Users, destination collisions, source-folder grant isolation, retained Tags and Calendar attachments, and restart fixtures. The ignored tests are explicit 100k performance profiles. The existing assertions were retained; stale test names now state the correct invariants.

cargo fmt --check passed with no output. bun run check returned:

svelte-check found 0 errors and 0 warnings

Serial crate gates are in progress. Product commits follow the working gate results. No push or deployment.

Both independent findings reproduced before the fixes: - Same-process Job retry: the original Item ID lookup returned `RowNotFound` after the source prefix was removed. - Stale-folder reconciliation: it returned success after removing the old rows while a landed move still had a failed Note rewrite. - Paused upload: repair removed the ticket's stored parent Item ID (`None` instead of the original ID). The fixes replay pending moves under the namespace lock before repair or folder scans and retain source subtrees while active uploads use them. Full scans repeat recovery after reacquiring their scan lock. Expired ordinary tickets do not hold a folder; pending installation intents do. No ticket identity, destination precondition or authorization check changes. The Note-write fault now uses a file in place of its Version directory, so it fails for root as well as an ordinary operating-system User. No product fault hook was added. Focused review command: `cargo test -p calternal-plugin-files voice_memos_review -- --nocapture --test-threads=2` ```text test result: ok. 13 passed; 0 failed; 2 ignored; 0 measured; 154 filtered out; finished in 115.11s ``` This includes empty-target and both conflict orders, same-process retry, stale scans, paused direct/nested upload parents, two Users, destination collisions, source-folder grant isolation, retained Tags and Calendar attachments, and restart fixtures. The ignored tests are explicit 100k performance profiles. The existing assertions were retained; stale test names now state the correct invariants. `cargo fmt --check` passed with no output. `bun run check` returned: ```text svelte-check found 0 errors and 0 warnings ``` Serial crate gates are in progress. Product commits follow the working gate results. No push or deployment.
Author
Owner

Round 3 fixes saved in two atomic commits:

  • a47def54c: recover landed moves before repair retries and folder scans; retain recording identities and grants after a failed Note write.
  • 244d3e5f89c866a90e4d3c37cb3c07b8143fab57: defer directory merges while active uploads use source parents; retain upload preconditions and source grant boundaries.

Focused review suite: 13 passed, 0 failed, 2 explicit performance profiles ignored. Files fmt and clippy passed. Web check returned 0 errors and 0 warnings. The full serial crate gate round is still running; its Files test binary is rebuilding. These are progress commits, not a full-suite completion claim. No push or deployment.

Round 3 fixes saved in two atomic commits: - `a47def54c`: recover landed moves before repair retries and folder scans; retain recording identities and grants after a failed Note write. - `244d3e5f89c866a90e4d3c37cb3c07b8143fab57`: defer directory merges while active uploads use source parents; retain upload preconditions and source grant boundaries. Focused review suite: 13 passed, 0 failed, 2 explicit performance profiles ignored. Files fmt and clippy passed. Web check returned 0 errors and 0 warnings. The full serial crate gate round is still running; its Files test binary is rebuilding. These are progress commits, not a full-suite completion claim. No push or deployment.
Author
Owner

Full Files verification found the earlier failure again. The complete diagnostics are now captured with --nocapture:

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

The first panic is the unchanged 300-second limit. The second follows abort and temporary Home cleanup: the test keeps only AbortHandles, so its timed-out JoinHandles are dropped before cancellation finishes. The temporary directory can be removed while a worker is still inside a filesystem step. The cleanup now retains and joins all workers before TempDir drops. No timeout, fixture size, status code or assertion is weakened. A focused rerun will determine whether the five-minute bound passes on this host; the full suite result remains a failure until then.

A separate source check found an ASCII-only Voice Memos rewrite classifier while folder discovery uses full Unicode folding. Added a focused two-legacy-twin conflict regression using long s, which discovery treats as ASCII s. It is compiling behind the shared Cargo cache lock. No fix claim yet.

Full Files verification found the earlier failure again. The complete diagnostics are now captured with `--nocapture`: ```text writes, reconcile scans, and watcher adoption complete within five minutes: Elapsed(()) atomic write 220 failed: entry not found ``` The first panic is the unchanged 300-second limit. The second follows abort and temporary Home cleanup: the test keeps only AbortHandles, so its timed-out JoinHandles are dropped before cancellation finishes. The temporary directory can be removed while a worker is still inside a filesystem step. The cleanup now retains and joins all workers before TempDir drops. No timeout, fixture size, status code or assertion is weakened. A focused rerun will determine whether the five-minute bound passes on this host; the full suite result remains a failure until then. A separate source check found an ASCII-only Voice Memos rewrite classifier while folder discovery uses full Unicode folding. Added a focused two-legacy-twin conflict regression using long s, which discovery treats as ASCII s. It is compiling behind the shared Cargo cache lock. No fix claim yet.
Author
Owner

Additional source finding: Files folder discovery uses NFC plus full Unicode case folding, while its Voice Memos attachment rewrite classifier used ASCII case comparison. Two imported folders containing long s can therefore be discovered as twins but skip per-file link rewrites before their folder links merge. A new conflict regression asserts both recording IDs, bytes and exact Note targets. Its pre-fix test build is still running; no pass claim.

The implementation reuses the existing calternal-fs name key. The only cross-crate addition is exporting fold_name; filesystem behavior and the name policy do not change. ASCII comparisons retain their allocation-free path.

The full Files test result is:

test result: FAILED. 165 passed; 1 failed; 3 ignored; 0 measured; 0 filtered out; finished in 2303.45s

The one failure is the unchanged five-minute write/reconcile stress bound. Its cancellation cleanup now joins workers before deleting their temporary Home. A focused rerun and final Files clippy are queued. The other crate gates and debug server build are queued on the same target lock. No push or deployment.

Additional source finding: Files folder discovery uses NFC plus full Unicode case folding, while its Voice Memos attachment rewrite classifier used ASCII case comparison. Two imported folders containing long s can therefore be discovered as twins but skip per-file link rewrites before their folder links merge. A new conflict regression asserts both recording IDs, bytes and exact Note targets. Its pre-fix test build is still running; no pass claim. The implementation reuses the existing calternal-fs name key. The only cross-crate addition is exporting `fold_name`; filesystem behavior and the name policy do not change. ASCII comparisons retain their allocation-free path. The full Files test result is: ```text test result: FAILED. 165 passed; 1 failed; 3 ignored; 0 measured; 0 filtered out; finished in 2303.45s ``` The one failure is the unchanged five-minute write/reconcile stress bound. Its cancellation cleanup now joins workers before deleting their temporary Home. A focused rerun and final Files clippy are queued. The other crate gates and debug server build are queued on the same target lock. No push or deployment.
Author
Owner

Saved f86da93b4: corrected the repair comment to match its existing order: merge imported twins into the chosen primary, then perform the final canonical rename. This is a documentation-only commit.

P1 and P2 fixes remain in a47def54c and 244d3e5f8. The Unicode conflict regression and storm-cleanup follow-ups are awaiting verification. The pre-fix Files test build has reached linking after over 35 minutes; the other gates and current debug server build remain queued. Chromium starts successfully. No push or deployment.

Saved `f86da93b4`: corrected the repair comment to match its existing order: merge imported twins into the chosen primary, then perform the final canonical rename. This is a documentation-only commit. P1 and P2 fixes remain in `a47def54c` and `244d3e5f8`. The Unicode conflict regression and storm-cleanup follow-ups are awaiting verification. The pre-fix Files test build has reached linking after over 35 minutes; the other gates and current debug server build remain queued. Chromium starts successfully. No push or deployment.
Author
Owner

The pre-fix Unicode conflict regression reproduced a link-identity failure. Both Note links became Documents/Voice Memos/shared.m4a; the first must target the older recording's stable conflict copy. Bytes and item IDs survived, but its Note link pointed to the newer recording.

    Finished `test` profile [unoptimized + debuginfo] target(s) in 46m 52s
test tests::voice_memos_review::review_unicode_folded_twins_keep_conflict_link_identities ... FAILED
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 169 filtered out; finished in 9.99s

The correction uses the existing full Unicode name key, with the ASCII fast path retained. Green verification is queued. Full diagnostics are in artifacts/unicode-red.log. No existing expectation was changed.

The pre-fix Unicode conflict regression reproduced a link-identity failure. Both Note links became `Documents/Voice Memos/shared.m4a`; the first must target the older recording's stable conflict copy. Bytes and item IDs survived, but its Note link pointed to the newer recording. ```text Finished `test` profile [unoptimized + debuginfo] target(s) in 46m 52s test tests::voice_memos_review::review_unicode_folded_twins_keep_conflict_link_identities ... FAILED test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 169 filtered out; finished in 9.99s ``` The correction uses the existing full Unicode name key, with the ASCII fast path retained. Green verification is queued. Full diagnostics are in `artifacts/unicode-red.log`. No existing expectation was changed.
Author
Owner

Follow-ups saved as separate progress commits to keep the work recoverable:

  • 47ebf7f71: join cancelled stress workers before temporary Home cleanup; preserve all workload sizes, timeouts and assertions.
  • 1606aa9f738cf137169ae4d6fa6c3d4fd5cc4071: use the filesystem Unicode name key for Voice Memos link repair and add the reproduced long-s twin conflict regression. The calternal-fs change exports an existing helper; it does not change filesystem behavior.

The Unicode test failed against the pre-fix binary as reported above. Its green rerun, the focused stress rerun and final Files clippy are queued behind Notes clippy. Full verification is pending for these progress commits. The earlier P1/P2 focused suite passed, while the full Files suite has its recorded five-minute stress timeout. No push or deployment.

Follow-ups saved as separate progress commits to keep the work recoverable: - `47ebf7f71`: join cancelled stress workers before temporary Home cleanup; preserve all workload sizes, timeouts and assertions. - `1606aa9f738cf137169ae4d6fa6c3d4fd5cc4071`: use the filesystem Unicode name key for Voice Memos link repair and add the reproduced long-s twin conflict regression. The calternal-fs change exports an existing helper; it does not change filesystem behavior. The Unicode test failed against the pre-fix binary as reported above. Its green rerun, the focused stress rerun and final Files clippy are queued behind Notes clippy. Full verification is **pending** for these progress commits. The earlier P1/P2 focused suite passed, while the full Files suite has its recorded five-minute stress timeout. No push or deployment.
Author
Owner

Completed verification and pre-fix regression evidence is attached. The Unicode green run, focused storm rerun, remaining crate tests and screenshots are still pending.

Completed verification and pre-fix regression evidence is attached. The Unicode green run, focused storm rerun, remaining crate tests and screenshots are still pending. - [round3-files-focused.log](https://git.kayg.org/attachments/560df0c9-0081-4ae5-8446-bf351b0b3a89) - [round3-calternal-plugin-files-clippy.log](https://git.kayg.org/attachments/11228d72-e1e5-48ab-a707-cb9b2c21099f) - [round3-calternal-plugin-files-test.log](https://git.kayg.org/attachments/a3d99398-c959-4024-b075-35bd7a2a823c) - [round3-calternal-plugin-notes-clippy.log](https://git.kayg.org/attachments/c433bbad-ca70-4acd-806c-4469efdc1b87) - [round3-web-check.log](https://git.kayg.org/attachments/a401de2c-392b-446f-8eb3-88f4ba3de8ee) - [unicode-red.log](https://git.kayg.org/attachments/37705b72-ffb3-47a7-b5c6-30c05501df0a) - [p1-red-behavior.log](https://git.kayg.org/attachments/92c1fc0a-8398-4484-9889-780e1ccd9de5) - [p1-scan-red.log](https://git.kayg.org/attachments/2ee7564c-d009-4089-a4a3-8d2e6c8b2403) - [p2-red.log](https://git.kayg.org/attachments/7a6d4f9b-0187-4409-8c40-8eaea10a95c0)
Author
Owner

Unicode conflict regression passed on the committed source. Head d687417a15b7b1cd5cf2e64a7f1c5eda8a1c853b adds DESIGN documentation only after the Rust fix.

    Finished `test` profile [unoptimized + debuginfo] target(s) in 70m 10s
test tests::voice_memos_review::review_unicode_folded_twins_keep_conflict_link_identities ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 169 filtered out; finished in 42.79s

The regression checks both recording IDs and bytes, the older recording's exact conflict Note target, the newer recording's original Note target, and a second repair. Full output.

The focused stress rerun, final Files clippy, remaining crate gates and current server build remain queued. Screenshots are prepared for macOS rendering at all three widths in both themes, including actual browser recording and saving a Note. No screenshot pass claim yet.

Unicode conflict regression passed on the committed source. Head `d687417a15b7b1cd5cf2e64a7f1c5eda8a1c853b` adds DESIGN documentation only after the Rust fix. ```text Finished `test` profile [unoptimized + debuginfo] target(s) in 70m 10s test tests::voice_memos_review::review_unicode_folded_twins_keep_conflict_link_identities ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 169 filtered out; finished in 42.79s ``` The regression checks both recording IDs and bytes, the older recording's exact conflict Note target, the newer recording's original Note target, and a second repair. [Full output](https://git.kayg.org/attachments/b8a55d94-1f70-4c06-8a0d-ce9d9c8d595e). The focused stress rerun, final Files clippy, remaining crate gates and current server build remain queued. Screenshots are prepared for macOS rendering at all three widths in both themes, including actual browser recording and saving a Note. No screenshot pass claim yet.
Author
Owner

Round 3: review fixes committed; verification incomplete at the four-hour job limit.

Head: d687417a15b7b1cd5cf2e64a7f1c5eda8a1c853b on job/voicememos-618. Merged origin/dev once (e5573dcb4). No push or deployment.

Built:

  • Replay landed Files move intents under the namespace lock before repair retries and folder scans. Retain recording IDs, Shares and public links until Note rewrites succeed.
  • Retain a legacy source subtree while its active uploads use a parent there. Resume the same ticket without changing destination preconditions or broadening folder grants.
  • Use the existing filesystem Unicode name key for attachment rewrites. Imported Unicode twins must keep each recording's Note link after a conflict move.
  • Join cancelled stress workers before temporary Home cleanup, and correct a stale repair-order comment. No existing timeout, assertion or fixture was weakened.

Files changed in this round:

  • crates/calternal-fs/src/lib.rs
  • crates/calternal-fs/src/path.rs
  • crates/plugins/files/src/index.rs
  • crates/plugins/files/src/lib.rs
  • crates/plugins/files/src/tests/voice_memos_review.rs
  • docs/DESIGN.md

Decisions:

  • Defer a directory merge with the existing queue retry policy instead of adding merge aliases or changing upload tickets.
  • Export the existing calternal-fs::fold_name helper. The filesystem policy does not change. ASCII matching retains its allocation-free path.

UX gaps closed:

  • Failed Note writes followed by same-process retry or scan can no longer delete recording identity and grants.
  • Paused direct and nested uploads retain their parents, bytes and authorization boundaries during repair.
  • Unicode legacy twins must not redirect the older recording's Note link to the newer recording. The focused Unicode regression passed.

Known gaps and UX gaps left:

  • Full Files verification hit the unchanged 300-second stress bound. Keep its failure in the report, even if the focused rerun passes.
  • Batch limits apply between moves. One move can exceed the soft duration when many Notes need rewrites.
  • Broader recording, restart, Share, Tags and Calendar attachment walkthroughs are for the merge round under the latest verification policy.
  • Final Files clippy and the focused stress rerun did not start beyond their target-lock wait. Notes tests compiled partially. notes-core, filesystem and Collab gates, including the SIGKILL test, did not run. The unfinished build/test queue was stopped at the job limit.
  • The current server and production web build completed, but no screenshots were produced. The runner failed first on a legacy title mismatch, then on two runner errors (missing storage seam and missing Job variable). The handoff runner is corrected and syntax checked; its runtime remains unverified.
  • The legacy title mismatch is filed as #962: #962. Only the title mismatch is proven.

For the merge round (latest owner verification policy):

  • (cd apps/web && bun run test) and the combined full e2e run. bun run test:e2e:composer, bun run test:e2e:files, bun run test:e2e:notes, bun run test:e2e:share and bun run test:e2e:deeplinks must prove recording playback, conflict moves, stable links and sharing after repair. Also walk Tags and a Calendar attachment, and restart during repair.
  • bash tests/adversarial/run-split.sh for the combined API verification round.
  • (cd apps/web && bun run build) then cargo build --release -p calternal-server; staging and real Mac interop remain with the orchestrator.
  • On the perf VM, with the existing shared release binary, flock /root/perf.lock sh -c 'uptime; exec python3 bench/voice-memo-migration-618.py --server "$CALTERNAL_SERVER_BIN" --runs 5 --average-files 64 --worst-files 100000 --conflicts 256 --linked-notes 256 --burst 32 --label "perf VM shared release"'. Keep the load average inside the lock. No new measurements were run in this non-performance issue. The profile says no Voice Memos scenario baseline exists yet; compare the recorded baseline commit and available metrics in docs/perf/baseline.json.

Verification output (verbatim summary lines; full logs attached):

cargo fmt --check: exit 0, no output, including the final Rust source.

Files clippy before the Unicode follow-up:

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

Notes clippy:

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 32m 54s

Focused recovery/upload review suite:

test result: ok. 13 passed; 0 failed; 2 ignored; 0 measured; 154 filtered out; finished in 115.11s

Full Files suite:

writes, reconcile scans, and watcher adoption complete within five minutes: Elapsed(())
atomic write 220 failed: entry not found
test result: FAILED. 165 passed; 1 failed; 3 ignored; 0 measured; 0 filtered out; finished in 2303.45s

The secondary NotFound followed timeout cleanup in the old harness. The cleanup fix retains and joins the workers. The focused rerun remained blocked, so this is not a rerun success claim. No bound or assertion changed.

Unicode regression on the committed Rust source:

    Finished `test` profile [unoptimized + debuginfo] target(s) in 70m 10s
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 169 filtered out; finished in 42.79s

Web check:

svelte-check found 0 errors and 0 warnings

Current debug server build:

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 115m 31s

Unfinished exact Rust commands for the merge round:

cargo clippy -p calternal-plugin-files --all-targets -- -D warnings
cargo test -p calternal-plugin-files internal_temp_paths_never_enter_index_during_atomic_write_reconcile_storm -- --nocapture
cargo test -p calternal-plugin-notes -- --nocapture --test-threads=2
for crate in calternal-notes-core calternal-fs calternal-collab; do
  cargo clippy -p "$crate" --all-targets -- -D warnings
  cargo test -p "$crate" -- --nocapture --test-threads=2
done

Use the required Cargo environment, four build workers and the worktree TMPDIR. The filesystem suite must execute review_case_crash::review_sigkill_at_each_case_rename_boundary and print its diagnostics on failure.

After the combined server and web build, run the attached corrected screenshot script from artifacts/:

TMPDIR="$PWD/target/tmp" CALTERNAL_SERVER_BIN="$CARGO_TARGET_DIR/debug/calternal-server" node artifacts/voice-memo-jobs-macos.mjs --screenshots-only --screenshots artifacts/voice-memo-jobs-macos

It must prove keyboard Copy link, actual recording/Keep/Mac submission, Note attachment paths, and 18 captures (Maintenance User/Admin and Composer at 390/820/1440, light/dark). Run without --screenshots-only to retain the legacy-navigation assertions after #962 is resolved. No image is committed.

Attached evidence:

Corrected handoff runner: voice-memo-jobs-macos.mjs.txt. Save it as artifacts/voice-memo-jobs-macos.mjs before the command above. Forgejo rejected the .mjs attachment extension; the text copy has the same content. The partial Notes/server/browser logs are also uploaded as issue assets.

Cleanup: the unfinished build/test queue was stopped. Web build output and temporary test data were removed. cargo clean was started and its final status is pending at report creation.

Round 3: review fixes committed; verification incomplete at the four-hour job limit. Head: `d687417a15b7b1cd5cf2e64a7f1c5eda8a1c853b` on `job/voicememos-618`. Merged `origin/dev` once (`e5573dcb4`). No push or deployment. Built: - Replay landed Files move intents under the namespace lock before repair retries and folder scans. Retain recording IDs, Shares and public links until Note rewrites succeed. - Retain a legacy source subtree while its active uploads use a parent there. Resume the same ticket without changing destination preconditions or broadening folder grants. - Use the existing filesystem Unicode name key for attachment rewrites. Imported Unicode twins must keep each recording's Note link after a conflict move. - Join cancelled stress workers before temporary Home cleanup, and correct a stale repair-order comment. No existing timeout, assertion or fixture was weakened. Files changed in this round: - `crates/calternal-fs/src/lib.rs` - `crates/calternal-fs/src/path.rs` - `crates/plugins/files/src/index.rs` - `crates/plugins/files/src/lib.rs` - `crates/plugins/files/src/tests/voice_memos_review.rs` - `docs/DESIGN.md` Decisions: - Defer a directory merge with the existing queue retry policy instead of adding merge aliases or changing upload tickets. - Export the existing `calternal-fs::fold_name` helper. The filesystem policy does not change. ASCII matching retains its allocation-free path. UX gaps closed: - Failed Note writes followed by same-process retry or scan can no longer delete recording identity and grants. - Paused direct and nested uploads retain their parents, bytes and authorization boundaries during repair. - Unicode legacy twins must not redirect the older recording's Note link to the newer recording. The focused Unicode regression passed. Known gaps and UX gaps left: - Full Files verification hit the unchanged 300-second stress bound. Keep its failure in the report, even if the focused rerun passes. - Batch limits apply between moves. One move can exceed the soft duration when many Notes need rewrites. - Broader recording, restart, Share, Tags and Calendar attachment walkthroughs are for the merge round under the latest verification policy. - Final Files clippy and the focused stress rerun did not start beyond their target-lock wait. Notes tests compiled partially. notes-core, filesystem and Collab gates, including the SIGKILL test, did not run. The unfinished build/test queue was stopped at the job limit. - The current server and production web build completed, but no screenshots were produced. The runner failed first on a legacy title mismatch, then on two runner errors (missing storage seam and missing Job variable). The handoff runner is corrected and syntax checked; its runtime remains unverified. - The legacy title mismatch is filed as #962: https://git.kayg.org/kayg/calternal/issues/962. Only the title mismatch is proven. For the merge round (latest owner verification policy): - `(cd apps/web && bun run test)` and the combined full e2e run. `bun run test:e2e:composer`, `bun run test:e2e:files`, `bun run test:e2e:notes`, `bun run test:e2e:share` and `bun run test:e2e:deeplinks` must prove recording playback, conflict moves, stable links and sharing after repair. Also walk Tags and a Calendar attachment, and restart during repair. - `bash tests/adversarial/run-split.sh` for the combined API verification round. - `(cd apps/web && bun run build)` then `cargo build --release -p calternal-server`; staging and real Mac interop remain with the orchestrator. - On the perf VM, with the existing shared release binary, `flock /root/perf.lock sh -c 'uptime; exec python3 bench/voice-memo-migration-618.py --server "$CALTERNAL_SERVER_BIN" --runs 5 --average-files 64 --worst-files 100000 --conflicts 256 --linked-notes 256 --burst 32 --label "perf VM shared release"'`. Keep the load average inside the lock. No new measurements were run in this non-performance issue. The profile says no Voice Memos scenario baseline exists yet; compare the recorded baseline commit and available metrics in `docs/perf/baseline.json`. Verification output (verbatim summary lines; full logs attached): `cargo fmt --check`: exit 0, no output, including the final Rust source. Files clippy before the Unicode follow-up: ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 9m 19s ``` Notes clippy: ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 32m 54s ``` Focused recovery/upload review suite: ```text test result: ok. 13 passed; 0 failed; 2 ignored; 0 measured; 154 filtered out; finished in 115.11s ``` Full Files suite: ```text writes, reconcile scans, and watcher adoption complete within five minutes: Elapsed(()) atomic write 220 failed: entry not found test result: FAILED. 165 passed; 1 failed; 3 ignored; 0 measured; 0 filtered out; finished in 2303.45s ``` The secondary NotFound followed timeout cleanup in the old harness. The cleanup fix retains and joins the workers. The focused rerun remained blocked, so this is not a rerun success claim. No bound or assertion changed. Unicode regression on the committed Rust source: ```text Finished `test` profile [unoptimized + debuginfo] target(s) in 70m 10s test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 169 filtered out; finished in 42.79s ``` Web check: ```text svelte-check found 0 errors and 0 warnings ``` Current debug server build: ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 115m 31s ``` Unfinished exact Rust commands for the merge round: ```sh cargo clippy -p calternal-plugin-files --all-targets -- -D warnings cargo test -p calternal-plugin-files internal_temp_paths_never_enter_index_during_atomic_write_reconcile_storm -- --nocapture cargo test -p calternal-plugin-notes -- --nocapture --test-threads=2 for crate in calternal-notes-core calternal-fs calternal-collab; do cargo clippy -p "$crate" --all-targets -- -D warnings cargo test -p "$crate" -- --nocapture --test-threads=2 done ``` Use the required Cargo environment, four build workers and the worktree TMPDIR. The filesystem suite must execute `review_case_crash::review_sigkill_at_each_case_rename_boundary` and print its diagnostics on failure. After the combined server and web build, run the attached corrected screenshot script from `artifacts/`: ```sh TMPDIR="$PWD/target/tmp" CALTERNAL_SERVER_BIN="$CARGO_TARGET_DIR/debug/calternal-server" node artifacts/voice-memo-jobs-macos.mjs --screenshots-only --screenshots artifacts/voice-memo-jobs-macos ``` It must prove keyboard Copy link, actual recording/Keep/Mac submission, Note attachment paths, and 18 captures (Maintenance User/Admin and Composer at 390/820/1440, light/dark). Run without `--screenshots-only` to retain the legacy-navigation assertions after #962 is resolved. No image is committed. Attached evidence: - [round3-files-focused.log](https://git.kayg.org/attachments/560df0c9-0081-4ae5-8446-bf351b0b3a89) - [round3-calternal-plugin-files-clippy.log](https://git.kayg.org/attachments/11228d72-e1e5-48ab-a707-cb9b2c21099f) - [round3-calternal-plugin-files-test.log](https://git.kayg.org/attachments/a3d99398-c959-4024-b075-35bd7a2a823c) - [round3-calternal-plugin-notes-clippy.log](https://git.kayg.org/attachments/c433bbad-ca70-4acd-806c-4469efdc1b87) - [round3-web-check.log](https://git.kayg.org/attachments/a401de2c-392b-446f-8eb3-88f4ba3de8ee) - [unicode-red.log](https://git.kayg.org/attachments/37705b72-ffb3-47a7-b5c6-30c05501df0a) - [p1-red-behavior.log](https://git.kayg.org/attachments/92c1fc0a-8398-4484-9889-780e1ccd9de5) - [p1-scan-red.log](https://git.kayg.org/attachments/2ee7564c-d009-4089-a4a3-8d2e6c8b2403) - [p2-red.log](https://git.kayg.org/attachments/7a6d4f9b-0187-4409-8c40-8eaea10a95c0) - [unicode-green.log](https://git.kayg.org/attachments/b8a55d94-1f70-4c06-8a0d-ce9d9c8d595e) Corrected handoff runner: [voice-memo-jobs-macos.mjs.txt](https://git.kayg.org/attachments/a8694ad5-d1c9-40d5-9264-d72f3ce70ed9). Save it as `artifacts/voice-memo-jobs-macos.mjs` before the command above. Forgejo rejected the `.mjs` attachment extension; the text copy has the same content. The partial Notes/server/browser logs are also uploaded as issue assets. Cleanup: the unfinished build/test queue was stopped. Web build output and temporary test data were removed. `cargo clean` was started and its final status is pending at report creation.
Author
Owner

Cleanup completed after the final report was posted:

     Removed 14839 files, 8.2GiB total

Web build output and temporary test data were removed. The worktree is clean at d687417a15b7b1cd5cf2e64a7f1c5eda8a1c853b. The local final report now records completed cleanup. No push or deployment. Verification remains incomplete as stated in the report.

Cleanup completed after the final report was posted: ```text Removed 14839 files, 8.2GiB total ``` Web build output and temporary test data were removed. The worktree is clean at `d687417a15b7b1cd5cf2e64a7f1c5eda8a1c853b`. The local final report now records completed cleanup. No push or deployment. Verification remains incomplete as stated in the report.
Author
Owner

Crate gates on job/voicememos-618 (Files plugin), run by Claude:

  • cargo fmt --check: exit 0
  • cargo clippy -p calternal-plugin-files --all-targets -- -D warnings: Finished \dev` profile [unoptimized + debuginfo] target(s) in 4m 57s`
  • cargo test -p calternal-plugin-files --no-fail-fast -- --test-threads=4:
    test result: ok. 167 passed; 0 failed; 3 ignored; 0 measured; 0 filtered out; finished in 94.78s
    test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
    

No fixes needed. Ready for the merge round (Files crate gates).

Crate gates on `job/voicememos-618` (Files plugin), run by Claude: - `cargo fmt --check`: exit 0 - `cargo clippy -p calternal-plugin-files --all-targets -- -D warnings`: `Finished \`dev\` profile [unoptimized + debuginfo] target(s) in 4m 57s` - `cargo test -p calternal-plugin-files --no-fail-fast -- --test-threads=4`: ``` test result: ok. 167 passed; 0 failed; 3 ignored; 0 measured; 0 filtered out; finished in 94.78s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ``` No fixes needed. Ready for the merge round (Files crate gates).
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#618
No description provided.