← Commit history

docs: 0.5.7 — drain reports the window it reasoned over; CloseDoc(path) discriminator; drain-gate protocol

Drew Owens ·f661c1f548 ·1mo ago ·parent 3f4e759
3 files changed +77−2
README.md+18−2
@@ -269,7 +269,23 @@ not create, and it never launches or stops SOLIDWORKS.  ## Roadmap -- v0.5.6 (this): **a title is not an identity — and the drain's CLOSE was the one+- v0.5.7 (this): **the close key is right; the window it reasoned over was not.**+  `done` never consulted `WalkStop::complete()`, so a walk that stopped at its scan+  cap or on an invalidated iteration reported a finished drain with temporaries+  still open past the window (measured: 55 of 60 scanned, a temp at #60 still open,+  `done:true`). `done` now requires reaching the end AND `documentsScanned ==+  documentCountBefore`; `walkStop` is published; and the collision claim is scoped+  to what it was checked over (`titleCollisionsCheckedOver`, and the hint says so).+  The mock selected victims across the whole session while reporting a 55-document+  scan — it is window-bound now, which is what makes any of those properties+  testable. And the premise the whole close rests on — that `CloseDoc` accepts a+  FULL PATH, which its help text does not promise — is now discriminated rather+  than assumed: a close that returns success and moves no count is a CAPABILITY+  failure (`close_by_path_unsupported`), the drain stops, and it never falls back+  to a title; only a count that DROPPED while the victim is still open is+  `wrong_document_closed`. `tools/drain-gate.py` proves the premise live on+  documents the bridge makes itself. 263 tests.+- v0.5.6: **a title is not an identity — and the drain's CLOSE was the one   place that rule was missing.** Victims were chosen by PATH and then closed with   `CloseDoc(title)`, which resolves by name and does not prompt: on Drew's live   session, leaked temps titled `First.step-1.SLDPRT` sit beside his SAVED@@ -284,7 +300,7 @@ not create, and it never launches or stops SOLIDWORKS.   models `CloseDoc`'s by-name resolution, so a close-by-title now fails the suite.   A walk that ended early (a `GetNext` on an invalidated iteration) is no longer   reported as complete: `walkComplete` / `walkStopped` are measured and `done`-  requires reaching the end. 257 tests.+  requires reaching the end. - v0.5.5: **the degrade path was itself an unbounded marshal.** Found on   the live 2144-document session the hour 0.5.4 was deployed: `swx_docs` still   timed out at 30 s and the com host was killed, while `GetDocumentCount`
SKILL.md+7
@@ -300,6 +300,13 @@ adom-bridge --ai-thread "<thread>" swx_save_as '{"outputPath":"C:\\parts\\bracke   live 2144-document session). `swx_close_all_documents` on such a session still   closes, but reports `closed`/`remaining` as **null** with counts, and names the   unknown in `skipped`. Never read a null list as "nothing there".+- **A drain that says `done:false` is not finished — read `walkStop`.** The drain+  looks at a bounded WINDOW per call (`documentsScanned`), and `done:true` means the+  walk reached the END of the session with nothing left. `walkStop` is+  `reachedEnd` / `hitMax` / `timedOut` / `iterationFailed`, and+  `titleCollisionsCheckedOver` says how many documents the collision check actually+  covered — a same-titled document beyond the window is not in that list. Call it+  again until `done:true`. - **The drain never closes a document whose title another open one shares.** It   closes by full path and verifies each close, but `CloseDoc` resolves by name — so   a shared title is refused and reported in `titleCollisions` (with every path that
docs/IMPORT-LEAK.md+52
@@ -380,3 +380,55 @@ pass 5's F3 (the path was always empty), in a new place.   a document closed under us — is not the end of the session. `walkComplete` and   `walkStopped` are in the response and `done` requires `reachedEnd`, no   collisions and no failed closes.++## Adversary round 10 → the close key is right; the WINDOW it reasons over was not (0.5.7)++Pass 10 confirmed the pass-9 fix at the mechanism (the fixture scenario — two+temps plus a saved same-titled document, bridge-launched — is safe) and found that+everything *around* the close still spoke as though it had seen the session.++* **`done` did not consult `WalkStop::complete()`.** `hit_limit` was seeded from+  `walk_stop == TimedOut` alone, so a walk that stopped at its scan cap+  (`hitMax`) or on an invalidated iteration (`iterationFailed`) was treated as one+  that reached the end. Measured on the adversary's fixture: 55 of 60 documents+  scanned, a temporary sitting at #60 still open, `done:true`. It is now+  `done = reachedEnd && scanned == documentCountBefore && no collisions && no+  failed closes && the batch limit was not hit && no root mismatch`.+* **`walkStop` is published** (`reachedEnd` / `hitMax` / `timedOut` /+  `iterationFailed`). It was computed, named, and never sent — so a caller could+  not tell those four apart, and `titleCollisions: []` was uninterpretable.+* **The collision claim is scoped to the window it was actually checked over.**+  `titleCollisionsCheckedOver: documentsScanned`, and the hint says so in words:+  collisions were checked among the N documents this call scanned, not across the+  session. A same-titled document beyond the window is invisible to the check —+  harmless for the close, because the path is the key, and load-bearing for the+  report.+* **The mock is window-bound now.** It selected victims and checked collisions+  over the WHOLE session while reporting a 55-document scan, so it closed+  documents its own reported window never reached — which is why 257 green tests+  said nothing about any of the above. Victim selection, the collision check and+  the near-miss count all run over the walked window only.+* **The `CloseDoc(path)` premise is now discriminated, not assumed.** The help+  text says only *"name of the document to close"*; that a full path is accepted+  has never been run live. If a close returns success and the document is still+  open, one extra count settles which of two very different things happened:+  * the count **did not move** → the call did nothing. That is a CAPABILITY+    failure: `closeIgnoredPath:true`, `errorCode:"close_by_path_unsupported"`, the+    drain stops, and **it does not fall back to a title** — that is exactly the+    ambiguity round nine removed. An unreadable count reads as this case, because+    it is the one that accuses nobody.+  * the count **dropped** while our victim is still open → some other document+    was closed: `wrong_document_closed`, stop, report loudly. Still unreachable;+    still checked.+  The mock models the failing premise (`mock-closedoc-ignores-path`: the path form+  returns success and closes nothing), so the discriminator has a test.+* **The server forwards `closedDocs`** (title + path for every document closed)+  and `titleCollisions`, not just counts. A caller needs to know WHICH files went.++`tools/drain-gate.py` is the live proof of the premise, on documents the bridge+makes itself: import the same fixture twice, save one copy under the same title+into a scratch dir, then ONE `swx_close_import_temps {batch:1}` and assert that+exactly one document closed, that it was named by its `IC~~` path, that the saved+twin is still open, that the count dropped by exactly one, that the collision was+reported, and that every document open at baseline is still open. It closes only+what it created and removes its own scratch directory.