Log attachment upload returns 500 after creating the files (duplicates on retry) #460

Closed
opened 2026-09-29 15:02:06 +00:00 by kayg · 12 comments
Owner

Bug (found by the ab-384-luna job, round 3, 2026-09-29)

While seeding e2e fixtures, an attachment upload for a Log entry returned HTTP 500 after creating the files, so the files exist but the client saw a failure (and retried, leaving duplicates with the round-2 names). A 5xx is a merge-blocking class, and a create-then-fail leaves orphans.

Work

Reproduce: attach 2 files to a Log entry through the same API the composer uses, repeatedly and concurrently, on a local production build. Find the failing step from the server log (quota reservation, index, the change feed, attachment link write into the daily note, thumbnail enqueue). Fix it so the operation is atomic from the client's view: success, or a clean failure with no files left behind (or files reused on retry through an idempotency key). Add a regression test plus an adversarial case (concurrent attach to the same entry, attach during a daily-note edit). Related: #427 attachment liveness. Gates per crate as in the preamble.

## Bug (found by the ab-384-luna job, round 3, 2026-09-29) While seeding e2e fixtures, an attachment upload for a Log entry **returned HTTP 500 after creating the files**, so the files exist but the client saw a failure (and retried, leaving duplicates with the round-2 names). A 5xx is a merge-blocking class, and a create-then-fail leaves orphans. ## Work Reproduce: attach 2 files to a Log entry through the same API the composer uses, repeatedly and concurrently, on a local production build. Find the failing step from the server log (quota reservation, index, the change feed, attachment link write into the daily note, thumbnail enqueue). Fix it so the operation is atomic from the client's view: success, or a clean failure with no files left behind (or files reused on retry through an idempotency key). Add a regression test plus an adversarial case (concurrent attach to the same entry, attach during a daily-note edit). Related: #427 attachment liveness. Gates per crate as in the preamble.
Author
Owner

Investigating #460 on branch job/attach-427, based on 43c1377c8f. I am reproducing the create-then-500 path and tracing each write boundary before selecting a fix.

Investigating #460 on branch job/attach-427, based on 43c1377c8fd3b1b495841446989a64156f8ae1e4. I am reproducing the create-then-500 path and tracing each write boundary before selecting a fix.
Author
Owner

Root cause reproduced in the Files upload route test: complete_install removed the files_uploads row and staging bytes before state.publish inserted the durable files_events row. An injected event-write failure returned HTTP 500 with the installed file and Index row present, but upload_rows=0; retrying the same tus URL then cannot resume. I am moving upload cleanup after publication and covering same-key retry.

Root cause reproduced in the Files upload route test: complete_install removed the files_uploads row and staging bytes before state.publish inserted the durable files_events row. An injected event-write failure returned HTTP 500 with the installed file and Index row present, but upload_rows=0; retrying the same tus URL then cannot resume. I am moving upload cleanup after publication and covering same-key retry.
Author
Owner

Committed server fix 18f63463. The injected post-install change-event regression is green; and Files clippy pass. The full Files suite reported failures in cursor migration, internal-temp recovery, and a stack overflow in the Log attachment rename test. I am isolating those separately and will not change existing expectations.

Committed server fix 18f63463. The injected post-install change-event regression is green; and Files clippy pass. The full Files suite reported failures in cursor migration, internal-temp recovery, and a stack overflow in the Log attachment rename test. I am isolating those separately and will not change existing expectations.
Author
Owner

Progress: commit 84fd7b09 adds the client retry path and a focused upload-queue regression. After a final attachment PATCH errors with all bytes staged, Retry now HEADs the same tus ID, sends the empty final PATCH, and keeps the server-routed path. The focused test passed: Test Files 1 passed (1); Tests 6 passed (6). The Files server fix is in 18f63463; its focused regression and Files clippy passed. I am regenerating the OpenAPI contract/client and continuing with production e2e plus the concurrent adversarial case.

Progress: commit 84fd7b09 adds the client retry path and a focused upload-queue regression. After a final attachment PATCH errors with all bytes staged, Retry now HEADs the same tus ID, sends the empty final PATCH, and keeps the server-routed path. The focused test passed: `Test Files 1 passed (1); Tests 6 passed (6)`. The Files server fix is in 18f63463; its focused regression and Files clippy passed. I am regenerating the OpenAPI contract/client and continuing with production e2e plus the concurrent adversarial case.
Author
Owner

Resuming round 2 on job/attach-427 at 7e8e9af43. The prior integration commit is 336f5e306; I will fetch and integrate current origin/dev once before final gates. I am continuing the interrupted Calendar timezone projection change, then finishing #460 atomic attach behavior, the e2e proof and required gates.

Resuming round 2 on `job/attach-427` at `7e8e9af43`. The prior integration commit is `336f5e306`; I will fetch and integrate current `origin/dev` once before final gates. I am continuing the interrupted Calendar timezone projection change, then finishing #460 atomic attach behavior, the e2e proof and required gates.
Author
Owner

Resuming round 2 on job/attach-427 at 7e8e9af43. The branch includes the origin/dev integration at 336f5e306; the latest committed change adds a concurrent attachment probe. I am finishing the timezone-aware attachment labels, then handling #460 retry atomicity/concurrency, generated API client checks, production e2e evidence, and the requested gates.

Resuming round 2 on `job/attach-427` at `7e8e9af43`. The branch includes the `origin/dev` integration at `336f5e306`; the latest committed change adds a concurrent attachment probe. I am finishing the timezone-aware attachment labels, then handling #460 retry atomicity/concurrency, generated API client checks, production e2e evidence, and the requested gates.
Author
Owner

Starting work on #460 alongside #427.

Branch: job/attach-427
Current HEAD: 7250f26db0fca979d28e4f7222f61c1b57896bbb
Branch base at this resumed round: 43c1377c8f

The branch already contains a server regression test that injects a durable Files change-event failure after install and retries the same tus upload ID, plus client behavior that keeps this ID retryable. I am validating that path and the concurrent attach probe, then will run the requested API generation and production e2e checks.

Starting work on #460 alongside #427. Branch: job/attach-427 Current HEAD: 7250f26db0fca979d28e4f7222f61c1b57896bbb Branch base at this resumed round: 43c1377c8fd3b1b495841446989a64156f8ae1e4 The branch already contains a server regression test that injects a durable Files change-event failure after install and retries the same tus upload ID, plus client behavior that keeps this ID retryable. I am validating that path and the concurrent attach probe, then will run the requested API generation and production e2e checks.
Author
Owner

Focused real-server adversarial result: the #460 concurrent attachment case passed. Eight parallel tus uploads returned 201 with unique destinations; one Log write linked all eight while another client edited the same Daily note; the attach returned 201, the edit returned 200, and the final read preserved the eight links and the edited title. Uploads took 24.9–48.2 s on the shared host and were marked SLOW. The separate 100-write Log/Files listing storm had 503/timeouts; I filed that evidence for controlled-load follow-up in #493.

Focused real-server adversarial result: the #460 concurrent attachment case passed. Eight parallel tus uploads returned 201 with unique destinations; one Log write linked all eight while another client edited the same Daily note; the attach returned 201, the edit returned 200, and the final read preserved the eight links and the edited title. Uploads took 24.9–48.2 s on the shared host and were marked SLOW. The separate 100-write Log/Files listing storm had 503/timeouts; I filed that evidence for controlled-load follow-up in #493.
Author
Owner

Finished: #460

Head: 0182ec91f7f81ab2cfc63a3eeb69d38fb035e0ad

Tus finalization now uses the stable upload ID as its retry identity. A retry after the file is installed returns the existing destination rather than creating another file. Finalization for the same upload ID is serialized, while independent uploads keep separate locks. The Files regression tests cover retry and concurrent completion.

The local production adversarial case ran 8 concurrent Tus uploads to the same Log entry while a Daily note edit ran. All 8 uploads returned 201 with distinct destinations; the Log write returned 201, the edit returned 200, and the final read retained all 8 attachment links and the edit. The focused #427 production attachment flow also passed.

Clippy and tests for Files, Calendar and Server, bun run check, and bun run test are reported with captured output in #427. The Files full suite had one shared-load stress timeout; the exact test passed when isolated. A broader worker-storm 503 finding is filed as #493.

Decision: the existing Tus upload ID is the idempotency key, so the client does not need a second retry token. The migration uses Files migration 0017 because upstream work reserves 0016.

## Finished: #460 **Head:** `0182ec91f7f81ab2cfc63a3eeb69d38fb035e0ad` Tus finalization now uses the stable upload ID as its retry identity. A retry after the file is installed returns the existing destination rather than creating another file. Finalization for the same upload ID is serialized, while independent uploads keep separate locks. The Files regression tests cover retry and concurrent completion. The local production adversarial case ran 8 concurrent Tus uploads to the same Log entry while a Daily note edit ran. All 8 uploads returned 201 with distinct destinations; the Log write returned 201, the edit returned 200, and the final read retained all 8 attachment links and the edit. The focused #427 production attachment flow also passed. Clippy and tests for Files, Calendar and Server, `bun run check`, and `bun run test` are reported with captured output in [#427](https://git.kayg.org/kayg/calternal/issues/427). The Files full suite had one shared-load stress timeout; the exact test passed when isolated. A broader worker-storm 503 finding is filed as #493. Decision: the existing Tus upload ID is the idempotency key, so the client does not need a second retry token. The migration uses Files migration 0017 because upstream work reserves 0016.
Author
Owner

Merge round 3 integration report

State: incomplete; do not fast-forward this snapshot to dev yet. The four-hour job limit ended while CLI Clippy was compiling. No completed final-tree gate failed. No source branch was dropped because the completed gates showed no failing branch.

  • Branch: job/merge-round-3
  • Head: 3e5056d485e9021d2d1f708613e783b0b901b447
  • Included in order: job/multiget-500, job/dav-delete-471, job/iso-435, job/admin-deny-483, job/attach-427, job/hidden-420, job/files-sel-keys, job/small-bugs-3, job/sweep-478.
  • Additional commits: 92f5803f3, 3ea69e317, 26b986bc4, 0948cffa1, 99c088193, df6b07a5a, 3e5056d48.

Completed gate output (verbatim excerpts)

cargo fmt --check exited 0 with no output.

  • DAV clippy: Finished \dev` profile [unoptimized + debuginfo] target(s) in 56.92s`
  • DAV tests:
    test result: ok. 40 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.37s
    test result: ok. 36 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.09s
    test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.31s
  • Notes Core clippy: Finished \dev` profile [unoptimized + debuginfo] target(s) in 14.97s`
  • Notes Core tests:
    test result: ok. 512 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.21s
    test result: ok. 19 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 8.21s
    test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.06s
    test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.35s
    test result: ok. 12 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s
  • Notes plugin clippy: Finished \dev` profile [unoptimized + debuginfo] target(s) in 2m 55s`
  • Notes plugin tests: test result: ok. 127 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 151.26s
  • Files clippy (after comment fix): Finished \dev` profile [unoptimized + debuginfo] target(s) in 48.77s`
  • Files tests: test result: ok. 144 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 178.62s
    The dev-version migration test passed: test tests::dev_files_schema_upgrades_through_share_log_and_sidecar_migrations ... ok
  • Calendar clippy: Finished \dev` profile [unoptimized + debuginfo] target(s) in 1m 53s`
  • Calendar tests:
    test result: ok. 52 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 7.01s
    test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.12s
    test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.22s
  • Photos clippy: Finished \dev` profile [unoptimized + debuginfo] target(s) in 1m 13s`
  • Photos tests: test result: ok. 45 passed; 0 failed; 2 ignored; 0 measured; 0 filtered out; finished in 11.10s
  • Search clippy: Finished \dev` profile [unoptimized + debuginfo] target(s) in 55.79s`
  • Search tests:
    test result: ok. 36 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 46.71s
    test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 2.38s
    test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.09s
    test result: ok. 21 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 10.44s
    test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.05s
    test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.02s
    test result: ok. 1 passed; 0 failed; 2 ignored; 0 measured; 0 filtered out; finished in 5.66s
    test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s
  • Embed clippy: Finished \dev` profile [unoptimized + debuginfo] target(s) in 27.32s`
  • Embed tests: test result: ok. 31 passed; 0 failed; 4 ignored; 0 measured; 0 filtered out; finished in 1.93s
  • Filesystem clippy: Finished \dev` profile [unoptimized + debuginfo] target(s) in 10.78s`
  • Filesystem tests:
    test result: ok. 50 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 9.04s
    test result: ok. 42 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 3.56s
  • Server clippy: Finished \dev` profile [unoptimized + debuginfo] target(s) in 1m 48s`
  • Server tests: test result: ok. 85 passed; 0 failed; 2 ignored; 0 measured; 0 filtered out; finished in 19.67s

Other completed checks:

  • Parity matrix: 190 web API actions, 122 shortcuts, 2 static commands, 136 menu actions, 31 settings groups, 172 actions with adapter gaps
  • Cross-User classification gate: 311 operations classified; its test suite printed Ran 5 tests in 0.246s and OK.
  • Admin coverage: 39 reviewed operations; contract and Rust guards agree; its test suite printed Ran 14 tests in 2.404s and OK.
  • Migration audit: ai: 4 migrations, no duplicate numbers; analytics: 2 migrations, no duplicate numbers; calendar: 3 migrations, no duplicate numbers; files: 18 migrations, no duplicate numbers; mail: 8 migrations, no duplicate numbers; notes: 19 migrations, no duplicate numbers; notifications: 4 migrations, no duplicate numbers; photos: 6 migrations, no duplicate numbers; video: 1 migrations, no duplicate numbers.

Remaining work

  • CLI Clippy was interrupted at the four-hour limit while checking dependencies; CLI tests and both Auth gates did not run.
  • The generated contract check, web bun run check, bun run test, and bun run build are pending.
  • The live two-User matrix, authz matrix, DAV round (including Apple’s 100-href and DELETE re-parent replays), sidecar probe, and attachment e2e are pending.
  • Production-browser screenshots for each affected screen at 390/820/1440 px in light/dark mode are pending. No visual review artifacts were produced.
  • The new benchmark profile was added, but its local run and comparison with docs/perf/baseline.json are pending.
  • cargo clean is running but has not returned yet; apps/web/build was removed.

Decisions

  • Files migration IDs follow merge order after dev’s 0015: 0016 share_search_invalidations, 0017 log_attachment_trash, 0018 sidecar_pairs. The populated dev-schema upgrade test passed.
  • Hidden-file Settings copy leads with the User-visible result and uses “Photo edit files (.xmp, .aae)”.
  • The parity exception snapshot was regenerated and reviewed for the newly merged API and Files UI actions.

The branch contains the merged code and commits, but the listed pending gates mean this is not a green merge candidate yet.

## Merge round 3 integration report **State: incomplete; do not fast-forward this snapshot to `dev` yet.** The four-hour job limit ended while CLI Clippy was compiling. No completed final-tree gate failed. No source branch was dropped because the completed gates showed no failing branch. - Branch: `job/merge-round-3` - Head: `3e5056d485e9021d2d1f708613e783b0b901b447` - Included in order: `job/multiget-500`, `job/dav-delete-471`, `job/iso-435`, `job/admin-deny-483`, `job/attach-427`, `job/hidden-420`, `job/files-sel-keys`, `job/small-bugs-3`, `job/sweep-478`. - Additional commits: `92f5803f3`, `3ea69e317`, `26b986bc4`, `0948cffa1`, `99c088193`, `df6b07a5a`, `3e5056d48`. ### Completed gate output (verbatim excerpts) `cargo fmt --check` exited 0 with no output. - DAV clippy: `Finished \`dev\` profile [unoptimized + debuginfo] target(s) in 56.92s` - DAV tests: `test result: ok. 40 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.37s` `test result: ok. 36 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.09s` `test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.31s` - Notes Core clippy: `Finished \`dev\` profile [unoptimized + debuginfo] target(s) in 14.97s` - Notes Core tests: `test result: ok. 512 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.21s` `test result: ok. 19 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 8.21s` `test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.06s` `test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.35s` `test result: ok. 12 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s` - Notes plugin clippy: `Finished \`dev\` profile [unoptimized + debuginfo] target(s) in 2m 55s` - Notes plugin tests: `test result: ok. 127 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 151.26s` - Files clippy (after comment fix): `Finished \`dev\` profile [unoptimized + debuginfo] target(s) in 48.77s` - Files tests: `test result: ok. 144 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 178.62s` The dev-version migration test passed: `test tests::dev_files_schema_upgrades_through_share_log_and_sidecar_migrations ... ok` - Calendar clippy: `Finished \`dev\` profile [unoptimized + debuginfo] target(s) in 1m 53s` - Calendar tests: `test result: ok. 52 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 7.01s` `test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.12s` `test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.22s` - Photos clippy: `Finished \`dev\` profile [unoptimized + debuginfo] target(s) in 1m 13s` - Photos tests: `test result: ok. 45 passed; 0 failed; 2 ignored; 0 measured; 0 filtered out; finished in 11.10s` - Search clippy: `Finished \`dev\` profile [unoptimized + debuginfo] target(s) in 55.79s` - Search tests: `test result: ok. 36 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 46.71s` `test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 2.38s` `test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.09s` `test result: ok. 21 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 10.44s` `test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.05s` `test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.02s` `test result: ok. 1 passed; 0 failed; 2 ignored; 0 measured; 0 filtered out; finished in 5.66s` `test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s` - Embed clippy: `Finished \`dev\` profile [unoptimized + debuginfo] target(s) in 27.32s` - Embed tests: `test result: ok. 31 passed; 0 failed; 4 ignored; 0 measured; 0 filtered out; finished in 1.93s` - Filesystem clippy: `Finished \`dev\` profile [unoptimized + debuginfo] target(s) in 10.78s` - Filesystem tests: `test result: ok. 50 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 9.04s` `test result: ok. 42 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 3.56s` - Server clippy: `Finished \`dev\` profile [unoptimized + debuginfo] target(s) in 1m 48s` - Server tests: `test result: ok. 85 passed; 0 failed; 2 ignored; 0 measured; 0 filtered out; finished in 19.67s` Other completed checks: - `Parity matrix: 190 web API actions, 122 shortcuts, 2 static commands, 136 menu actions, 31 settings groups, 172 actions with adapter gaps` - `Cross-User classification gate: 311 operations classified`; its test suite printed `Ran 5 tests in 0.246s` and `OK`. - `Admin coverage: 39 reviewed operations; contract and Rust guards agree`; its test suite printed `Ran 14 tests in 2.404s` and `OK`. - Migration audit: `ai: 4 migrations, no duplicate numbers`; `analytics: 2 migrations, no duplicate numbers`; `calendar: 3 migrations, no duplicate numbers`; `files: 18 migrations, no duplicate numbers`; `mail: 8 migrations, no duplicate numbers`; `notes: 19 migrations, no duplicate numbers`; `notifications: 4 migrations, no duplicate numbers`; `photos: 6 migrations, no duplicate numbers`; `video: 1 migrations, no duplicate numbers`. ### Remaining work - CLI Clippy was interrupted at the four-hour limit while checking dependencies; CLI tests and both Auth gates did not run. - The generated contract check, web `bun run check`, `bun run test`, and `bun run build` are pending. - The live two-User matrix, authz matrix, DAV round (including Apple’s 100-href and DELETE re-parent replays), sidecar probe, and attachment e2e are pending. - Production-browser screenshots for each affected screen at 390/820/1440 px in light/dark mode are pending. No visual review artifacts were produced. - The new benchmark profile was added, but its local run and comparison with `docs/perf/baseline.json` are pending. - `cargo clean` is running but has not returned yet; `apps/web/build` was removed. ### Decisions - Files migration IDs follow merge order after dev’s 0015: 0016 `share_search_invalidations`, 0017 `log_attachment_trash`, 0018 `sidecar_pairs`. The populated dev-schema upgrade test passed. - Hidden-file Settings copy leads with the User-visible result and uses “Photo edit files (.xmp, .aae)”. - The parity exception snapshot was regenerated and reviewed for the newly merged API and Files UI actions. The branch contains the merged code and commits, but the listed pending gates mean this is not a green merge candidate yet.
Author
Owner

Merge round 3 report addendum

Branch job/merge-round-3, HEAD 3e5056d485e9021d2d1f708613e783b0b901b447.

  • Cleanup completed after the main report: Removed 25367 files, 17.5GiB total.
  • apps/web/build removal check: web build output removed: True.
  • git diff --check exited 0 with no output; the worktree has no modified or untracked files.
  • The 4-hour cutoff also prevented a full re-read of documentation comments across all 234 changed files. This remains an audit gap alongside the pending gates listed in the main report.

The branch is still not a green merge candidate.

## Merge round 3 report addendum Branch `job/merge-round-3`, HEAD `3e5056d485e9021d2d1f708613e783b0b901b447`. - Cleanup completed after the main report: `Removed 25367 files, 17.5GiB total`. - `apps/web/build` removal check: `web build output removed: True`. - `git diff --check` exited 0 with no output; the worktree has no modified or untracked files. - The 4-hour cutoff also prevented a full re-read of documentation comments across all 234 changed files. This remains an audit gap alongside the pending gates listed in the main report. The branch is still not a green merge candidate.
Author
Owner

Merged in merge round 3 and deployed to calternal.cloud in cc25c441b (healthy).

Merged in merge round 3 and deployed to calternal.cloud in cc25c441b (healthy).
kayg closed this issue 2026-09-30 23:22:41 +00:00
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#460
No description provided.