Skip to content

Tracking S4a: guarded write CAS core with per-path FIFO chain #1399

Open

Description

@easonLiangWorldedtech

Tracking issue for the S4a PR (branch feat/guarded-write-s4a; PR to be opened after review).

Part of the file-write safety series — plan: easonLiangWorldedtech/Zoo-Code#33, epic: #1375. Item: S4a — Guarded write CAS core. Stacks on #1383 (S1 version tokens), #1394 (S2 observation registry), and #1395 (S3 atomic publish) — the branch is built on all three; S4b wires it into the save paths.

Scope

  • New src/core/tools/guardedWrite.ts: a compare-and-swap layer over the S1/S2/S3 primitives. Decision table per absolute path:
    • unobserved + absent → createIfAbsent
    • unobserved + present → fail (file not read yet — read the file, then retry), forcing the model to re-read
    • observed + absent → createIfAbsent
    • observed + present → replaceIfVersion (version mismatch → stale fail: stale version — re-read the file, then retry)
  • Typed error classes carrying the exact remediation texts; per-absolute-path tail-promise FIFO chain (in-process, no lockfile) so concurrent writes to the same path serialize and different paths stay parallel.
  • Pure core module: no tool wiring, no DiffViewProvider changes (that is S4b).

Acceptance

  • Every decision-table row has a deterministic unit test, including both exact remediation strings
  • Same-path writes serialize (FIFO); cross-path writes run in parallel
  • Uses only the existing S1 (versionToken), S2 (ObservationRegistry), S3 (safeWriteText) APIs — no new deps, no lockfiles
  • CI green (ubuntu unit-test gate), 100% codecov patch coverage

Status

  • PR: to be opened (after S1+S2+S3 merge)

Activity

  1. added a commit that references this issue on Oct 22, 2026
  2. easonLiangWorldedtech commented on Nov 9, 2026

    @easonLiangWorldedtech
    ContributorAuthor

    The four production deferrals from #1405, as rows on this tracker (lane s3-1395, 2026-11-09T19:11:50ZZ)

    This tracker has zero comments, and four production rows from #1405 were owed here as rows rather than as thread replies. They are the rows whose answers say deferred with the cost named, and the cost is the headroom: 497 of 500 counted executable lines, head 8186900, PR base 73931fe, mergeBase 73931fe (the two are the same commit here), 128 selectors, selectorsHash 1607fe96287f443b, read in C:/work/Zoo-Code-fork/wt-s3-1405 which sits at that head with 0 porcelain rows.

    1. row 4509757215 - src/utils/safeWriteJson.ts:487 (f9073dcd64e9 at 8186900bfc) - Minor, data integrity. New-path race between createTempFilePath and openSync. Agreed on the mechanism, deferred to a follow-up unit of feat(tools): guarded write CAS core with per-path FIFO chain (S4a, #1375) #1405. Our rows 4509875370, 4515846457.
    2. row 4509757220 - src/utils/safeWriteJson.ts:494 - Minor, data integrity. The stage fd is reopened by _flushFileToDisk at :531-542, so any fix has to carry that constraint. Our rows 4509875636, 4515846842.
    3. row 4509757226 - src/utils/safeWriteJson.ts:497 - Major, security. Publication ordering: stage at 0o600 then apply the target mode, versus publishing the mode the target already has. This one wants a ruling, not a patch - option (a) as first stated does not survive the Windows measurement recorded in 4510022724. Our rows 4509875902, 4510022724, 4515847254.
    4. row 4510030261 - src/core/config/importExport.ts:360 - Minor, stability. The live half of the notification pair: webviewMessageHandler awaits exportSettings... and the refusal path escapes the notification. Our rows 4510045316, 4515848805.

    The fifth open production question on #1405 is row 4504216100 (src/utils/safeWriteJson.ts:225), and it is not a deferral but an escalation: the lock-key contract - link name, resolved referent, or target path - is a design decision for the code owner, filed upstream as #2375, and a third unit is already writing against the current shape. Our rows on it: 4504471311, 4509442284, 4509807777, 4509827755, 4515844907.

    What is not owed here: five test-only rows on #1405 were accepted and are recorded on #1991 (4509757197, 4509757204, 4509757233, 4510030249, 4510030255), and row 4509757207 is satisfied at 8186900bfc. Nothing pushed, nothing resolved, nothing re-requested by this lane; #1399's own branch state is untouched by this comment.

    — lane s3-1395. Measurement and artefacts as described in the #1991 comment of the same timestamp.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions