feat: add fail-closed physical write-domain admission - #183
Conversation
Pin an existing local NTFS directory and atomically reserve a HANDLE-relative marker. Preserve unresolved markers across destructor/owner death; allow explicit withdrawal only before writes begin, with no automatic recovery or writer-completion authority. Keep CLI and existing build callers unchanged. Add fixed real alias, contention, abnormal-owner/residual-writer tests to the existing native executable and a Debug/Release evidence workflow, plus writable-state inventory and scope limits. VERSION remains5.5.0.
Actual native domain gates passed in both configurations; owner death did not authorize takeoverExact head
In both configurations, the same-domain alias contenders produce exactly one acquired/one blocked (raw NTSTATUS3221225525/0xc0000035), while distinct physical domains produce two acquired. Winners stay reserved until both attempts are recorded; no favorable ordering was selected afterward. Real junction retargeting preserves the pinned original identity and HANDLE-relative creation, not the new lexical target. Explicit unstarted withdrawal works; empty/corrupt/directory markers and invalid/moved states remain refusals. The death test retains the child's process creation identity before terminating the owned parent HANDLE, confirms parent exit73 while child remains alive, and confirms the released exclusive marker HANDLE was not inherited. Raw payload is exactly No existing build/CLI caller uses this primitive; the tests do not establish actual MSVC writer completion, recursive output containment, power-loss durability or usable project commit/recovery. The retained file records are test evidence, not a complete syscall trace. The 25 local state/error checks use simulated Win32; an additional unsafe automatic-destructor-deletion mutation was compiled locally and rejected(exit134), not counted as native coverage. This closes the dedicated native-domain gate only. Full standard Debug/Release/selfhost/package, original70/42/batch/target controls and independent ABBA remain required before final merge review. No post-submission source correction, same-head native retry or weakened check was used. |
Iviesever
left a comment
There was a problem hiding this comment.
Final review — accept conservative single-directory admission, not a complete build transaction
Implementation self-review with separate read-only source reconstruction, native-artifact inspection and statistical replay; not an independent human approval.
Exact base: d7428af12a735e7234ccd31e30572ec76471ffb1.
Reviewed head: ff4d1110faf656bb150502ea42ca5f382d37bc03.
Candidate tree: ac25db90468660b8945bc18a7c926830c272d840.
Native test-merge: 00c7f61f898469be3628957a00dbb7cd431aa693, identical tree and exactly those base/head parents.
Seven files, 679 additions/1 deletion; 420 of422 existing files byte-identical, two modified and five new,427 candidate files. Full canonical source archives, seven Git blobs and exact patch replay agree. This is a new public product primitive plus tests/documentation, not a test-only change. The new implementation is registered as the81st non-main product translation unit; the79 native-test executable inventory is unchanged. Existing product implementations/callers, benchmark, generic process runner, CLI/freshness and VERSION remain unchanged.
Product boundary reviewed
The class pins ONE existing local NTFS directory with a non-inheritable HANDLE and volume/128-bit file identity. open is read-only and creates neither directory nor marker. Unsupported identity/filesystem cases refuse instead of substituting a textual key. Identity is scoped to the held object, not arbitrary deletion/recreation or volume reset.
Reservation atomically creates a fixed marker relative to the retained RootDirectory HANDLE using FILE_CREATE, not a pathname reopen or OPEN_IF. Junction retargeting after pinning cannot redirect this create. Existing active, abandoned, empty, corrupt or directory markers block admission; native errors remain refusals, not takeover authority. Marker content is diagnostic and never interpreted as a PID/expiry recovery certificate.
Only explicit withdraw_unstarted may remove the exact owned marker HANDLE, and only before begin_writes; the cooperative caller must have submitted no writer in that state. Normal destruction, owner death and move-assignment replacement do not clean a marker. Once writes begin, there is deliberately no completion/reset/recovery API. Write/flush/disposition/close anomalies cannot become successful release claims. Flush is not namespace durability across arbitrary power loss.
This primitive is intentionally NOT ready to be wrapped around a complete build: active transactions cannot yet be marked clean. It neither intercepts legacy writers nor proves recursive containment, handles missing-root initialization, acquires overlapping/multiple roots, or defends against same-permission hostile marker removal. Future pathname-based writes must resolve their own containment/ancestor/reparse races; pinning the marker root does not solve that write-set problem. No build/CLI/plan/compdb caller adopts it here. Allocations may throw, and an instance is not concurrently mutable. There is no process termination policy or shared-service writer-completion authority.
The accompanying inventory records discovery before target setup, toolchain project caches and invocation-private temporary scripts, scan/compile/PCH/module outputs, native side outputs and link/archive cache replacements. It identifies external overrides, nested/reparse destinations and paired-native-subshard sharing as unresolved integration requirements rather than pretending a .mqb marker covers everything. Foreground execution remains outside the future transaction.
Actual current-head native gates
All 17 triggered workflows completed successfully on this first published head; no source revision or same-head retry was requested.
- Physical Write Domain Admission #1/34487992805: actual current MQB/probe builds and 39/39 fixed native checks in both Debug and Release. Both original ZIPs include per-check results, contender files, physical identities, residual payload and actual probe bytes.
- Native Debug #747/34487992608: actual Debug build, all four paired subshards, ambient/include/runtime/parameter/freshness/side-output checks and final gate passed. Standard job 102910215200 also executes the39 new checks and the original process-runner suite.
- Native Release #629/34487992534: Stage0, all four paired subshards, full self-host and exact runtime-only package validation passed. Standard job 102910382623 executes the39 checks with the original process suite. Self-host/package 102911498326 is completed, not merely queued; publish-release skipped.
- Default Endpoint #32/34487992585, Private Ownership #34/34487992622, Typed MSVC Batch #10/34487992584, Real Target Admission #8/34487992612 passed their actual original native gates.
- Performance #616/34487992618: both exact checkouts, both Release builds, instrumentation verification, all19x4 ABBA measurements and upload ran in job102907102219.
- Documentation#190, Cross-Stage#222 and seven applicable inspection/reporting workflow statuses pass. Those ancillary statuses are not presented as a full download of every raw artifact. Untriggered old File Event/PDB Open studies are not described as current reruns.
The dedicated and standard Debug/Release runs are predeclared independent configuration gates, not adaptive retries. Existing C4100/C4996/D9025 warnings remain; no warning-free/WX claim. Dedicated probes used image20260824.214.3; other jobs include20260907.229.1, so identical historical host state is not claimed.
Native identity, contention and dead-owner evidence
Both configurations verify actual Unicode/case/dot/junction aliases, retargeting after pinning, original-HANDLE-relative creation, live root/marker replacement refusal, move/invalid states, empty/corrupt/directory marker refusal and explicit pre-write withdrawal. Same-domain process contenders produce exactly one acquired/one blocked; distinct physical domains produce two acquired. All attempts are recorded before winners release. Collision retains raw NTSTATUS0xc0000035, not an invented clean result.
The abnormal-owner test retains the child's creation identity and process HANDLE, terminates only the owned fixture parent HANDLE with exit73, and observes the child still alive. The exclusive marker handle is gone and was not inherited, yet another claim remains blocked. The original child payload is exactly before-owner-death\nafter-owner-death\n: actual writing occurs after owner death. Another claim remains blocked after the child exits as well. Normal owner exit23 and ordinary destruction also retain unresolved state. These are positive demonstrations that dead owner/released kernel handle/known child exit are not automatic recovery authority.
Only the disposable harness cleans its tree after all known children exit; there is no product cleanup/recovery path. This is a real Win32 residual writer, not a real MSPDBSRV transaction under the new primitive. It does not demonstrate actual MSVC writer completion, recursive output closure, hostile manipulation or power-loss recovery.
Dedicated artifact hashes: Debug10156607515 a651bcdde669578610e35787093c12e7154185673a0e0c6818f3922b70ca7442; Release10156618738 364ca4fbc4b5e7647c5025d82253c45d0cebe993cfb43cb211263f6b044c54d0. Native probe hashes independently match provenance and actual ZIP members: Debug ba972398e712ba52d3df4c9a419efa65dc7ee01322d9dcf624f1b43dfcdba9c5, Release 4172c099e4742d17a1089b07875e24e0fec6b1102c1a73331de99594ca1b1ef2.
Existing outcomes retained, not conflated with new admission coverage
Independent raw replay verifies default70/private42 complete, all required unmanaged/direct/scheduler positive controls,150ownership-record expectations(113accepted/37rejected), exact Windows collector hash and all14scheduler/direct input comparisons(56sources/70argv).
Default retains three original adverse managed B failures: /ZI A-started cancel(C1083/C2471), PCH Release A-started normal/cancel(C1090). Private retains three: /ZI A-started cancel, PCH Debug A-started normal and Modules Debug A-started normal(C1090). Original exits, unattempted link/run and separate recovery0 remain. Across both modes all28 A-started managed endings still kill the original service, so that policy remains unsafe. Audited721/411original tool results and1442/822diagnostic files; sparse B owner identity16/70 and4/42 is not all-writer evidence.922/529binary inventories are post-case hashes, not failure-instant bodies.
Both six-case real-MSVC regressions also pass independently. Batch evidence retains18original results/36diagnostics, including two injected C2338 failures classified failed despite cancellation. Target evidence retains48results/96diagnostics,96cache-body copies/120snapshots and accurate post-stop dirty freshness. Original successful sibling caches and pending/failed source states remain separate.32target-record expectations pass. Actual input executables match their own source/provenance. None of these builds uses the new domain primitive; they are existing-path regressions, not new lease-integration proof.
Independent unchanged ABBA — all samples retained
Artifact 10156842040,35335bytes,SHA256 4bc6259f46fd716777bc14f1d24e7a9d07545cfdfa25fb6bc51e0702f2fcb750. Recomputed all76pairs, stored arithmetic, AB/BA/AB/BA order, paired medians/MAD/nearest-rankP95 and marginal medians. All72instrumented complete counters/breakdowns/compile-link-archive hit-miss vectors match; four external counters are unavailable, not zeros. Only the last row uses timings-off external elapsed; four-pairP95 is the maximum, not a population estimate.
| Scenario | Paired median delta ms | Paired median delta % | MAD ms | Maximum delta ms | Slower pairs |
|---|---|---|---|---|---|
| cold | -3.990 | -0.26 | 39.865 | 36.400 | 2/4 |
| no-op | -0.297 | -6.64 | 0.098 | -0.147 | 0/4 |
| single-tu | 1.512 | 1.67 | 2.326 | 4.022 | 2/4 |
| public-header | -1.850 | -1.87 | 2.906 | 1.895 | 2/4 |
| build-run | 0.209 | 1.45 | 1.467 | 3.130 | 3/4 |
| link-only | 1.632 | 3.15 | 4.263 | 13.057 | 2/4 |
| target-scale-cold | -81.581 | -2.09 | 112.937 | 180.737 | 1/4 |
| target-scale-no-op | 0.635 | 2.20 | 0.556 | 8.373 | 3/4 |
| target-scale-no-op-auto | 2.662 | 9.88 | 2.828 | 10.107 | 2/4 |
| target-scale-no-op-j1 | 0.337 | 0.92 | 0.065 | 0.435 | 3/4 |
| target-scale-common-header-no-op | -1.030 | -3.19 | 0.475 | -0.337 | 0/4 |
| target-scale-single-tu | -0.245 | -0.17 | 2.250 | 9.174 | 2/4 |
| discovery-cold | 10.130 | 0.64 | 15.360 | 33.913 | 3/4 |
| discovery-no-op | -0.039 | -0.49 | 0.139 | 0.105 | 2/4 |
| discovery-header | 5.633 | 5.51 | 9.456 | 24.917 | 3/4 |
| modules-cold | 16.613 | 1.02 | 19.613 | 38.332 | 2/4 |
| modules-no-op | 0.075 | 1.69 | 0.156 | 0.304 | 2/4 |
| timings-enabled-no-op | -0.060 | -1.73 | 0.087 | 0.072 | 1/4 |
| timings-disabled-no-op (external) | 0.374 | 3.31 | 1.084 | 1.949 | 2/4 |
Unrounded external paired medians +0.37385ms/+3.3079722695% do not cross the unchanged BOTH>1ms AND>10% gate. Keep all slower cases and scale-cold+180.737ms tail. No speedup/zero-overhead claim, presumed-noise deletion, AA subtraction or historical #170/#599/C1041/cold-tail debt closure. Existing production callers do not invoke this primitive, but the newly linked translation unit still means zero overhead cannot simply be assumed.
The original comparison stores runtime executable paths, not commit SHAs or executable bodies. Exact source checkout/build identity was inspected separately in native job102907102219; that provenance is explicitly labeled log-inspection metadata. The first local portable replay incorrectly asserted SHAs in comparison JSON and failed. Only that offline assertion was corrected to validate the actual path fields plus separately inspected provenance; the failure log is retained. Final full portable replay passes. No raw archive, product code, native result or performance measurement was changed or rerun.
Decision and next bounded topic
Accept normal merge with expected head ff4d1110faf656bb150502ea42ca5f382d37bc03, subject to unchanged main/protection. All predeclared current gates passed without waiver. The accepted scope is conservative physical identity and cooperative single-directory reservation, with no automatic post-write cleanup. It is not whole-project single-writer integration, usable automatic commit/recovery, CLI cancellation or completion of M1b. Keep VERSION5.5.0, #172HOLD and historical reliability/performance debts open.
Next independent small topic: a read-only inventory and physical mapping of the complete intended write set before any reservation or build launch. Account for early discovery/toolchain caches, overridden outputs, missing directories, nested/overlapping roots and child reparse/external destinations; unknown or uncontained writes must remain explicit refusals. Do not add a naive finish()/stale-marker deletion or adopt a CLI lease until writer-completion and recovery authority are proven. Keep foreground execution outside the future transaction; do not bundle another observer or resident service.
Reproducibility and limitations
Twelve immutable core ZIPs, complete canonical base/head source, exact patch, hashes, local test material and a fully executed portable read-only replay are retained for delivery. This is not every artifact or full log from all17workflows. Core retention30days. New domain probe bodies are included; existing diagnostic generated-binary inventories are post-case metadata. No actual ABBA binary pair or OS trace is claimed archived.
The25local state/I/O-error checks run the actual implementation with simulated Win32 under GCC strict warnings/ASan+UBSan; a deliberately unsafe destructor-auto-delete mutation is rejected(exit134). These are not actual NTFS I/O-failure injections or local MSVC/ETW execution. An unreferenced prepublication manifest transcription blob was rejected before constructing the published tree. The new Windows behavior is supported separately by the actual native runs above. Native log notes/excerpts are labeled as such. Title/ready skips and new post-merge push CI are not substituted for these completed exact-tree gates.
Post-merge delivery replay correction — use the exact original default artifact, not the earlier transcribed summaryResumed live reads confirm #183 is already merged as The final review's default-matrix paragraph contains a transcription mismatch. Artifact10157310068,19799916bytes,SHA256 -70/70 records complete, all required unmanaged/direct/scheduler positive controls pass. Private artifact10156977270 SHA256 All12coreZIPs were downloaded/CRC/SHA checked and the portable offline replay completed again. Dedicated Debug/Release39checks each,150ownership record expectations,32target record expectations, six batch/six real target-cache cases and all76ABBA pairs reproduce. Current external no-op medians remain +0.37385ms/+3.3079722695%,72instrumented full semantic vectors match; nothing about the original benchmark changed. The delivery being regenerated here contains these12immutableZIPs, manifests, exact source/merge identity metadata, the unchanged BASE source needed by the existing target/collector audit dependencies, and executed portable replay. It does not claim to contain the full candidate-source archive/patch, prior local simulated-Win32 binaries or complete native CI logs. Those current code bytes remain in the accepted Git commit. The previous workspace/source-package was unavailable in this continuation; it was not silently reconstructed from guessed content. A source-archive network fetch failed and did not modify GitHub. This is an evidence-summary/delivery correction, not a new source revision, new experimental batch or a claim of historical root-cause resolution. The accepted cooperative single-domain/no-auto-takeover scope and all remaining project/CLI/recovery limitations remain unchanged. |
Final decision: accept conservative physical admission, not a project transaction
Final exact-source review, native evidence, complete19-row ABBA and scope-limited decision
Accept normal expected-head merge. This adds an opt-in product primitive; no current CLI or build caller uses it. After writes begin there is intentionally no completion/reset/recovery API. #172 remains independently held, M1b incomplete and historical C1041/performance debts open.
Exact accepted source
d7428af12a735e7234ccd31e30572ec76471ffb1.ff4d1110faf656bb150502ea42ca5f382d37bc03.ac25db90468660b8945bc18a7c926830c272d840.00c7f61f898469be3628957a00dbb7cd431aa693, exact base/head parents.Narrow product contract
WindowsWriteDomain::openpins one existing absolute local NTFS directory, reads its held volume/128-bit file identity and creates nothing. Reservation creates the fixed unresolved marker atomically via NtCreateFile/FILE_CREATE relative to that retained directory HANDLE, not by reopening a path. Junction retargeting after pinning cannot redirect the marker. Unknown/inaccessible identity and any existing marker—including abandoned, empty or corrupt—refuse admission; no PID/age/timeout/content takeover.Only explicit
withdraw_unstartedcan delete the exact owned marker HANDLE, beforebegin_writes, when the cooperative caller has submitted no writer. Destruction/normal exit/owner death never automatically clean a marker. Write/flush/disposition/close errors are not successful-release evidence. After entering writing, the marker remains unresolved even if known clients exit. Flush does not establish arbitrary power-loss namespace durability.This is not yet usable as a complete build lock: active writes have no safe commit/recovery operation. It does not intercept legacy writers, close a recursive write set, initialize missing roots, handle nested/multiple domains or defend against hostile same-user removal. Future string-based writers still require containment/reparse/ancestor-race handling. The new document inventories current discovery/toolchain/scan/compile/PCH/module/link/archive writes and those integration gaps. Foreground execution stays outside the future transaction.
Completed current-head gates
No source revision or same-head native/CI/benchmark retry after publication. Dedicated and standard configurations are predeclared separate gates. Untriggered old File Event/PDB Open studies are not labeled rerun. Existing build warnings remain; no warning-free claim.
Actual dead-owner and alias evidence
Native39-check audit and exact probe hashes
Both configurations verify Unicode/case/dot/real-junction identity, junction retargeting after pinning, original-HANDLE-relative create, root/marker replacement refusal, moved/invalid states, explicit unstarted withdrawal and retained malformed/abandoned markers. Same-domain process contenders produce exactly one winner; different domains both win. Every attempt is recorded before winners release.
The owned parent exits73 after termination through its retained HANDLE while a separately retained child remains alive. The exclusive marker HANDLE is gone and was not inherited, yet another claim is refused. The child actually appends
after-owner-deathto its file after parent death; takeover is still refused after the child exits. Normal owner exit23 and scope destruction also preserve unresolved state. This is a real Win32 writer test, not proof of MSPDBSRV completion under a new project lease. Test harness cleanup is not a product recovery API.Original failures and performance remain visible
Default/private preserve three/three original adverse managed B failures, raw diagnostics, unattempted link/run and separate recovery. All28A-started managed endings still kill original services.721/411original result files and1442/822diagnostics audited. Sparse owner identities16/70and4/42 do not authorize takeover. Six real batch cases preserve their two C2338 failures despite cancellation; six target cases preserve old target/cache bytes while freshness correctly remains dirty. Those builds do not call the new primitive.
External no-op paired median +0.37385ms/+3.3079722695%,2/4slower,max+1.949ms, does not cross the unchanged BOTH>1ms AND>10% gate. All76pairs/72semantic vectors are recomputed; external counters unavailable,not zero. Only the external row is timings-off elapsed; four-pairP95 is a maximum. Preserve all unfavorable rows and scale-cold+180.737ms tail. No zero-overhead/speedup claim, noise deletion, AA subtraction or historical debt closure.
Raw comparison JSON records runtime executable paths, not commit SHAs/binary bodies. Exact checkout/build provenance is separately inspected in native job102907102219. An initial local replay mistakenly expected SHAs in JSON; only that offline assertion was corrected and its failed log retained. Final full replay passes without changing source, raw measurements or CI.
Acceptance, next boundary and retained evidence
All predeclared current gates pass without waiver. Accept only the physical single-domain reservation primitive, not a complete transaction, automatic post-write cleanup, CLI lease, shared-service termination, M1b completion or release.
Next independent topic: read-only intended-write-set inventory and physical root mapping before reservation. Account for early caches, overridden outputs, missing/nested roots and reparse/external destinations; unknown containment must remain explicit refusal. Do not introduce naive finish/stale-marker deletion or default CLI locking before writer-completion/recovery authority exists. Keep foreground execution separate; no observer/resident-service bundle.
Delivery retains12immutable coreZIPs, full canonical source archives, patch, hashes and an executed portable read-only replay. Not every Actions artifact or full job log; core retention30days. New domain probe bodies are included, but no ABBA binary pair/OS trace is claimed. Existing generated-binary inventories are post-case metadata.25local simulated-Win32 state/error checks and an unsafe-destructor mutation are not actual NTFS fault injection or local MSVC/ETW execution. Title/ready-triggered skips and post-merge push CI are not substitutes for completed exact-tree validation.