Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
f778fd8
PT-4159: auto-sync blocking store (200ms grace, refcount, safety clear)
rolfheij-sil Jul 14, 2026
0ac340e
PT-4159: auto-sync blocking service (network event subscription)
rolfheij-sil Jul 14, 2026
dbfeb6e
PT-4159: auto-sync blocking overlay with single-shot Cancel
rolfheij-sil Jul 14, 2026
c407d1e
PT-4159: focus containment + Cancel re-arm on failure (review findings)
rolfheij-sil Jul 14, 2026
2b6913a
PT-4159: live sync progress on the blocking overlay
rolfheij-sil Jul 14, 2026
0c5eed8
PT-4159: overlay focus yields to modals + dialog semantics (review fi…
rolfheij-sil Jul 14, 2026
e496195
PT-4159: narrow overlay focus-yield to aria-modal layers + async-yiel…
rolfheij-sil Jul 14, 2026
ea708e1
PT-4159: replace blocking overlay with a headless editor-block driver
rolfheij-sil Jul 15, 2026
54725e2
PT-4159: freeze editing + show sync banner in the Scripture editor
rolfheij-sil Jul 15, 2026
37e8c35
PT-4159: add inert public C# write-gate for automatic Send/Receive
rolfheij-sil Jul 15, 2026
72d75c2
PT-4159: gate ManageBooks/Inventory writes + wiring tests for all gates
rolfheij-sil Jul 15, 2026
df61224
PT-4159: block comment-editor Save while sync-blocked (review findings)
rolfheij-sil Jul 15, 2026
d27e2c5
PT-4159: mock edit-block driver in app.component test (jsdom matchMedia)
rolfheij-sil Jul 15, 2026
4fadc40
PT-4159: rework SendReceiveWriteLock as a ReaderWriterLockSlim gate
rolfheij-sil Jul 15, 2026
3aeeff5
PT-4159: document and enforce the Send/Receive write-gate rule
rolfheij-sil Jul 15, 2026
fe3252e
PT-4159: gate CheckRunner writes + harden write-gate (post-review)
rolfheij-sil Jul 15, 2026
8b2afa9
PT-4159: wire up auto-sync blocking service and edit-block driver at …
rolfheij-sil Jul 15, 2026
cff082e
PT-4159: Rebuild S/R write gate without thread affinity (#2564)
lyonsil Jul 16, 2026
e79699c
PT-4159: address renderer review findings (round 2)
rolfheij-sil Jul 16, 2026
3834035
PT-4159: address C# write-gate review findings (round 3)
rolfheij-sil Jul 16, 2026
9bc9595
PT-4159: address extension review findings (round 3)
rolfheij-sil Jul 16, 2026
243e6a9
PT-4159: regenerate papi.d.ts for SHUTDOWN_SYNC_TIME_OUT_MS export
rolfheij-sil Jul 16, 2026
0ebc7ef
PT-4159: fix permanent editor block from stale re-flag subscription o…
rolfheij-sil Jul 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,40 @@ npm run typecheck
- Don't add features, refactor code, or make "improvements" beyond what was asked.
- Avoid indecipherable [initialisms and abbreviations](.context/standards/Code-Style-Guide.md#initialisms-and-abbreviations).

## Send/Receive Write Gate

Any new C# code path that **mutates project data** (`ScrText` writes — `PutText`,
`Settings.Save`/`SetSetting`/`RemoveSetting`, `FileManager` operations, comment/note mutations,
extension data) MUST wrap the mutation in `using var _ = SendReceiveWriteLock.EnterWrite(projectId);`
as the first statement of its entry-point method (see
`c-sharp/Projects/SendReceive/SendReceiveWriteLock.cs`). The gate works in both directions: an
armed automatic Send/Receive rejects the write fail-fast (the `(SR_EDIT_BLOCKED)` sentinel),
while a starting sync waits, bounded, for open write scopes to drain before it replaces files on
disk.

The gate has **no thread affinity** (its state is a single atomic word — an armed flag, an
in-flight write count, and an arm generation — not an OS lock): a scope may be disposed on a
different thread, holding one across an `await` is safe, and `SetSyncing`/`Clear` may run on any
threads. `SetSyncing` returns a token; end the bracket with `Clear(token)` (a stale token is a
logged no-op, so a late Clear can never disarm a newer sync) and keep parameterless `Clear()` for
crash recovery — it force-disarms unconditionally and is idempotent. Nested `EnterWrite` calls do
not crash, but they are NOT safe: if a sync arms while the outer scope is open, the inner call
throws the sentinel mid-mutation — keep one scope per mutation (delegate to an un-gated core
inside a single scope, as `SetBookUsfmInScope` does). Keep scopes **tight** — the mutation and
nothing else — because every open scope delays a starting sync's bounded drain toward its timeout.

This is an **in-process** gate, distinct from the S/R server-side repository lock
(`lockrepo`/`unlockrepo` between clients) — do not conflate the two. `SendReceiveWriteLockCoverageTests`
(`c-sharp-tests/Projects/SendReceive/`) scans the source tree (excluding `bin`/`obj`) for direct
project-write call patterns (a general `.Save(` heuristic, `PutText`, comment `SaveUser`/`SaveEdits`,
and `File`/`FileManager` deletes) and fails on any hit that isn't covered per site by ONE of: gate
evidence (an `EnterWrite`/`EnterSyncWriteScope` call above it in the same method); an inline
`// SR-write-gate: exempt — <reason>` marker on/above the write (for writes reached only through an
already-gated caller — the un-gated `SetBookUsfmInScope` core and the ManageBooks orchestrators,
each citing its gated caller + `TODO(PT-4210)`); or a whole-file entry on the test's exempt list,
which is reserved for **not-project-data** files only. Per-site (not whole-file), so a NEW ungated
write added to an already-gated file is still caught.

## Never Commit Secrets

This is an open-source repository. Never introduce secrets into the codebase:
Expand Down

Large diffs are not rendered by default.

Loading
Loading