chore: le Result porte le round 3, et la correction sur le code de sortie e2e
This commit is contained in:
@@ -212,3 +212,36 @@ The twenty-five access routes the review found closed were left alone, and the s
|
|||||||
|
|
||||||
`delete` and `clear` now act only on what the view shows. That is a WRITE-side narrowing justified by the read boundary, and it is the one place this task went beyond the finding: it was done because `has` already refuses the same question, so the view was contradicting itself. A fresh adversary should weigh whether a holder losing the ability to clear a collection they cannot fully see is the right trade.
|
`delete` and `clear` now act only on what the view shows. That is a WRITE-side narrowing justified by the read boundary, and it is the one place this task went beyond the finding: it was done because `has` already refuses the same question, so the view was contradicting itself. A fresh adversary should weigh whether a holder losing the ability to clear a collection they cannot fully see is the right trade.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Round 3 - one leak, three outages, and a correction I owe on my own reporting
|
||||||
|
|
||||||
|
**FIRST, A CORRECTION TO ROUND 2's REPORT.** I called the e2e gate green on the SUMMARY LINE and never captured the process's exit code. Sometimes it is `1`: the runner prints its clean summary and then HANGS in teardown until its own 25-minute wall clock aborts it (`[e2e deadline] ... This is a HANG, not a verdict`). **Intermittent, and pre-existing - not mine.** Counted over every run recorded here, the abort follows a clean summary in **3 of 7**, and one of the three is `scratchpad/e2e-run1.log`, written at 14:33 on 2026-09-24 against `46 passed` and predating this task's starting commit `5993a8c` (17:50). The CHECKS are the verdict and they pass in all seven. Reported rather than fixed: it is the harness's teardown, outside this task.
|
||||||
|
|
||||||
|
**F1, the leak, closed - and it settles the trade I had asked to have weighed.** `delete` and `clear` asked `keep`; `add` did not. That asymmetry made the sentence I had just published true by coincidence, because the ungated `add` MANUFACTURED the state the other two then handled partially: bob plants an object into ALICE's document, the view filters it straight back out so he never sees it again, the two-way binding commits it there, and `clear()` leaves it behind. Reproduced, then fixed, then re-run.
|
||||||
|
|
||||||
|
The arbitration, adopted: **all three ask the same question.** What they ANSWER differs because the members differ, and that is not a residual asymmetry but the members' own contracts - `delete` has `false`, which is the Set contract's word for "it was not there" and is true of the view; `add` returns the collection whether or not it did anything, so it has no value meaning "that did not happen" and therefore THROWS.
|
||||||
|
|
||||||
|
**F3/F4, the outage, closed.** Eighteen declared array members plus `includes` and the seven ES2025 set combinators were throwing for the holder whose data it was - a leak traded for an outage, which is not a repair. The view now serves **everything `@ng-org/alien-deepsignals` declares non-mutating**, computed over the readable items. The three key sets are restated (the package exports no subpath for them, and `src/` may not import an optional peer at runtime), and a test READS the shipped `dist/iteratorHelpers.js` and fails if the lists have parted company - so the restatement cannot drift silently. The misnamed `iteratorHelperKeys` comment is corrected by the same change.
|
||||||
|
|
||||||
|
**F2, latent, closed.** The descriptor trap returned an ACCESSOR untouched, so its getter - which reads the target - was a door around the view. Not reachable on the shape that ships; reachable on the next one, which is the whole claim this file makes. Getter routed through the view, setter refused.
|
||||||
|
|
||||||
|
**F5, closed on the view's own account, and the fake no longer diverges.** There were no `set`/`deleteProperty`/`defineProperty` traps, so against a plain ordered array `view[0] = x`, `delete view[0]` and `view.length = 0` all went through, the last defeating the gated `clear`. Production was protected BY THE TARGET, which is resting on a guarantee this view does not make about a shape it does not control. The view carries it now, proved at the unit level against a PLAIN array so that what refuses is unambiguously the view. And the fake builds the REAL collections - `deepSignal(new Set(...))` and `readOnlyArray(deepSignal([...]))` - so it is neither more correct than the target (last round) nor more permissive (this round).
|
||||||
|
|
||||||
|
**MY OWN SWEEP OF THIS ROUND'S REPAIR found two more**, which is the discipline working rather than a surprise: `Object.setPrototypeOf(view, other)` replaced the REAL collection's prototype, after which iterating it throws for every identity - the `clear` problem in another key - and `Object.preventExtensions(view)` (what `Object.freeze` begins with) wrote to the target and would have stranded the index projection, which is only lawful while the target is extensible. Both trapped, both pinned.
|
||||||
|
|
||||||
|
**The memo claim corrected**, not removed: it buys `result.data === result.data` within one call, and the cross-render stability it used to claim is unattainable because `useDeepSignal` replaces its root proxy on every relevant rerender.
|
||||||
|
|
||||||
|
### Round 3 gate, verbatim
|
||||||
|
|
||||||
|
```
|
||||||
|
486 pass / 0 fail / 1450 expect() calls, six consecutive runs (baseline 465 pass / 0 fail)
|
||||||
|
src exit=0 e2e exit=0 concept lint: 0 ERROR
|
||||||
|
== ORM live-read summary: 5 passed, 0 failed, 5 declared - run 0.6 min == (process exit 0)
|
||||||
|
== Polyfill e2e summary: 47 passed, 0 failed, 47 total == (process exit 0)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Follow-up opened
|
||||||
|
|
||||||
|
`e2e/run.ts` INTERMITTENTLY fails to exit after printing its verdict - 3 runs in 7 here, one of them predating this task - and is then killed by its own 25-minute deadline, exiting 1 on a batch whose every check passed. Pre-existing and outside this task, but it makes the exit code an unreliable CI signal, and it is the kind of flake that gets read as a failure of whatever changed last.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user