@ycheung5/pi-computer-use 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/GLOSSARY.md +38 -0
- package/LICENSE +21 -0
- package/README.md +165 -2
- package/assets/accessibility.cs +208 -0
- package/assets/browser-indicators.cs +37 -0
- package/assets/capture.cs +215 -0
- package/assets/clipboard.cs +197 -0
- package/assets/controls.cs +249 -0
- package/assets/indicator-preview.png +0 -0
- package/assets/indicators.cs +252 -0
- package/assets/node-LICENSE.txt +2732 -0
- package/assets/ocr.cs +86 -0
- package/assets/ownership.cs +59 -0
- package/assets/pointer.cs +229 -0
- package/assets/puppeteer-LICENSE.txt +202 -0
- package/assets/readme-banner.svg +33 -0
- package/assets/stop.cs +197 -0
- package/assets/text.cs +249 -0
- package/assets/wgc.cs +167 -0
- package/assets/window-management.cs +217 -0
- package/assets/window-marker.cs +23 -0
- package/assets/window-references.cs +80 -0
- package/assets/windows.cs +127 -0
- package/dist/accessibility.d.ts +29 -0
- package/dist/accessibility.js +258 -0
- package/dist/browser-actions.d.ts +21 -0
- package/dist/browser-actions.js +213 -0
- package/dist/browser-indicators.d.ts +23 -0
- package/dist/browser-indicators.js +69 -0
- package/dist/browser-profiles.d.ts +10 -0
- package/dist/browser-profiles.js +174 -0
- package/dist/browser.d.ts +11 -0
- package/dist/browser.js +2071 -0
- package/dist/capture.d.ts +74 -0
- package/dist/capture.js +199 -0
- package/dist/client.d.ts +38 -0
- package/dist/client.js +331 -0
- package/dist/desktop.d.ts +20 -0
- package/dist/desktop.js +42 -0
- package/dist/extension.d.ts +4 -0
- package/dist/extension.js +409 -0
- package/dist/launcher.d.ts +6 -0
- package/dist/launcher.js +85 -0
- package/dist/native.d.ts +11 -0
- package/dist/native.js +145 -0
- package/dist/ocr.d.ts +52 -0
- package/dist/ocr.js +246 -0
- package/dist/ownership.d.ts +4 -0
- package/dist/ownership.js +24 -0
- package/dist/pointer.d.ts +108 -0
- package/dist/pointer.js +174 -0
- package/dist/protocol.d.ts +15 -0
- package/dist/protocol.js +1 -0
- package/dist/runtime.d.ts +8 -0
- package/dist/runtime.js +72 -0
- package/dist/settings.d.ts +85 -0
- package/dist/settings.js +449 -0
- package/dist/stop.d.ts +24 -0
- package/dist/stop.js +156 -0
- package/dist/text.d.ts +100 -0
- package/dist/text.js +183 -0
- package/dist/waits.d.ts +19 -0
- package/dist/waits.js +262 -0
- package/dist/window-management.d.ts +25 -0
- package/dist/window-management.js +167 -0
- package/dist/worker.d.ts +1 -0
- package/dist/worker.js +540 -0
- package/docs/README.md +54 -0
- package/docs/adr/0001-preserve-reference-behavior.md +9 -0
- package/docs/adr/0002-window-lifetime-references.md +11 -0
- package/docs/adr/0003-exclusive-desktop-control.md +11 -0
- package/docs/adr/0004-pi-first-acceptance.md +9 -0
- package/docs/adr/0005-default-apps-and-workspace-reuse.md +7 -0
- package/docs/agents/domain.md +9 -0
- package/docs/agents/issue-tracker.md +10 -0
- package/docs/agents/triage-labels.md +9 -0
- package/docs/browser.md +113 -0
- package/docs/implementation-plan.md +139 -0
- package/docs/indicators.md +53 -0
- package/docs/native-interop-research.md +17 -0
- package/docs/ownership.md +25 -0
- package/docs/pi-extension-research.md +57 -0
- package/docs/pointer.md +65 -0
- package/docs/runtime.md +42 -0
- package/docs/settings.md +33 -0
- package/docs/spec.md +161 -0
- package/docs/stopping.md +83 -0
- package/docs/text.md +79 -0
- package/docs/tickets.md +84 -0
- package/docs/validation.md +1372 -0
- package/docs/windows.md +171 -0
- package/package.json +134 -4
|
@@ -0,0 +1,1372 @@
|
|
|
1
|
+
# Release validation
|
|
2
|
+
|
|
3
|
+
Release status: **publication pending**. Installation acceptance #2 is complete for the user-approved first-release scope; final aggregate release approval/publication remains #21. Automated and passive fixture results are evidence for their stated paths, not proof that all applications, physical input, displays or user acceptance work. The [spec](spec.md) defines requirements; this page maps them to runnable checks and pending evidence.
|
|
4
|
+
|
|
5
|
+
## Final release audit
|
|
6
|
+
|
|
7
|
+
Audit date: 2026-11-06. Baseline `89bdea3`; this audit reuses the closed capability owners and does not repeat desktop, physical-stop or paid-model scenarios. No release/tag/registry publication is performed.
|
|
8
|
+
|
|
9
|
+
| Area | Result and practical limit |
|
|
10
|
+
| --- | --- |
|
|
11
|
+
| Functional coverage | All 25 implemented tools map below to named checks and accepted owner receipts. #6/#20 display/recording, #26/#27 text/clipboard, #28 targeting, #30 workspace/pointer, #31 control and #35/#36 agent outcomes are complete within their stated scope. |
|
|
12
|
+
| Current portable checks | `npm run check` passed 187 tests, one skipped at the audit baseline (`/tmp/pi-release-audit-check.log`). The skip is the opt-in historical DSH-provider discovery test because its two reference environment variables are absent; it is not a missing Pi release case. This is not clean-OS acceptance. |
|
|
13
|
+
| Remote CI | Main baseline `89bdea3` passed [GitHub Checks run 42195532251](https://github.com/ycheung5/pi-computer-use/actions/runs/42195532251). The connector's commit-run query is PR-scoped and this environment has no `gh`; a bounded unauthenticated read of public Actions metadata supplied the actual status. This baseline result is not a claim about a later audit commit. |
|
|
14
|
+
| Distribution | Existing `test:package` builds/packs/extracts the distribution and checks local documentation links. The audit strengthens it to require the declared project license/Puppeteer notice, coherent source/lock/packed versions and exclusion of development/environment files. Final artifact check passed: 91 entries, version 0.1.0, MIT license and documentation links verified (`/tmp/pi-release-package-final.log`). |
|
|
15
|
+
| Version and compatibility | Candidate remains 0.1.0, matching the lockfile; no tag/publication. Tested Pi SDK/CLI 1.4.0 and TypeBox 1.3.27. Declared host Node >=22.19.0; private Windows runtime 22.23.4. Other SDK/arm64 configurations are not certified. |
|
|
16
|
+
| Dependencies and notices | Production dependency is pinned Puppeteer Core 25.16.0. The lock records 25 runtime dependency paths with MIT, Apache-2.0, ISC or BSD-3-Clause identifiers; no missing license identifiers or install scripts appeared in that runtime subset. Host-provided peers/dev dependencies are separate. Node and Puppeteer notices remain packaged. Installed dependencies retain their own license/notice files; this inventory records declared identifiers. |
|
|
17
|
+
| Repaired packaging gap | The manifest declared MIT but the root LICENSE was absent. The actual tarball regression first failed (`/tmp/pi-release-license-red.log`); an intermediate link check also rejected the README audit anchor before this section existed (`/tmp/pi-release-license-green.log`). The final check passed after both fixes. This audit adds the standard MIT license and repository/support metadata. No runtime code or license-policy change. |
|
|
18
|
+
| Installation instructions | Built checkout instructions retained. Prebuilt archive extraction + runtime-only dependency install + `pi install .` is documented. Installed Pi 1.4.0 source treats local files as extension resources and local directories as packages; a raw .tgz must be extracted first. Git clones run dependency installation but this package has no prepare build, so raw unbuilt GitHub-source installation remains unsupported. These are source-checked instructions, not a fresh clean-machine pass. |
|
|
19
|
+
| Known limits/failure disposition | Preserve hook-removal limits, explicit Windows activation refusals, retained text pacing, experimental installed Firefox, accepted unverified #28 cases, #6 available-scale scope and #20 recorder/capture-route scope. Earlier failures stay with their repair/collector/environment dispositions; closed owners are not reopened by old wording. |
|
|
20
|
+
| Remaining release gates | #2 is complete on the user-reported second-computer WSL success and explicit acceptance of remaining clean-environment test limitations on 2026-11-09. #21 retains final supported-workflow/limit acceptance and publication reconciliation. The interactive settings editor/reload check was subsequently user-confirmed below. Existing-machine checks do not waive #2. |
|
|
21
|
+
|
|
22
|
+
The README's stale #30/cancellation-pending statements and this page's current capability table are reconciled during the audit. Historical dated receipts remain historical. Final packaging/review receipts are recorded here. Responsiveness review reuses prior scoped evidence: warm native reads had roughly 74 ms medians at the dated lifetime-checkpoint candidate, not a current whole-agent benchmark. Explicit SendInput retains the documented 50 ms per-unit gap plus scheduling overhead; no minimum-delay or universal-latency claim is made. No new observed performance defect justifies a fresh benchmark/model programme in this audit. Clean-install provisioning responsiveness remains with #2.
|
|
23
|
+
|
|
24
|
+
Final local verification passed after the fixes: 187 tests with one historical-reference skip (`/tmp/pi-release-audit-final-check.log`), and a built 91-entry 0.1.0 archive with MIT/license notices, version coherence, development/environment-file exclusion and documentation links verified (`/tmp/pi-release-audit-final-package.log`). Both standards/spec reviews reported no unresolved findings. Root license text follows the already-declared MIT license; runtime code and dependency versions are unchanged. No Windows desktop, physical input, clipboard, personal profile, model call, tag or package publication was used for this audit. The agent-owned audit checkpoint is complete. Subsequent #2 disposition and interactive acceptance are recorded below; #21 final release approval/publication remains open.
|
|
25
|
+
|
|
26
|
+
Current scope, 2026-11-02: [ADR 0004](adr/0004-pi-first-acceptance.md) makes Pi functionality the release criterion. DSH manual/host/model runs, credentials and parity benchmarks are removed. Dated DSH/paired reports and earlier “remaining comparison” statements below are historical evidence, not current instructions or blockers; the [Pi-first queue](tickets.md#execution-queue) owns unfinished work. Reference-backed scripts are optional historical developer utilities, not required checks. Do not run manual DSH comparisons unless the user explicitly restores that scope.
|
|
27
|
+
|
|
28
|
+
The next validation cycle follows the [current implementation phases](implementation-plan.md#detailed-milestones). The [alignment scenario catalog](#alignment-scenario-catalog) below is planned coverage, not additional passing evidence.
|
|
29
|
+
|
|
30
|
+
## First-release preparation
|
|
31
|
+
|
|
32
|
+
Candidate: **`@ycheung5/pi-computer-use@0.1.0`**, not published or tagged. All 25 tools are implemented, with named Windows/WSL2, native/browser, control/handback and agent-workflow receipts in the [capability matrix](#capability-coverage). Installation #2 is complete for its accepted scope and the user confirmed interactive settings/editor/reload. This preparation changes documentation only; prior audit code checks retain their source scope.
|
|
33
|
+
|
|
34
|
+
The user selected the personal npm scope after discovering the unscoped name belongs to another maintainer. Package/lock names are updated together, public scoped publishing is explicit, and author metadata is `ycheung5 <yatfei9@gmail.com>`. npm sets registry maintainer ownership from the publisher account, independently of the author field. No account email/ownership change or registry publication is performed by this preparation. The scoped tarball name is `ycheung5-pi-computer-use-0.1.0.tgz`; earlier unscoped artifact receipts remain historical. The packaged Pi-host runner now resolves the installed package by its manifest name, including the scope. Scoped-package verification passed: `npm run lint` completed with existing warnings/information, `npm run test:package` built and verified all 91 entries including scoped source/lock/packed-name coherence, author metadata and public access; `npm publish ./ycheung5-pi-computer-use-0.1.0.tgz --dry-run` succeeded for the public registry. No registry publication occurred, and the live Pi-host runner was not rerun for this metadata/path adjustment.
|
|
35
|
+
|
|
36
|
+
The release README now introduces capabilities, example tasks, setup, control and tested limits, with an original static SVG banner and CI/license/platform badges. The configured artifact check passed with 92 entries, including the banner and resolved local documentation links. SVG XML parsed successfully; no runtime behavior, desktop test or model call changed. Registry publication remains pending account publishing authentication.
|
|
37
|
+
|
|
38
|
+
Proposed release notes:
|
|
39
|
+
|
|
40
|
+
- Standalone Pi Windows computer use from native Windows or WSL2: accessibility discovery/actions, screenshots/OCR, pointer/text/clipboard, application/window management and browser workflows.
|
|
41
|
+
- Windows default-app and existing-workspace guidance, explicit dedicated browser profiles, personal settings/tool presets, blue control border, emergency stopping and handback.
|
|
42
|
+
- Candidate baseline: Windows 11 x64, WSL2 Ubuntu, Pi SDK/CLI 1.4.0; host Node >=22.19.0. See [installation](../README.md#install-a-built-archive) for the prebuilt archive route. No other Pi extension or separately installed Windows Node is required; first runtime provisioning needs nodejs.org access.
|
|
43
|
+
- Validation: audit checks passed 187 tests with one historical-reference skip; accepted native/browser real-agent outcomes and human checks retain their recorded scopes. Package contents, notices, version and local documentation links are checked by `test:package`.
|
|
44
|
+
|
|
45
|
+
Carry these limits into the public release notes: Windows can silently remove low-level hooks; activation may be refused by Windows; explicit Unicode SendInput retains 50 ms per-unit pacing; installed Firefox support is experimental. Arm64/other SDK configurations, unavailable 200% scaling/other unexercised displays, genuine same-HWND/PID reuse, verified UIPI denial and other recorder/remote/capture variants are not certified. Fresh native-Windows installation, missing/corrupt prerequisites and shutdown in that clean environment remain unverified under the accepted #2 disposition. The second-computer clone/install report does not establish a generally build-free source-install route. These limits do not remove runtime safeguards.
|
|
46
|
+
|
|
47
|
+
Preparation validation on 2026-11-09: `npm run test:package` passed the 91-entry 0.1.0 archive, license/notices, version, development-file exclusion and documentation links. The sandboxed npm pack child first exited without diagnostics (code 226); the same configured check passed with permitted execution outside that sandbox. No source repair was needed. Prior runtime/portable tests were reused because this preparation changes documentation only.
|
|
48
|
+
|
|
49
|
+
Final aggregate approval and actual publication stay under #21; #1 closes after publication. No npm registry or GitHub release has been created by this preparation.
|
|
50
|
+
|
|
51
|
+
## Second-computer installation report
|
|
52
|
+
|
|
53
|
+
On 2026-11-09 the user reported cloning this repository on another computer, installing the extension with `pi install` under WSL, and successfully performing computer actions. The user reports no separate `npm install` or build step. This is human-reported second-machine functional success; no command transcript, checkout revision, host versions or prerequisite inventory was collected. The exact install argument/source and any existing build/cache were not independently established. It does not establish a generally reproducible build-free Git checkout installation route, so the documented built-checkout/archive procedures remain unchanged.
|
|
54
|
+
|
|
55
|
+
This report supplies WSL installation/use evidence for #2. A fresh disposable native Windows install, missing/corrupt prerequisite diagnostics and shutdown in that clean environment were not reported; prior scoped checks remain valid. On 2026-11-09 the user explicitly accepted those unreported cases as first-release test limitations and authorized closing #2. They remain unverified, not passing tests; the install/prerequisite/shutdown safeguards are unchanged. No code changes or new live tests were made for this receipt.
|
|
56
|
+
|
|
57
|
+
## Interactive settings and reload acceptance
|
|
58
|
+
|
|
59
|
+
On 2026-11-09 the user confirmed all four requested checks passed in their Pi session: `/computer-settings show` displayed settings without errors; `/computer-settings edit` opened and cancelled with Esc; reopening and saving unchanged with Enter succeeded; `/reload` followed by `show` retained the settings without extension errors. This is human-reported acceptance of the terminal settings display/editor/reload path, not an independently captured transcript or a separate tool-result renderer test. The session version and host were not separately collected in this confirmation.
|
|
60
|
+
|
|
61
|
+
No runtime changes, desktop input, paid-model runs or repeated capability tests were performed by the coding agent for this receipt. Reuse the accepted #35/#36 supported workflows. Final release/known-limit acceptance and publication remain with #21; #2 is subsequently closed with the accepted limitations in the second-computer receipt.
|
|
62
|
+
|
|
63
|
+
## Design cleanup checkpoint
|
|
64
|
+
|
|
65
|
+
The 2026-11-01 design review and first cleanup are recorded in the [plan](implementation-plan.md#design-revision) and [dispositions](tickets.md#cleanup-dispositions). Shared test-host reuse and in-process report verification preserve all existing assertions. Public worker checks cover argument limits before and after removal of redundant browser validation. Portable checks remain 160 passed with one skipped; build and the 87-entry package/document-link check passed. No Windows desktop or paid-model acceptance was rerun for this cleanup; earlier live results retain their original source scopes.
|
|
66
|
+
|
|
67
|
+
## Reproduce automated checks
|
|
68
|
+
|
|
69
|
+
From a clean checkout with Node 22.19+ and npm:
|
|
70
|
+
|
|
71
|
+
```sh
|
|
72
|
+
npm ci --ignore-scripts
|
|
73
|
+
npm run check
|
|
74
|
+
npm run build
|
|
75
|
+
npm run test:package
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
`test:package` packs/extracts the actual distribution and verifies its required assets plus every local Markdown link/heading. Optional historical utility: `npm run test:parity -- /path/to/dsh-computer-use-win` reads the reference's advertised schemas without desktop calls, comparing all 25 declarations and supported parameter types, defaults, enums, required fields, array/numeric/string bounds, patterns and additional-property restrictions. It does not compare prose or prove runtime behavior. Extra native signed-32-bit bounds on move_window X/Y are reported explicitly. The inspected reference baseline is 0.5.3 at commit `6fb642129595a6357588c70812974951db304662`.
|
|
79
|
+
|
|
80
|
+
On WSL2, serialize all live checks:
|
|
81
|
+
|
|
82
|
+
```sh
|
|
83
|
+
flock -w 120 /tmp/pi-cu-live-tests.lock npm run test:pi
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
`test:pi` creates a new tarball and installs it in a disposable consumer directory with development and peer packages omitted. It loads the result through the real Pi CLI using Pi's public offline faux provider. Normal agent turns execute only health/list_windows, reach settlement and shut down the worker; no paid model, physical input, clipboard mutation, normal browser profile or daily Pi settings are used. On WSL2 it also launches a native Windows Pi CLI with the private runtime. On Windows it exercises that host alone. It verifies host-provided packages resolve without being bundled in the consumer package. `PI_CU_RELEASE_OUTPUT` can name a directory for sanitized JSON evidence; raw desktop window titles are not retained.
|
|
87
|
+
|
|
88
|
+
This runner uses the installed development Pi 1.4.0 distribution as the test host, not a fresh OS/Windows Pi install. Its scripted provider is a test fixture, never a production dependency. Real provider quality, interactive terminal workflows, and dedicated input/user acceptance remain separate checks.
|
|
89
|
+
|
|
90
|
+
The separate `test:pi:browser` companion reproduces six scoped real-model outcomes (`form`, `advanced`, `stale`, `mixed`, `partial`, `cancel`) using the existing local server and isolated headless Edge profiles; `mixed` adds an owned passive native form. It uses the installed Pi host and its existing authentication; no credentials are printed or bundled. Unlike `test:pi`, it makes paid model requests. First build and follow [Windows-readable dependency prerequisites](runtime.md#verification). Preview safely without a build, Windows launch, credential lookup or file write:
|
|
91
|
+
|
|
92
|
+
```sh
|
|
93
|
+
npm run test:pi:browser -- --plan
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Select a named case or `all` and one to three independent resets; the defaults are OpenAI, GPT-6.1 Sol and low reasoning. Requested settings and actual assistant metadata are recorded separately. For example:
|
|
97
|
+
|
|
98
|
+
```sh
|
|
99
|
+
PI_CU_RELEASE_OUTPUT=/tmp/pi-browser-evidence flock -w 120 /tmp/pi-cu-live-tests.lock npm run test:pi:browser -- --scenario stale --runs 3 --provider openai --model gpt-6.1-sol --thinking low
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
The `cancel` case intentionally aborts its real Pi episode after independently observing a held HTTP request and its sole matching pending worker frame. Its successful cancellation report ends the invocation; use separate fresh invocations for independent cancellation resets. It does not complete the requested confirmation.
|
|
103
|
+
|
|
104
|
+
The test-only `PI_CU_TEST_TIMEOUT_MS` sets a 50–180000 ms episode watchdog (default 180000); expiry retains ownership rather than terminating it. Each unique output directory contains its tool trace, independent report and `owner.json`. A normal report requires actual observations, exact server/file oracles, Pi settlement and scoped cleanup. Stale refreshes are explicit fixture-controlled public-tool navigation; the product must return the real stale refusal and the agent must recover with its own new observations. Prior private three-run results below remain historical evidence, not validation of this new collector. A retained report is a failure requiring investigation: its referenced keeper preserves uncertain ownership and fixture pipes, blocks later actions/cases and records identities in `owner.json`; do not treat it as completed cleanup or wait indefinitely for a pass. There are no automatic retries or arbitrary browser termination.
|
|
105
|
+
|
|
106
|
+
The browser fixture now catches synchronous authorization/audit and result-state hook faults, retains a fixture-fault latch and denies further dispatch. Only a journal explicitly in `running` phase permits calls; native selectors, including `windowRef`, remain outside headless-only cases even on waits. The optional mixed case routes explicitly owned native observations/semantic Invoke through the existing visual guard, with separate browser/native references and image-free auditing. A nine-case offline test uses actual Pi `ExtensionRunner` hooks and passive registered tools: healthy running control allows one dispatch; retained/missing/malformed/non-running journals, audit I/O and native-reference input are refused; result-audit and result-processing errors fence the next mutation after I/O is restored. The causal baseline showed SDK-swallowed **result-hook** errors followed by an unfenced passive mutation. Before-hook errors threw and dispatched zero on this installed SDK; no before-hook dispatch leak is claimed. This is a finite test-harness repair, with no production/dependency change or repeated live/model acceptance. Raw red/green checks are retained at `/tmp/pi-cu-browser-guard36-{red,green}.log`.
|
|
107
|
+
|
|
108
|
+
The checked-in companion passed one fresh real-model run of each original browser-only case on 2026-10-31, without retries, after independent guard/oracle review. Candidate `416f8e5` merged integration `5972914`; each report records identical source, compiled worker/browser, unchanged server-fixture and collector SHA-256 manifests. Effective assistant metadata matched the request: OpenAI `gpt-6.1-sol`, low reasoning, Pi 1.4.0. The scoped headless Edge version was 156.0.4314.50, Windows Node 22.23.4, OS build 26200. All three independently confirmed Pi settlement, empty owned profiles, zero matching browser processes and fixture exit. Portable checks passed 133 tests with one skip. No production source, fixture contract or dependency changes were needed for this collector port.
|
|
109
|
+
|
|
110
|
+
| New collector case | Independent result | Retained local evidence |
|
|
111
|
+
| --- | --- | --- |
|
|
112
|
+
| Form/delayed confirmation | Exact Unicode form payload, one submission/start/ready event and an actual positive delayed observation | `/tmp/pi-cu-model-port-20261031/form-1-eueKUy/` |
|
|
113
|
+
| Advanced navigation/dialogs/transfers | Owned child and return, exact prompt, rejected confirm, correlated owned alert dismissal, upload bytes/count one, completed download bytes/count one and truthful final path | `/tmp/pi-cu-model-port-20261031/advanced-1-5pwmai/` |
|
|
114
|
+
| Controlled stale-document recovery | One public-tool reload, actual product stale refusal, independently blank/unsubmitted second form before recovery, model-observed fresh IDs with correlated successful mutation, exact second payload/submission one | `/tmp/pi-cu-model-port-20261031/stale-1-UT7Vn6/` |
|
|
115
|
+
|
|
116
|
+
Each unique directory retains authoritative `report.json` (including its manifest), `trace.jsonl`, `tools.jsonl` and a settled `owner.json`. The output root's `summary.json` is a mutable latest-invocation index: reusing the root for another named command replaces that index but preserves previous case directories. These were separate named invocations; their three case reports remain the evidence. The advanced agent first made three out-of-scope reads that the fixture guard refused without dispatch, then opened the permitted local page and completed the outcome. These are guard recoveries, not product failures. The stale refusal is deliberate injection; prior incomplete/cue-warning runs remain below. These three port checks establish reproducibility of the named scoped Pi cases, not new three-reset acceptance, DSH parity, mixed desktop completion or full #36 closure.
|
|
117
|
+
|
|
118
|
+
### Current host acceptance evidence
|
|
119
|
+
|
|
120
|
+
Ticket #34 was rechecked on 2026-10-30 from WSL2, using Pi **1.4.0**, Linux Node **22.20.0**, the private Windows Node **22.23.4**, and Windows build **26200.9711**. The validation worktree started at `a905fde`; production code remained unchanged from `7a7c0c5`. Windows fixture commands ran outside the subprocess-restricted development sandbox, serialized with the shared live-test lock. No physical input, clipboard mutation, live model request, daily settings change or normal browser-profile access was performed.
|
|
121
|
+
|
|
122
|
+
| Check | Observed result and scope |
|
|
123
|
+
| --- | --- |
|
|
124
|
+
| `npm run check` and build | Type checking, linting, all 42 portable tests and build passed. Existing public host/worker tests cover lazy startup, shutdown rejection, failed launch/recovery, runtime checksum rejection, preset transitions, invalid settings, disabled execution and queued saves; these are not clean-OS installation evidence. |
|
|
125
|
+
| `test:pi` | Production-only tarball installed with development/peer dependencies omitted. Real Pi CLI health/list turns passed from WSL2 and a native Windows process, reached `agent_settled`, produced empty stderr and left no worker process. The provider was the public scripted offline fixture, not GPT or OpenRouter. |
|
|
126
|
+
| `test:wsl` | Both WSL-filesystem and Windows-filesystem disposable copies passed with spaces, Unicode and quotes in their paths; worker reuse, shutdown, parent-exit cleanup, active cancellation and timeout cleanup were observed. See the fixture correction below. |
|
|
127
|
+
| `test:settings` | Native-write/WSL-read and WSL-write/native-read round trips passed with isolated settings; lazy startup, disabled execution, unrelated-tool preservation and visible malformed-file error passed. First environment lookup took 42 ms on this run. |
|
|
128
|
+
| `test:indicators` | Offscreen rendering/protocol checks passed: quiet startup, two reported monitors, configured shortcut, invalid-target quietness and stopping while indicators were disabled. Visible preview was not enabled. Actual shortcut presses and visual/display behavior remain pending. |
|
|
129
|
+
| Native capture fixture | Public Pi tool results contained correctly sized PNG image blocks and coordinate metadata. Snapshot-with-image, no-image and UIA-failure-with-image cases retained their correct error distinctions; native PrintWindow/WGC, covered/minimized fallback, pixels and wrong-owner checks passed. |
|
|
130
|
+
|
|
131
|
+
The native capture fixture initially failed before execution because Windows Node could not resolve `typebox` through this worktree's absolute Linux dependency symlink. It was rerun from the main checkout's Windows-readable dependency tree after verifying the capture runner, production source and assets were identical. This was a test-environment correction, not a package or production-code fix.
|
|
132
|
+
|
|
133
|
+
The first `test:wsl` run failed because its stale assertion expected `COMPUTER_USE_CANCELLED`, while the public client's abortable call surfaces the signal's `AbortError`. The fixture now checks that public result **and** independently reads the cooperating Windows peer's count of cancelled active requests; exactly one must have received cancellation. The corrected fixture passed both filesystem locations. The original failure is retained here; merely accepting any rejected promise would not establish active cancellation.
|
|
134
|
+
|
|
135
|
+
Remaining host acceptance is grouped into three sessions rather than another sequence of individual prompts:
|
|
136
|
+
|
|
137
|
+
1. **Clean installation:** native Windows and WSL2 environments without the development tree; install/update/removal and missing/corrupt runtime or network diagnostics. Current-host package and portable failure tests do not close this gate (#2, #21).
|
|
138
|
+
2. **Interactive Pi presentation:** actual terminal settings editor and reload, rendered images/errors and user-visible lifecycle. Automated CLI/provider and tool-result checks do not prove the full interactive experience; the remaining gate stays owned by #21 after the automated baseline in #34 completes.
|
|
139
|
+
3. **Dedicated desktop presentation/interference at the passive checkpoint:** the [indicator checklist](indicators.md#acceptance-checklist), physical shortcuts, pointer/key cleanup, mixed DPI/display changes and screen-sharing/recording behavior. At that checkpoint the user had deferred physical-input tests; later scoped physical results are recorded below. Outstanding exclusive-control acceptance follows the delivery plan (#20, #21, #31).
|
|
140
|
+
|
|
141
|
+
This establishes the automated/passive host-validation baseline and records its gaps. It does not establish clean-machine readiness, physical-input acceptance, real-model reasoning quality or overall release acceptance. Real-agent tasks remain in #35/#36; DSH setup prerequisites are recorded in the [baseline identity audit](#baseline-identity-and-schema-evidence).
|
|
142
|
+
|
|
143
|
+
### Passive operation evidence
|
|
144
|
+
|
|
145
|
+
One actual native-Windows Pi 1.4.0 RPC registered-command case passed on unchanged reviewed `73d4162`, using only health/wait and a scripted provider. A received 30-second wait remained pending while its identified ownership helper held the mutex; RPC `/computer-stop` was handled, and the exact worker request returned `COMPUTER_USE_STOPPED` after 3699.39 ms from request receipt on the worker's monotonic clock. That duration includes independent busy-state preparation and is not stop-command latency. Its successful released acknowledgment preceded the custom continuation; the custom wait was refused without another worker wait frame, while a fresh ordinary-user operation had a distinct ID and passed its 1 ms wait. Settlements were aborted/normal/normal. Hook/presentation flags remained off, all five recorded Windows processes were independently absent, isolated settings were removed, and all 18 observer records were fault-free. Raw events/identities/proofs: `/tmp/pi-cu-hoststop31-live/receipt/`; source/installed-SDK hashes: `/tmp/pi-cu-hoststop31-live/provenance.json`. This is the native-host result; the separately collected WSL case below does not relabel this source. Neither establishes real-model, physical-key or held-input behavior; #31 stays open.
|
|
146
|
+
|
|
147
|
+
One actual WSL2 Pi 1.4.0 RPC case then passed on unchanged reviewed `e09b12c`. The Linux Pi host used Node 22.20.0 with `/proc` PID/start/executable identity and a separately recorded interop child; Windows worker/helper/console identities were obtained through Windows CIM only from the worker's genuine returned Windows PID. Producer metadata confirmed its actual mapped UNC cwd, relative `settings.json` override and mapped trace path; forwarding used child-only `WSLENV`, with no global setting change. The matching worker wait response was stop-specific after 4824.29 ms from request receipt (including busy-state preparation, not stop latency), and its released acknowledgment preceded the custom continuation. Custom retry produced no worker wait; the fresh user turn used a distinct operation and passed its 1 ms wait. All four recorded Windows and two Linux actors were absent, settings/agent directories were removed, hooks/presentation stayed off, and all 18 observer records were fault-free. Raw receipts and actual source/SDK hashes: `/tmp/pi-cu-hoststop31-wsl-live/{receipt/,provenance.json}`. No physical input, UIA/discovery, clipboard, images, real model, route fallback or additional live reset was used.
|
|
148
|
+
|
|
149
|
+
The actual host cases required no production repair. Independent review corrected a test-oracle gap before either live run: SDK abort/stopped notification alone cannot prove cancellation. The collector now requires the exact pending worker response and same-process monotonic deadline proof, plus a successful released acknowledgment before later turns. Offline normal-completion, late cancellation, missing/wrong response identity/clock and missing/failed/early-release controls preserve those limits. Initial WSL plan/identity setup red and a corrected fake-child test lifetime are test-harness evidence, not product failures. The final configured offline suite passed 147 tests with one skipped; build and the 87-entry package/documentation check passed. These paired native/WSL command cases fill the bounded no-input host-command slice, while physical Pi-host containment, Esc/shortcut, held keys/buttons, DSH host stopping and broader #31 acceptance remain open.
|
|
150
|
+
|
|
151
|
+
Ticket #31 was investigated on 2026-10-30 from WSL2 at integration base `4514b5d`, using the same Pi/Node/Windows versions recorded above. Production source and assets were unchanged. Windows checks ran outside the restricted subprocess sandbox under `flock -w 120 /tmp/pi-cu-live-tests.lock`. No key/button injection, clipboard mutation, physical-input opt-in or daily document interaction occurred.
|
|
152
|
+
|
|
153
|
+
| Evidence | Result and limit |
|
|
154
|
+
| --- | --- |
|
|
155
|
+
| Public Pi/worker portable suites | Busy protocol-peer stopping, queued cancellation, operation identity across turns/custom continuations, settlement, Pi abort, blocked retries, new-user recovery, process retirement and sticky cleanup failure passed. Peer dispatch counts show queued work was not sent; process-existence checks establish retirement. This is protocol evidence, not a blocked native UIA provider or physical-input run. |
|
|
156
|
+
| Timeout non-replay regression | The external peer now journals received actions across replacement processes. Exactly `uncertain-action`, then the caller's explicit `health`, were received by distinct PIDs; the old PID had exited. Previously this test asserted rejection and recovery without independently observing non-replay. The action is a disposable protocol operation, not desktop input. |
|
|
157
|
+
| `test:stop` | Three fresh enhanced runs passed. Independent PowerShell processes opened the actual Windows event and observed unsignaled before stop, signaled afterward, then a distinct unsignaled event for a fresh operation. Same-operation calls were blocked and the next operation recovered. The deliberately invalid HWND/PID click was source-checked to fail identity resolution before dispatch and returned `TARGET_IDENTITY_CHANGED`; it is no evidence of successful clicking or held-button cleanup. |
|
|
158
|
+
| `test:ownership` | Three fresh runs passed using registered Pi tools in separate WSL/native Windows hosts. Competitors were rejected, low-level `agent_end` retained ownership, settlement handed off ownership, a live owner was not displaced during the fixture's one-second observation, and killing its worker allowed recovery. This bounded observation plus the OS-mutex implementation is not a long-duration soak test. |
|
|
159
|
+
| `test:native:waits` with private Windows Node | The existing passive fixture passed window/control transitions, complete timeout versus incomplete absence, OCR transitions, cancellation and subsequent new-operation recovery/window disappearance. It sent no physical input. |
|
|
160
|
+
| Shared owned-provider cancellation subset | The [accessibility collector](#accessibility-comparison-evidence) independently observed entry into a bounded blocked UIA Name-property call before aborting it through each public request seam. Both callers completed cancellation before the fixture's automatic release. Follow-up OS process observations confirmed the same reader was alive after provider entry and absent after cancellation while independent fixture IPC still reported the provider inside its wait with its release event unsignaled; explicit release, fresh-read recovery and disposal followed. See the [provider evidence](#accessibility-comparison-evidence) for method and limits. |
|
|
161
|
+
|
|
162
|
+
Queue and host-lifecycle comparison is source-based; the separate provider subset exercises the reference backend's MCP cancellation, **not the DSH host's stop button**. Pinned reference `mcp/server.mjs` (`dispatchNextBackend`, `cancelBackendRequest`, `dispatchBackend`) also serializes before starting execution deadlines, discards unsent cancelled work, distinguishes interruptible quiet reads from actions needing cleanup, and retires a timed-out backend. Its `mcp/activity.mjs` keeps conversation/turn ownership in the DSH host, releases at `turn/end` and has a 30-second idle fallback; `mcp/takeover.mjs` tracks stopped series and resumes for a new user turn. Pi's settlement/operation identifiers and Windows named mutex are the required Pi/WSL host adaptation, not an assertion that these lifetimes are identical. The cached DSH SDK has no per-session abort API; killing its process would not prove the normal DSH stop-button path.
|
|
163
|
+
|
|
164
|
+
**At that passive checkpoint, still open in #31:** busy physical input, actual held-key/button release and bounded cleanup during input, real Esc/custom shortcut while busy, and user-interference/restoration checks. Physical input had then been deferred; the later [dedicated session](#dedicated-physical-comparison-evidence) added scoped drag-button evidence. Earlier manual reports remain historical observations; the current automated results do not close the broader criteria. Continue the short dedicated session when available rather than repeating passive checks or marking all stopping/ownership acceptance complete. No production repair or new mechanism is justified by this passive run alone; newly diagnosed product gaps belong to #37.
|
|
165
|
+
|
|
166
|
+
### Pi OCR failure acceptance
|
|
167
|
+
|
|
168
|
+
On 2026-11-02, `npm run test:native:ocr -- --failures` passed using Windows Node 22.23.4 from the WSL2 checkout (production baseline `9cbaebd`). Windows resolved the checkout's real `puppeteer-core` dependency before the run. The existing painted HELLO fixture and the public worker protocol were used; no physical input, clipboard changes, installed-language changes or personal-application captures occurred.
|
|
169
|
+
|
|
170
|
+
| Case | Observed result |
|
|
171
|
+
| --- | --- |
|
|
172
|
+
| OCR helper unavailable | Removing only `assets/ocr.cs` from a disposable package copy produced `OCR_UNAVAILABLE` with `NATIVE_RESOURCE_MISSING`. Capture remained available. No text/lines/matches or conclusive absence were returned. Restoring the source allowed another request without restarting the worker. |
|
|
173
|
+
| No profile-language engine | A copied-source injection substituted null for the engine only while a private flag existed. The actual helper's existing null-engine branch returned `OCR_LANGUAGE_UNAVAILABLE`; the public worker preserved the failure, `conclusive: false` and absence of invented text. This proves the error path, not an installation with languages removed. |
|
|
174
|
+
| Actual language selection | Removing that flag used the unchanged `TryCreateFromUserProfileLanguages()` call. Real WinRT OCR recognized the fixture and reported `zh-Hant-HK`, present in its 15 available recognizers. The tool intentionally has no language-selection parameter. |
|
|
175
|
+
| Active cancellation and recovery | A second copied-source barrier acknowledged actual `RecognizeAsync` dispatch before holding result consumption. Aborting the public request settled cancellation, and OS process probing confirmed that OCR helper exited while the hold flag still existed. A fresh operation then recognized the label. This proves cancellation after dispatch, not that WinRT remained computationally busy at the instant of cancellation. |
|
|
176
|
+
| Capture refusal and pre-cancellation | Reused the existing native runner's accepted minimized-target refusal and pre-aborted request evidence; neither was repeated. A desktop fallback is not treated as target OCR success. |
|
|
177
|
+
|
|
178
|
+
The two injections exist only in a temporary copy; the production TypeScript/C# sources and public interfaces are unchanged. The runner verifies each replacement occurs once, uses a bounded readiness/process-exit poll, and removes its worker, fixture and temporary package/cache before printing the final passing receipt. An initial run passed the behavior assertions but failed removal of executable caches on the WSL UNC filesystem; no matching helper process remained. Moving only the private test cache to the fixture's Windows temporary directory resolved this test cleanup failure. The successful rerun confirmed cleanup.
|
|
179
|
+
|
|
180
|
+
This completes #7's scoped failure/cancellation acceptance. Actual clean-machine WinRT/metadata availability remains #2; protected-image compatibility is not claimed. Multi-monitor/DPI mapping remains #6, with [existing localization evidence](#paired-capture-and-ocr-comparison) retained. No additional OCR feature or recovery retry was introduced. Standards and spec reviews found no unresolved findings. Final configured checks passed: 169 portable tests, one skipped; TypeScript, lint, build and the 89-entry package/documentation-link check passed.
|
|
181
|
+
|
|
182
|
+
### Default-app and workspace acceptance
|
|
183
|
+
|
|
184
|
+
The #30 implementation extends the existing launch tool/native helper and Pi guidance; no new tool, dependency, planner or element cache was introduced. The Pi-host guidance regression first failed on the old isolated-browser preference, and the existing built worker refused `resolveOnly` as unknown. The new optional `npm run test:native:management -- --workspace` case uses registered Pi tools from Windows Node 22.23.4 on the WSL2 checkout, with Windows-readable dependencies verified before live execution.
|
|
185
|
+
|
|
186
|
+
The focused sequence passed Windows HTTPS/browser-alias resolution without opening the user's browser; actual Explorer opening through a private GUID file association into the owned fixture; new task-tab creation with original document contents unchanged; independent owned-caller foreground followed by element-only invocation/value editing; explicit background preservation; an explicitly requested separate window; borrowed-window survival across worker shutdown; and unknown-association refusal. Success is printed after private registry/fixture/cache cleanup. It uses no personal documents, clipboard or physical input. The final passing rerun additionally verified activation returns the same lifetime reference used by targetless observations.
|
|
187
|
+
|
|
188
|
+
Initial failures are retained here: the original runner's cleanup hid the first assertion; the owned multiline editor did not expose the assumed Edit/Value pattern, so the fixture now uses a standard single-line Value-capable editor. Unknown extensions initially resolved to generic Open With; production now uses `ASSOCF_INIT_IGNOREUNKNOWN`. A later cleanup script incorrectly returned failure for an already-exited fixture PID; verified-identity cleanup now handles that case explicitly. These runner/provider assumptions are separate from the production routing/association repair. Review found and repaired element-only inheritance and activation-witness propagation gaps before completion.
|
|
189
|
+
|
|
190
|
+
The existing Chromium UIA fixture's optional `npm run test:native:chromium -- --workspace` mode also passed using the resolved Windows default, Google Chrome, with a normal tabbed window and disposable profile. Native UIA alone observed its original tab, invoked the observed New Tab button, verified exactly one additional tab in that same window, selected the original tab and verified its editor value was unchanged. Foreground remained on that window. Renderer readiness was honestly reported as partial; positive observed controls sufficed for these scoped assertions. No CDP/BiDi connection, daily profile, clipboard or physical input was used. An initial return-to-original-tab attempt used an unsupported test argument (`action: select`); the fixture was corrected to the existing invoke default, which selects the supported pattern. Production required no selection change. The existing control regression also exposed a stale fixture wrapper that attached HWND/PID to `list_windows`, which rejects target arguments; the wrapper now keeps listing arguments separate and checks its result explicitly.
|
|
191
|
+
|
|
192
|
+
This proves the owned app and native Chrome workflows plus protocol/guidance contracts, not that a model has completed the equivalent task. Other default browsers/apps, ambiguous/unsupported-workspace handling and the remaining pointer/menu/dialog/restoration outcomes stay with #30; ordinary-agent workflows retain their agent acceptance owner. Existing dedicated-browser/profile and #31 stop/control evidence remain accepted. TypeScript, lint and all 169 portable tests passed, with one skipped. The existing native control regression passed native edit/invoke/focus/scroll, read-only/stale/unsupported and missing-resource checks; its optional sibling restoration remained unavailable because Windows refused that activation and is not counted as passed. Build and the 90-entry package/documentation-link check passed. Final standards and spec reviews had no unresolved findings.
|
|
193
|
+
|
|
194
|
+
### Ordinary Pi workspace actor preparation
|
|
195
|
+
|
|
196
|
+
The real-Pi companion `test:pi:workspace` drives the existing native Chromium fixture through the production extension. It defaults to a side-effect-free plan; `--plan` overrides `--run`. `--preflight` checks owned-window visibility, readiness and cleanup without provider requests. Actual episodes use the installed Pi CLI, existing OpenAI authentication and `gpt-6.1-sol` with low reasoning. No physical input, clipboard changes, personal profiles or protocol-based browser actions are permitted in this scoped check.
|
|
197
|
+
|
|
198
|
+
On 2026-11-04, the user authorized up to three episodes. All three were used:
|
|
199
|
+
|
|
200
|
+
| Receipt | Outcome and disposition |
|
|
201
|
+
| --- | --- |
|
|
202
|
+
| `/tmp/pi-workspace-20261104-approved/reset-1-rBB4KS/` | Fixture failure: Chrome was hidden, so ordinary visible-window discovery returned no owned row. Pi correctly resolved the default browser, reported the missing target and stopped. The independent fixture still observed the original tab. |
|
|
203
|
+
| `/tmp/pi-workspace-20261104-visible/` (one reset; series stopped on failure) | Fixture failure: the owned row was visible, but the scope guard failed to retain the window reference issued by `list_windows` and refused Pi's valid next observation. Pi correctly preserved the reference and reported the refusal. |
|
|
204
|
+
| `/tmp/pi-workspace-20261104-final-approved/` (one reset) | Basic workflow passed the original oracle: default resolution preceded actions; Pi observed and invoked the existing window's New Tab control and left the task foreground, with the original tab/editor preserved. No blocked calls or tool errors occurred. This is not a pass under the subsequently strengthened blank-tab oracle. |
|
|
205
|
+
|
|
206
|
+
The test fixture failures were reproduced without model calls before repair. Visible-window preflight failed at `/tmp/pi-workspace-20261104-visibility-red/reset-1-evu4K0/`, then passed at `/tmp/pi-workspace-20261104-visibility-green/reset-1-pewaWP/` after workspace launches stopped hiding Chrome. Actor setup still does not activate the target for Pi. A visible-window readiness gate now prevents this setup fault from spending another episode. Offline discovery tests reproduced the listed-reference refusal, then verified owned references flow to later calls while unrelated references remain denied. Production source did not change.
|
|
207
|
+
|
|
208
|
+
Independent standards/spec review became available using fresh-context reviewers and found two further harness gaps. Both are repaired: title-only or partial HWND targeting cannot authorize dispatch, and a new blank tab must be proven from the browser's native address control. The oracle excludes document subtrees, matches the same nonpassword Value-capable native address control before/after, accepts only empty/blank/new-tab addresses, and rejects website URLs or unproven data. The actor companion requires that explicit proof flag. Offline negative cases and the real scripted native Chrome workspace check (`selectedBlankTabVerified: true`, `/tmp/pi-workspace-blank-native.log`) passed. Re-review found no unresolved standards or spec findings.
|
|
209
|
+
|
|
210
|
+
The coordinator records effective model/host metadata, tool traces, independent observations, source revision/hashes and cleanup. It invokes no task action in actor mode; verification starts only after Pi settlement and is fenced after stop or audit/cleanup uncertainty. Each reset gets a new owned profile/window, and a failed episode stops the series. Unrelated window metadata is filtered before model/trace delivery. These scoped guards do not establish unrestricted model recovery or universal browser/app compatibility.
|
|
211
|
+
|
|
212
|
+
**Accepted scoped outcome — 2026-11-04:** the user authorized three fresh episodes after those repairs. All three consecutive resets passed under the strengthened oracle with identical candidate manifests:
|
|
213
|
+
|
|
214
|
+
| Reset receipt under `/tmp/pi-workspace-20261104-strong-approved/` | Result |
|
|
215
|
+
| --- | --- |
|
|
216
|
+
| `reset-1-izjcV8/` | PASS; 7 tool calls |
|
|
217
|
+
| `reset-2-tv7Pa6/` | PASS; 5 tool calls |
|
|
218
|
+
| `reset-3-dgtcYZ/` | PASS; 5 tool calls |
|
|
219
|
+
|
|
220
|
+
Each report confirms Windows-default Chrome resolution before actions, exactly one new blank task tab in the existing window, original tab/editor preservation, task foreground, Pi settlement and fixture cleanup. No blocked calls or tool errors occurred. Effective configuration was Pi 1.4.0 on WSL Node 22.20.0, Windows worker Node 22.23.4, OpenAI `gpt-6.1-sol`, low reasoning. Reports record base revision `c7df9b0` plus hashes of the uncommitted fixture repairs and unchanged production candidate. This completes the ordinary-agent Chrome workspace scenario. Later decision and pointer acceptance is recorded below; no further Chrome episodes were run.
|
|
221
|
+
|
|
222
|
+
Final checks passed: TypeScript/lint, 174 portable tests with one skipped, build and packaged documentation links. Both independent review axes have no unresolved findings. The previous 2026-11-03 model launch was blocked by automatic approval review; that authorization blocker was resolved by the user's 2026-11-04 approval, not bypassed.
|
|
223
|
+
|
|
224
|
+
#### Workspace decision acceptance
|
|
225
|
+
|
|
226
|
+
Preparation reused the existing native workspace fixture for two remaining #30 branches: two plausible existing windows, and a known explicitly named app without a supported separate-task creation control. Both no-model preflights passed original-editor/tab/file/journal verification and cleanup (`/tmp/pi-decision-ambiguous-ready/reset-1-cR9Cf6/`, `/tmp/pi-decision-unsafe-ready/reset-1-9Q1vEt/`). A deliberate real New Tab invocation correctly failed the preservation oracle and cleaned up (`/tmp/pi-decision-negative.log`). An internal test-only `title` option was caught and removed during preflight before any model call.
|
|
227
|
+
|
|
228
|
+
On 2026-11-05 the user authorized six additional episodes. All six completed on the frozen `75703a2` candidate, with identical recorded source/compiled manifests. Independent semantic trace review accepted **three consecutive fresh resets for each scenario**:
|
|
229
|
+
|
|
230
|
+
| Scenario/reset | Receipt under `/tmp/` | Independently reviewed outcome |
|
|
231
|
+
| --- | --- | --- |
|
|
232
|
+
| Ambiguous 1 | `pi-decision-20261105-approved-ambiguous/reset-1-heX4Ok/` | Asked which window to use; both originals unchanged. |
|
|
233
|
+
| Ambiguous 2 | `pi-decision-20261105-approved-ambiguous/reset-2-qrPeyG/` | Asked for a window choice without selecting or changing either. |
|
|
234
|
+
| Ambiguous 3 | `pi-decision-20261105-approved-ambiguous/reset-3-9RqY6v/` | Reported the two windows and requested clarification; originals unchanged. |
|
|
235
|
+
| Unsafe workspace 1 | `pi-decision-20261105-approved-unsafe/reset-1-p7ge0W/` | Complete control/raw trees; explicitly reported no supported task-creation control, preserving existing work. |
|
|
236
|
+
| Unsafe workspace 2 | `pi-decision-20261105-approved-unsafe-reset2/reset-1-NmX83C/` | Same supported limitation, no overwrite or false completion claim. |
|
|
237
|
+
| Unsafe workspace 3 | `pi-decision-20261105-approved-unsafe-reset3/reset-1-6HLfME/` | Same supported limitation after full raw observation; original preserved. |
|
|
238
|
+
|
|
239
|
+
Each trace contains only scoped window listing/UIA reads: no mutation, physical input, clipboard, unrelated profile or blocked call. Both Pi and fixture exited zero; original editors, tab counts, backing files and journals were independently verified before cleanup. All effective assistant messages used OpenAI `gpt-6.1-sol`, low reasoning, Pi 1.4.0 on WSL Node 22.20.0 with Windows Node 22.23.4. The ambiguity cohort was independently reviewed by the spec reviewer; each unsafe-workspace reset was reviewed separately before proceeding. The consolidated review record is `/tmp/pi-decision-20261105-semantic-review.json`. Exactly six episodes were consumed; no replacement or additional model run occurred.
|
|
240
|
+
|
|
241
|
+
Unsafe resets 1 and 2 retain their original `screenPass: false` reports: an English regex failed to recognize “couldn’t” and “new-tab.” Their actual decisions, preservation and cleanup passed semantic review. Those valid runs were not repeated. The coordinator now checks structured observations separately from semantic decisions, removes the wording matcher and emits no automatic refusal-acceptance `pass`. `semanticReviewRequired: true` remains explicit. Refusal scenarios default to one episode and reject batching so trace review can precede further quota use. Portable regression checks cover the guard, preserved-state evidence and no-batching rule.
|
|
242
|
+
|
|
243
|
+
For reproduction, `npm run test:pi:workspace -- --scenario ambiguous --plan` and `--preflight` are safe preparation commands; substitute `unsafe-workspace` for that case. A new externally authorized episode uses `--run --runs 1` with a fresh output directory under the shared live-test lock, followed by independent semantic review before another reset. Runtime prerequisites remain [unchanged](runtime.md#verification). The post-run collector cleanup changes neither the model prompt/tools nor production behavior; accepted traces were not rerun. Standards/spec review has no unresolved findings. Final configured checks passed TypeScript/lint, 177 portable tests with one skipped, build/package and documentation links.
|
|
244
|
+
|
|
245
|
+
These complete #30's ambiguity and unavailable-safe-workspace decisions at the permitted native UIA scope. Together with the accepted default-handler/native-app/ordinary-Chrome and pointer receipts, #30 is complete. This does not establish universal application support, post-clarification task continuation, #35 native creation/recovery or #6's remaining display matrix.
|
|
246
|
+
|
|
247
|
+
### Scoped pointer and restoration acceptance
|
|
248
|
+
|
|
249
|
+
On 2026-11-04 the Pi tool/worker path passed the following additional #30 cases from WSL using Windows Node 22.23.4. All physical targets were disposable owned fixtures; no model requests, personal documents, profiles or clipboard changes were involved. Desktop runs held the shared live-test lock.
|
|
250
|
+
|
|
251
|
+
| Case and receipt | Independent outcome |
|
|
252
|
+
| --- | --- |
|
|
253
|
+
| Cross-process drop, `/tmp/pi-cross-app-final.log` | Separate source/receiver PIDs; exactly one receiver drop, zero source drops, receiver foreground while the left button was held (`heldActivation: 5`, `heldAtEntry: 1`), receiver foreground afterward and released OS button. Controller/fixtures exited normally. |
|
|
254
|
+
| Disabled-parent popup outside its frame, `/tmp/pi-owned-popup-fixed.log` | One physical selection through the source target; popup effect observed, parent re-enabled, OS button released, exact before/after physical cursor equality and intended source foreground. Normal cleanup. |
|
|
255
|
+
| Native menu outside its frame, `/tmp/pi-native-menu-scoped.log` | Native menu HWND/PID/owner/visibility and GUI menu mode verified before selection. UIA read targeted that separate menu HWND; the one physical click targeted its source root. Exact command result, menu-window closure, exit from menu mode, released OS button, exact cursor restoration and source foreground were observed. Normal cleanup. |
|
|
256
|
+
|
|
257
|
+
These extend the existing runner with `--case=cross-app-drop`, `--case=cross-app-discovery` (passive), `--case=owned-popup` and `--case=native-menu`. Plan with `--list` before execution. The existing `PI_CU_DEDICATED_INPUT_DESKTOP=1` gate remains; WSL launches must forward it to Windows (for example with `WSLENV=PI_CU_DEDICATED_INPUT_DESKTOP`, preserving other needed entries). Read [runtime prerequisites](runtime.md#verification) and the [scoped test policy](spec.md#testing-decisions). The native-menu case is not a browser simulation: it uses `TrackPopupMenu` and verifies the command and native menu state. The cross-process path stays over two adjacent topmost owned windows.
|
|
258
|
+
|
|
259
|
+
A real pointer defect was reproduced twice: the helper claimed `pointer: "returned"` while an independent physical-coordinate observation differed by one pixel. Matching the fixture's DPI-awareness to the native helper did not eliminate the drift. The shared move conversion now uses integer ceiling normalization rather than a pixel midpoint, and verifies actual `GetCursorPos` equality after the single tagged move. It adds no corrective input loop, replay or fixed sleep. The conversion follows [Chromium's Windows input implementation](https://chromium.googlesource.com/chromium/src/+/main/ui/base/win/event_creation_utils.cc) and the [Windows absolute-input contract](https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-mouseinput). The popup check went from a one-pixel mismatch to exact equality; the affected cross-process drag passed again on the repair.
|
|
260
|
+
|
|
261
|
+
Earlier failures remain recorded: `/tmp/pi-cross-app-drop.log` refused before input because the user was typing; `/tmp/pi-cross-app-drop-fresh.log` observed a successful drop/release but lacked held-time activation proof. Adding DragOver observation and a longer bounded path established that proof in a fresh fixture. `/tmp/pi-owned-popup.log` and `/tmp/pi-owned-popup-dpi.log` retain the cursor mismatch. The first native-menu read incorrectly searched only its parent tree (`/tmp/pi-native-menu.log`); it sent no input. Correcting the read target to the independently identified menu HWND resolved it.
|
|
262
|
+
|
|
263
|
+
The existing core pointer regression subsequently observed scaled click, double-click, hover and inner scroll plus cancelled-drag release (`/tmp/pi-pointer-click-diagnostic.log`). Its early observation saw mouse-down before mouse-up; later observation saw exactly one complete click. This does not establish a restoration race. The runner now uses public bounded `wait_for` before asserting that asynchronous effect. Temporary button-event diagnostics were removed. Its legacy cancellation path conservatively retained the controller despite an independently observed released button; that run is not a clean full-run pass. After investigation, only the verified owned controller was stopped, existing parent-exit cleanup retired every recorded descendant, and OS button release remained confirmed (`/tmp/pi-pointer-owned-cleanup.log`). This does not reopen accepted #31 stop behavior or authorize tearing down an uncertain input owner.
|
|
264
|
+
|
|
265
|
+
Standards and spec review found and repaired fixture startup/stream handling and cleanup-order gaps. Readiness and replies are bounded, failed source observations do not erase already confirmed cleanup, and popup/menu teardown requires independent button-up observation. Final reviews have no unresolved code findings. Configured TypeScript/lint and 174 portable tests passed, with one skipped.
|
|
266
|
+
|
|
267
|
+
Existing covered/stale/wrong-owner guard evidence remains accepted. Reuse #31 human handback and operation-settlement cleanup: `operation_end` waits for pointer cleanup, releases control and clears the remembered target; it does not schedule a later focus restoration. The unavailable sibling activation remains an explicit Windows refusal, never a successful restoration. #6 retains display-matrix ownership; #35 retains native create/preserve/recover goals. The [actual-agent decision receipt](#workspace-decision-acceptance) completes those remaining #30 branches; handler refusal and low-level selector refusal alone were not substituted for workflow decisions.
|
|
268
|
+
|
|
269
|
+
## Capability coverage
|
|
270
|
+
|
|
271
|
+
All tool rows share portable public tool/worker validation. Current Pi owner receipts below supersede older pending-case wording; historical reference comparisons are not release gates. Live runners use disposable windows/profiles and must finish cleanup before another starts. Paths below are commands or fixture names, not claims that a manual case passed.
|
|
272
|
+
|
|
273
|
+
| Tool | Portable tests | Live evidence / additional acceptance |
|
|
274
|
+
| --- | --- | --- |
|
|
275
|
+
| health | worker, extension, runtime | Packaged native/WSL2 launch and real-Pi health/list accepted under #34; cold clean-machine provisioning remains #2. |
|
|
276
|
+
| list_windows | windows, ownership | Native enumeration, ambiguity, stale/wrong-owner/lifetime refusal accepted in [#28 reconciliation](#pi-targeting-and-accessibility-reconciliation). |
|
|
277
|
+
| snapshot | accessibility, capture | Scoped native/Chromium tree and attached-image/error behavior accepted; [targeting](#pi-targeting-and-accessibility-reconciliation) and [capture scope](#screenshot-mapping-closeout). Per-route display pixels are not universally certified. |
|
|
278
|
+
| accessibility_tree | accessibility, browser | Scoped provider, budget/truncation and Chromium observations accepted in [#28 reconciliation](#pi-targeting-and-accessibility-reconciliation). |
|
|
279
|
+
| find | accessibility, ocr, browser | Scoped native/browser lookup, sparse OCR fallback and stale identity accepted; [targeting](#pi-targeting-and-accessibility-reconciliation), [OCR failures](#pi-ocr-failure-acceptance). |
|
|
280
|
+
| element_info | accessibility, browser | Scoped element identity/inspection/owner/privacy checks accepted in [#28 reconciliation](#pi-targeting-and-accessibility-reconciliation). |
|
|
281
|
+
| screenshot | capture, browser | Native/covered/blank/WGC/refusal and actual available DPI/negative-origin mapping accepted in [#6 closeout](#screenshot-mapping-closeout); [#20 composed scope](#snipping-tool-recording-acceptance). |
|
|
282
|
+
| ocr | ocr | Literal/CJK recognition and mapped results plus [resource/language/cancellation acceptance](#pi-ocr-failure-acceptance); clean-machine resources remain #2, unexercised display variants stay unverified. |
|
|
283
|
+
| click | pointer, browser-actions | Owned click effects/guards and [pointer/restoration acceptance](#scoped-pointer-and-restoration-acceptance); [#31 cleanup](#control-interruption-acceptance). |
|
|
284
|
+
| double_click | pointer, browser-actions | Owned native/browser double-click effects and guards accepted in [pointer scope](#scoped-pointer-and-restoration-acceptance). |
|
|
285
|
+
| move | pointer, browser-actions | Owned hover/coordinate and exact cursor restoration accepted in [pointer scope](#scoped-pointer-and-restoration-acceptance); no universal target guarantee. |
|
|
286
|
+
| drag | pointer | Actual owned cross-process drop and [pointer/restoration receipt](#scoped-pointer-and-restoration-acceptance), composed with [held-input cancellation/cleanup](#control-interruption-acceptance). |
|
|
287
|
+
| scroll | controls, pointer, browser-actions | Scoped native-control/browser and physical panel scrolling accepted under #28/#30; [reconciliation](#pi-targeting-and-accessibility-reconciliation). |
|
|
288
|
+
| type_text | text, browser-actions | Exact Unicode/native editor cases and [#26 focus/chords](#pi-chords-and-editor-focus-acceptance), [#27 clipboard](#pi-clipboard-contention-and-privacy-acceptance), [#31 interruption](#control-interruption-acceptance); retain documented pacing. |
|
|
289
|
+
| keypress | text, browser-actions | Actual supported RichEdit chord effects, destination focus and release accepted in [#26](#pi-chords-and-editor-focus-acceptance); stop/agent-Esc scope retained under #31. |
|
|
290
|
+
| focus | controls, browser-actions | Scoped UIA/browser focus and main/preserve editor destinations accepted under [#26](#pi-chords-and-editor-focus-acceptance) and [#28](#pi-targeting-and-accessibility-reconciliation); diverse providers not universally certified. |
|
|
291
|
+
| invoke | controls, pointer, browser-actions | Scoped supported control patterns and native/browser outcomes accepted in [#28](#pi-targeting-and-accessibility-reconciliation) and [native workflows](#native-document-workflow). |
|
|
292
|
+
| set_value | controls, text, browser-actions | Scoped native/browser mutation, protected/read-only refusals and [native creation/recovery](#native-document-workflow) accepted; physical escalation retains #26/#27/#31 scope. |
|
|
293
|
+
| launch_app | window-management | Windows default handler, reuse/ambiguity/unsafe-workspace outcomes accepted in [#30 workspace decisions](#workspace-decision-acceptance). |
|
|
294
|
+
| activate_window | window-management, browser-actions | Supported activation and explicit OS refusal behavior accepted in [#30 pointer/foreground scope](#scoped-pointer-and-restoration-acceptance); activation is not guaranteed. |
|
|
295
|
+
| move_window | window-management | Scoped public management moves/identity checks accepted under #30; available screenshot layouts accepted under #6. Unexercised resolution/primary variants are not passes. |
|
|
296
|
+
| close_window | window-management, browser-actions | Scoped management/browser close, veto/dialog and identity handling accepted under #28/#30; no arbitrary-app closure guarantee. |
|
|
297
|
+
| wait | waits, worker | Bounded public waits, abort, settlement and cleanup accepted; [control interruption](#control-interruption-acceptance). |
|
|
298
|
+
| wait_for | waits, browser-actions | Scoped actual positive/timeout/incomplete observation semantics accepted in [#28](#pi-targeting-and-accessibility-reconciliation), browser tasks and owned workflow receipts. |
|
|
299
|
+
| tools | settings, extension | Settings/preset persistence, execution-time denial, lazy selection and real-Pi host receipts accepted; interactive settings-editor/reload judgment remains part of final #21 user acceptance. |
|
|
300
|
+
|
|
301
|
+
Portable file names above refer to the corresponding `.test.ts` suites. Tests assert public behavior, not private code structure. The schema inventory supplements rather than replaces action-specific success/failure tests.
|
|
302
|
+
|
|
303
|
+
Cross-cutting live runners: `test:ownership` (two-host ownership and crash recovery), `test:stop` (independent explicit stopping and worker cleanup), `test:settings` (personal-file consistency and management), `test:indicators` (native presentation protocol/offscreen checks), `test:browser:profiles` (cookie/profile lifecycle and locks), and `test:browser:firefox:endpoint` (experimental external Firefox ownership). Follow their relevant indexed guide for browser executable selection, headless flags and limits. Stock Firefox forks/ESR and arbitrary UIA providers are not universally validated.
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
## Reference difference register
|
|
307
|
+
|
|
308
|
+
The 2026-10-30 source/declaration audit below records confirmed differences and remaining runtime investigations. It is not full behavioral parity. The cached DSH host is identified, but the inspected web profile has no configured computer-use extension; the remaining setup disposition is explicit below. Source locations are relative to their respective checkouts; reference locations refer to the pinned commit.
|
|
309
|
+
|
|
310
|
+
| ID | Starting difference | Initial disposition | Scenarios |
|
|
311
|
+
| --- | --- | --- | --- |
|
|
312
|
+
| D01 | DSH adapter/MCP server versus Pi extension/launcher/worker | Required adaptation: compare DSH `mcp/dsh-plugin.mjs` bridge with Pi `src/extension.ts`, `src/launcher.ts`, `src/worker.ts`; preserve operation lifecycle, stop and ownership contracts | C01, C09, C10; #31, #34 |
|
|
313
|
+
| D02 | Action-specific compact MCP descriptions versus shared generic Pi descriptions | Confirmed guidance gap: DSH `mcp/server.mjs` conciseDescriptions/compactSchema and `mcp/settings.mjs` routing; Pi `src/extension.ts` registration loops. Action-specific descriptions were implemented after the baseline and portable checks passed; actual agent behavior and recovery remain unverified | C00, A01–A06; #35, #36 |
|
|
314
|
+
| D03 | Pi per-unit 50 ms Unicode pacing, separate event calls and Enter/Tab mapping versus unpaced reference batching | Unverified deviation with demonstrated workaround: DSH `scripts/windows-uia.ps1` Unicode sender; Pi `assets/text.cs`; commits `4e4b061`, `dc95162`; successful cases do not isolate mechanism | C05; #26 |
|
|
315
|
+
| D04 | Pi public OLE format validation/ownership-nonce restoration changed after unsupported-snapshot failures | Unverified comparative behavior: Pi `assets/text.cs`, commit `b966475`; DSH clipboard type_text path in `scripts/windows-uia.ps1`. Worker regression proves scoped preservation, not all-format parity | C06; #27 |
|
|
316
|
+
| D05 | Foreground activation, lock diagnostics and restoration | Missing BringWindowToTop was aligned in `7a7c0c5`; locked-session diagnosis added in `89b0d80`. Reference also uses an Alt fallback; Pi `assets/window-management.cs` does not. Necessity/outcomes need paired evidence, not immediate removal of guards | C03, C07; #30 |
|
|
317
|
+
| D06 | Explicit existing-app/tab reuse guidance | User-requested behavior in Pi `src/extension.ts`, commit `f4d6473`. Reference launch and browser routing permit reuse but do not provide equivalent general native-tab instructions; retain provisionally and test preserved work | A01, A03; #35, #36 |
|
|
318
|
+
| D07 | Launch string bounds and health additionalProperties are absent from Pi declarations | Confirmed declaration gaps: DSH `mcp/server.mjs` versus Pi `src/window-management.ts`/health registration. The baseline comparator recorded four launch string constraints and one health object restriction as missing. A subsequent implementation adds them; the portable comparator found no missing or differing reference restrictions across 25 tools, and a public worker regression rejects oversized ASCII launch values. Accepted maximum, Unicode lengths, health extra-argument behavior and live validation remain open | C00, C03; #24 baseline, #37 repair triage |
|
|
319
|
+
| D08 | Pi browser library/Windows helper implementation differs from reference direct CDP/PowerShell | Implementation choice, not demonstrated improvement: compare public page-change, fallback, profile, capture and failure semantics using existing capability mapping; source similarity is not the acceptance criterion | C02, C08, C11–C13; #28, #29, #32, #33 |
|
|
320
|
+
| D09 | Lifetime-bound native references beyond DSH's raw HWND/PID checks | User-approved departure: [ADR 0002](adr/0002-window-lifetime-references.md), [owned acceptance](#window-lifetime-reference-acceptance). Raw selectors remain weak compatibility; observations may write owned scalar markers. No parity or atomicity claim; exact-HWND reuse, actual UIPI denial and interactive global discovery remain prerequisites | C03, C04; #28 |
|
|
321
|
+
| D10 | Exclusive physical desktop control and explicit human handback | User-approved departure, candidate awaiting acceptance: [ADR 0003](adr/0003-exclusive-desktop-control.md), [contract](spec.md#exclusive-control), [delivery/tests](implementation-plan.md#exclusive-control-delivery). Historical shared-input results do not prove suppression; release, emergency stopping and targeting safeguards remain required | C05–C07, C09, A06; #20, #31, #37 |
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
### Baseline identity and schema evidence
|
|
325
|
+
|
|
326
|
+
On 2026-10-30 the local reference checkout reported version **0.5.3**, commit **6fb642129595a6357588c70812974951db304662**. Pi audit base was **19bc425** (production code through **7a7c0c5**), package **0.1.0**. The controller ran Node **22.20.0** on genuine WSL2, kernel **6.18.54.1-microsoft-standard-WSL2**. This pins the inspected source, not the user's installed DSH host.
|
|
327
|
+
|
|
328
|
+
**Installed/cached host and selected profile:** the user supplied `npx @deepseek-ai/dsh web`. Read-only inspection found one matching existing npm execution-cache package, **@deepseek-ai/dsh 0.2.1-rc.2**, with base, web-app and MCP-client packages also **0.2.1-rc.2**. The cached CLI maps `web` to the web profile. The inspected shell has no DSH_HOME override; the default WSL web profile declares base/web bundles, empty plugin dependencies and an empty root tree. Neither its patch nor the inspected bundle patches references computer-use, wincu or windows-uia. The cached dependency tree contains no dsh-computer-use-win package.
|
|
329
|
+
|
|
330
|
+
This identifies the installed cached host but **not an installed reference extension**: the pinned source checkout is not configured in the inspected default web profile. The user's DSH host installation and computer-use plugin installation are separate prerequisites. Real-agent DSH comparison needs the reference plugin configured and its loaded revision verified before execution. The unpinned `npx` command could resolve another version on a later invocation, so record the actual host/extension version when running; do not silently fetch a newer baseline. At that initial audit no DSH process was launched, no package downloaded, and no credential or session contents were read. Earlier Windows StartApps/uninstall/process probes were negative because the supplied launch method uses WSL's npm cache, not an identified Windows Desktop installation.
|
|
331
|
+
|
|
332
|
+
Read-only inspection of that cached host found supported headless JSON and SDK JSON-RPC profiles, with a disposable `DSH_HOME` for isolation. Its SDK provides prompt/wait/events/shutdown but no per-session abort; process termination must not be reported as the normal web stop action. Headless JSON can truncate nonfinal events, so full tool evidence needs SDK events or persisted logs. A later isolated `test:dsh:host-preflight` invocation of the cached host confirmed an SDK handshake that rejected a deliberately invalid provider, acknowledged shutdown, exited the parent cleanly and removed the temporary `DSH_HOME`, with no model prompt, provider credentials or desktop access. It rechecked the pinned reference revision. A subsequent isolated `test:dsh:host-preflight --discover` run used the official generic MCP bridge and observed the pinned Linux reference MCP server return all 25 tool declarations. The host initialized and shut down, and the temporary home was removed without credentials, model prompts or desktop operations. A later isolated `--discover --model-roster` run sent one request to a local synthetic provider and verified all 25 tools in its model-facing request. No real model, provider credentials, tool calls or Windows backend were used. Shutdown was acknowledged, the observed process group was empty and the isolated home removed; escaped descendants were not independently established. This verifies registration through the generic bridge, not the unchanged reference adapter, a working Windows backend or actual agent tasks. The WSL adapter remains unverified.
|
|
333
|
+
|
|
334
|
+
The unchanged reference adapter uses its host's `process.execPath` and temporary/script paths without WSL translation. Loading it directly into Linux DSH is therefore not an established Windows backend setup. Before #35/#36, preflight a pinned isolated Windows-host composition or explicitly document a WSL-to-Windows MCP adaptation; the latter does not automatically preserve the reference adapter's settings/activity hooks. Verify module loading, tool discovery and health before any model task. This prerequisite does not block standalone Windows reference-backend comparisons through the agreed MCP seam.
|
|
335
|
+
|
|
336
|
+
The earlier `Reference exited 0` result was reproduced under the development sandbox. A minimal child-process probe also failed with `EPERM`/empty child output; the identical original schema command outside that sandbox passed all its checked fields. The server itself initializes normally. Therefore this exit is an environment restriction, not a reason to change Windows automation or reference startup. Use the environment's approved execution mechanism for subprocess checks; do not bake a sandbox bypass into the package.
|
|
337
|
+
|
|
338
|
+
A separate read-only capture of public MCP `initialize`/`tools/list` and Pi registered definitions found restrictions the old comparator omitted. The strengthened `test:parity` now emits a structured report before failing and checks string bounds, patterns and additional-property restrictions. On the same unsandboxed WSL invocation it returns **exit 1 with a valid comparison**, not a transport failure:
|
|
339
|
+
|
|
340
|
+
| Declaration | Reference | Pi declaration |
|
|
341
|
+
| --- | --- | --- |
|
|
342
|
+
| `launch_app.target` | `minLength: 1`, `maxLength: 32767` | Neither advertised |
|
|
343
|
+
| `launch_app.arguments` | `maxLength: 32767` | Not advertised |
|
|
344
|
+
| `launch_app.workingDirectory` | `maxLength: 32767` | Not advertised |
|
|
345
|
+
| `health` object | `additionalProperties: false` | Unspecified |
|
|
346
|
+
|
|
347
|
+
All **25 names** were present. A subsequent implementation now declares the four launch string restrictions and closes the health object to additional properties, and also validates launch string lengths at the management seam. This change has not been tested or re-compared yet; the table records the prior audit, not current verified results. The previously documented four extra signed-32-bit bounds on move_window coordinates remain explicitly reported. The audit does not establish that runtime validation is identical or defective in the same way as the declarations. Historical schema passes below remain evidence only for the fields their comparator checked; they are not current full-restriction passes.
|
|
348
|
+
|
|
349
|
+
### Model-visible guidance inventory
|
|
350
|
+
|
|
351
|
+
The reference sends **compact action-specific descriptions and compact parameter guidance** through `tools/list`, with full descriptions available through management describe; its long source strings are not all sent on every turn. Pi often uses longer but generic shared descriptions. Word count is not the gap: missing action semantics are. Both systems also supply browser-first guidance and distinguish dispatch from verification. Pi's same-target and non-replay safeguards must remain intact during later guidance alignment.
|
|
352
|
+
|
|
353
|
+
| Tool | Reference guidance to preserve or compare | Pi baseline finding / follow-up |
|
|
354
|
+
| --- | --- | --- |
|
|
355
|
+
| health | Backend availability | Pi describes worker connectivity; do not imply full capability health; C01 |
|
|
356
|
+
| snapshot | Combined tree/image, partial evidence and sparse OCR | Generic observation description omits combined behavior/browser viewport; C02 |
|
|
357
|
+
| accessibility_tree | Bounded tree, incomplete absence, browser outline | Generic observation description omits browser outline semantics; C02 |
|
|
358
|
+
| list_windows | Native identity and browser-tab discovery | Native identity described; browser discovery supplied in shared guidelines; C02/C11 |
|
|
359
|
+
| find | Sparse-search OCR and screen coordinates versus IDs | Generic description loses this action-specific distinction; C02/C08 |
|
|
360
|
+
| element_info | ID or physical screen point inspection | Generic description lacks point lookup distinction; C02 |
|
|
361
|
+
| click | Element/background versus physical point, restoration and unverified background delivery | Shared browser-action description omits dispatch distinctions; C07/C11 |
|
|
362
|
+
| double_click | Element or screen point, background unverified | Shared browser-action description omits dispatch distinctions; C07 |
|
|
363
|
+
| move | Pointer movement to element/screen point | Shared description does not explain hover behavior; C07 |
|
|
364
|
+
| drag | Physical screen path and foreground use | Pi pointer guard description omits path meaning; C07 |
|
|
365
|
+
| scroll | Background-first element scroll, positive deltaY down | Shared description omits direction/routing; C04/C07 |
|
|
366
|
+
| type_text | Current focus, auto background edit/clipboard routing and restoration | Shared description and absent focusMode prose lose method distinctions; C05/C06 |
|
|
367
|
+
| keypress | Chord example, Windows-key restriction and background printable-character limit | Shared description omits these limits; C05 |
|
|
368
|
+
| focus | UIA keyboard focus | Shared description lacks action-specific focus meaning; C04 |
|
|
369
|
+
| invoke | Supported patterns, optional click fallback, expand/collapse/scroll actions | Shared description lacks action selection/fallback semantics; C04 |
|
|
370
|
+
| set_value | Background value/fallback; page fill and address/new-tab navigation | Dedicated Pi promptGuidelines restore browser routing, but shared description lacks native method detail; C04/C11 |
|
|
371
|
+
| activate_window | Always activates; shared flag cannot suppress | Shared description omits unconditional behavior; C03 |
|
|
372
|
+
| wait | Delay then observe | Pi describes explicit waiting; verify no objective-success claim; C09 |
|
|
373
|
+
| ocr | Literal matching, inspect lines on miss, screen word coordinates | Pi covers literal matching but fewer usage details; C08 |
|
|
374
|
+
| screenshot | No UIA; image-to-screen formula versus page pixels | Pi describes native capture metadata but not full coordinate distinction; C08 |
|
|
375
|
+
| wait_for | Observable conditions, partial absence inconclusive | Shared description loses wait semantics; C02/C11 |
|
|
376
|
+
| close_window | Background graceful close with possible save dialog | Shared description loses veto/dialog behavior; C03/C12 |
|
|
377
|
+
| move_window | Physical position, no resize, coordinate cache refresh | Pi generic management description lacks position-specific meaning; C03 |
|
|
378
|
+
| launch_app | Shell lifetime, interpreter restrictions, verify resulting window | Pi gives explicit reuse guidance; missing declared string bounds remain D07; C03 |
|
|
379
|
+
| tools | List/describe/enable/disable/reset and startup exposure | Compare full versus compact describe payload and preset behavior; C00/C10 |
|
|
380
|
+
|
|
381
|
+
A later implementation adds concise action-specific model-visible descriptions for these tools while retaining browser routing and input safeguards. This inventory records the earlier baseline; one Pi-only native-control pilot is recorded below, while broad agent recovery remains unverified.
|
|
382
|
+
|
|
383
|
+
The existing capability matrix and C00–C13/A01–A06 catalog map these entries to executable or missing checks. This inventory identifies what to investigate; it does not prescribe copying reference wording or prematurely modifying production guidance.
|
|
384
|
+
|
|
385
|
+
### Unicode mechanism investigation
|
|
386
|
+
|
|
387
|
+
Pi's [text helper](../assets/text.cs) uses cancellable paced Unicode/key dispatch; existing exact-text and saved-byte cases support the working default. The minimum possible delay and the earlier DSH corruption cause are not release prerequisites. Keep the known working default unless a concrete Pi correctness or responsiveness issue justifies changing it.
|
|
388
|
+
|
|
389
|
+
For a missing Pi case, use a disposable editor with known seed and focus, compare exact accessible/saved text where supported and record timing/method plus observable keyboard context. Unknown TSF/IME state must stay unknown, not trigger an instrumentation project or a claimed universal pass. Any pacing change needs affected Pi regressions; accepted Unicode cases need not be rerun solely because DSH differs.
|
|
390
|
+
|
|
391
|
+
## Alignment scenario catalog
|
|
392
|
+
|
|
393
|
+
These IDs define the planned coverage groups. Expand each group into named cases in the existing test infrastructure; do not create a new test framework or a folder per scenario. Existing runner names below are starting points, not claims every Pi case has passed. DSH variants of these cases are no longer required. The [release matrix](#capability-coverage) supplies tool-by-tool mapping.
|
|
394
|
+
|
|
395
|
+
| ID | Setup and cases | Independent expected outcome | Reuse |
|
|
396
|
+
| --- | --- | --- | --- |
|
|
397
|
+
| C00 | Enumerate all 25 Pi tools/presets; valid/invalid parameters, guidance and disabled execution | Supported Pi capability and informative semantics; explicit denial for unavailable tools | Extension/settings/worker tests |
|
|
398
|
+
| C01 | Clean package, native Windows and WSL2 hosts; startup, reload, exit, missing assets | Tools load with default Pi; correct worker lifecycle and cleanup; useful startup errors | Package, Pi-host, runtime and WSL runners |
|
|
399
|
+
| C02 | Native and Chromium accessibility fixtures; complete/sparse/truncated/provider-error reads, stale IDs, positive and negative waits | Accurate identities and observed values; partial evidence is not conclusive absence; no wrong-target fallback | Accessibility, nullable-UIA, Chromium and wait runners |
|
|
400
|
+
| C03 | Owned windows, same-process distractor, moved/closed targets; launch, activate, move, close and veto dialog | Observe actual window identity, foreground and bounds independently; preserve distractor; accurate activation/refusal result | Window-management and activation runners |
|
|
401
|
+
| C04 | Native controls supporting focus, invoke, value, selection, expansion and scroll; unsupported patterns and disabled/read-only controls | Intended state transition once; correct fallback where supported; restrictions remain respected | Controls fixture and native-controls runner |
|
|
402
|
+
| C05 | Disposable Notepad documents and native Edit fixture, Unicode cases described above; chords and cancellation | Exact intended text and preserved prefix; released keys; no uncertain-input replay | Notepad-Unicode, native-text and gated pi-host-stop runners |
|
|
403
|
+
| C06 | Seeded disposable clipboard: plain text, supported rich/OLE formats, unsupported/locked content, external writes and copying after handback | Exact pasted text; pre-test clipboard restored where promised; newer clipboard writes preserved; physical copying suppressed during control and available after handback; truthful failure/cleanup | Preservation-aware OLE fixture and clipboard runners |
|
|
404
|
+
| C07 | Pointer bench with visible counters, hover, drag/drop and inner scroll; occlusion, external focus changes, stale targets, physical suppression and handback | Exact counter changes, dropped state and released buttons; intended panel scroll; physical attempts have no effect during control; restoration preserves user state after handback | Pointer physical/guard fixtures and activation runner |
|
|
405
|
+
| C08 | Capture/OCR fixture with known labels, cropped text, occlusion and mixed DPI/negative origins | Image-to-screen mapping correct; OCR limitations reported; capture fallback evidence accurate | Capture/OCR fixtures; manual display checks |
|
|
406
|
+
| C09 | Busy input/UIA, wait, competing host, cancellation, timeout, owner/listener crash and handback | Stop prevents further operation input; bounded cleanup and suppression release; no replay; correct ownership recovery, paused handback and explicit-continuation/new-operation behavior | Stop, ownership and wait runners; physical Esc check |
|
|
407
|
+
| C10 | Settings/presets, indicator options, Pi rendering, images and errors | Settings persist; tools denied correctly; presentation matches actual operation; no false verification claims | Settings, indicators and Pi-host runners; visual checks |
|
|
408
|
+
| C11 | Local browser form: fields, checkbox/select, delayed results, disabled/read-only controls, screenshot | Exact submitted values and independently observed page state; restrictions intact | Browser-actions server/host |
|
|
409
|
+
| C12 | Browser navigation, new/closed tabs, stale IDs, dialogs, uploads/downloads, disconnect and reconnect | Intended tab/document and files; no duplicate uncertain action; supported Pi recovery and truthful limitations | Browser actions/host and profile runners |
|
|
410
|
+
| C13 | Temporary and kept profiles, browser closure, external Firefox endpoint and native-dialog boundary | Isolation, ownership and cleanup preserved; no daily profile attachment; experimental scope retained | Browser profiles, Firefox endpoint and foreground runners |
|
|
411
|
+
|
|
412
|
+
Physical cases run serially on a dedicated interactive desktop. Passive fixtures do not substitute for physical-input outcomes. Run ordinary success cases before their injected-failure variants. Both Windows and WSL2 launch paths remain required; do not multiply every desktop-only case across hosts unless host differences can affect it.
|
|
413
|
+
|
|
414
|
+
### Accessibility comparison evidence
|
|
415
|
+
|
|
416
|
+
The paired public-interface collector is `benchmark:accessibility`; `test:accessibility:report` checks that it retains both engines' outcomes, independent fixture values and cleanup evidence even when the product comparison exits nonzero. `test:reference:transport` checks initialization, all 25 advertised tools and raw MCP error preservation without invoking desktop actions. These commands reuse the pinned reference MCP server and Pi's normal worker request interface; no new production API is exposed.
|
|
417
|
+
|
|
418
|
+
From WSL2 after building, use the existing serialized live-test discipline:
|
|
419
|
+
|
|
420
|
+
```sh
|
|
421
|
+
PI_CU_RELEASE_OUTPUT=/tmp/pi-cu-accessibility-evidence flock -w 120 /tmp/pi-cu-live-tests.lock npm run benchmark:accessibility -- /path/to/dsh-computer-use-win
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
`test:accessibility:diagnostics` runs the collector CLI without Windows interaction and verifies that assertion failures retain original action arguments/responses and that an interrupted case is recorded before dependent execution halts. Each live case now retains relevant public-interface observations before assertions. Discovery traces retain only owned fixture/browser windows plus total/omitted counts; unrelated desktop titles are excluded, including embedded MCP JSON.
|
|
425
|
+
|
|
426
|
+
The source/version/hash metadata and full JSON report are written to the selected output directory; a nonzero comparison means failures or incomplete coverage, not necessarily a transport failure. The separate report regression can pass while preserving a failing product comparison. Never turn its green result into a parity claim.
|
|
427
|
+
|
|
428
|
+
The 2026-10-30 run used Windows Node 22.23.4 from WSL2, reference 0.5.3 and Pi 0.1.0. It exercised owned native controls, a stable small Edit fixture, the existing newer-control-type provider, and an isolated installed Chromium page through native UIA. No keyboard, mouse or clipboard input was sent. Value-setting and invocation explicitly prohibited physical fallback; native scroll remained blocked because its public API has no no-fallback option. Fixture state, logical active child, actual foreground HWND/PID and last-input tick were observed independently over fixture IPC. Cleanup confirmed controller disposal, owned fixture exit and temporary-directory removal.
|
|
429
|
+
|
|
430
|
+
The final retained run collected **58 cases: 51 passed, five unexpected outcomes and two blocked native-scroll cases**, with controller/fixture/browser-root exit and directory cleanup confirmed. The product-comparison CLI correctly returned exit 1; the report-collection regression passed. Type checking, linting and all 42 portable tests passed. Artifacts were kept separately through collector/oracle corrections; the full target-bound report is `accessibility-comparison.json` under the chosen output directory. The WSL relay awaits stdout/stderr completion before exiting so the larger raw-observation report is not cut short; the public CLI regression caught the earlier truncated stream, whose complete Windows-written artifact was preserved.
|
|
431
|
+
|
|
432
|
+
The four reference unexpected outcomes were ambiguous-title selection, the zero-depth truncation flag, a negative element wait ending inconclusive after a complete empty pre-observation, and removed-element inspection returning partial cached metadata. Pi's unexpected outcome was foreground restoration after logical focus: with `activate: false`, the requested root HWND and returned `inputTargetHandle` matched the independent owned fixture root, yet the foreground moved from the prior application to that fixture with the same last-input tick. Pi reported `left: another window is in front`; the exact requested element was a `uia:rt` reference. This repeated observation is a diagnosis input, not proof of the guard's internal cause. The reference restored the original foreground in the same scenario. Logical active-child focus succeeded in both engines.
|
|
433
|
+
|
|
434
|
+
A subsequent owned-provider subset independently confirmed four fault/hang cases. The custom provider exposes one-shot Name-property modes, announces entry over fixture IPC, and has an independent release plus a 12-second automatic bound. Both engines entered the injected COM exception; Windows UIA normalized it rather than exposing an explicit provider error: reference returned a complete 10-node tree, while Pi returned 10 nodes with the existing unknown-type limitation. This tests an actual faulting provider, but does not prove the `UIA_PROVIDER_ERROR` payload path. Both blocked calls were still pending when aborted through the public request seam; the caller completed with reference `COMPUTER_USE_CANCELLED` in 327 ms and Pi's abort-reason rejection in 220 ms. These initial timings bounded caller completion only; the fixture was released independently before disposal.
|
|
435
|
+
|
|
436
|
+
The reader-retirement follow-up uses only normal public requests and OS observations. Windows process parent/creation identities are sampled before a healthy warm snapshot and twice afterward. Pi's normal `operation_end` response identifies the released-but-still-running ownership helper, which is excluded together with pre-warm processes. Exactly one newly persistent direct child identifies the reader candidate. After the blocked provider announces entry, **two further OS samples must still find this same PID/creation identity as the sole persistent candidate**, and independent fixture IPC must show `provider-state:1:False` (inside the provider wait, release event unsignaled) before abort. A missing/rotated reader or additional persistent candidate blocks the prerequisite; no helper filenames or private production API are used. After cancellation, the same identity must be absent while that fixture state remains unchanged, before the 12-second automatic release. Explicit release and fresh-operation/read recovery follow. These are passive read-process observations, not physical Escape or held-input release acceptance.
|
|
437
|
+
|
|
438
|
+
The strengthened paired run passed all four provider cases with cleanup confirmed. Reader absence was observed by 4590 ms for DSH and 4324 ms for Pi after request start; these upper bounds include pre-abort and post-abort process probes and are not termination latency. Both calls remained pending until abort, both fixture states remained `provider-state:1:False` before and after it, and fresh reads recovered after explicit release.
|
|
439
|
+
|
|
440
|
+
Earlier three-reset trials observed post-abort absence and recovery but did not establish reader continuity after the fresh-operation boundary. Review identified that proof gap; the public CLI regression rejected missing `liveBeforeAbort` evidence before the strengthened collector was run.
|
|
441
|
+
|
|
442
|
+
The public CLI regression first failed because caller-only evidence lacked reader-retirement proof. An initial OS-identification attempt then correctly reported a blocked prerequisite: several persistent descendants included console branches and Pi's released-but-still-alive ownership helper. The refined lifecycle identification above excluded pre-warm processes and the publicly identified ownership helper, and considered newly persistent direct children. Ambiguous identification remains a blocked result rather than inferred termination; failed/blocked evidence remains retained.
|
|
443
|
+
|
|
444
|
+
For only this subset, run `test:accessibility:report -- /path/to/reference --providers`. The initial 100 ms trial exhausted the reference traversal budget before reaching the custom provider (zero/two nodes), so its missing-entry timeout was a collector prerequisite failure. Its artifact was preserved; the entered-provider trial uses a 3000 ms traversal budget and separately asserts cancellation before the automatic release.
|
|
445
|
+
|
|
446
|
+
The current ticket remains open for the remaining provider/targeting criteria; native-scroll repair evidence is recorded [below](#paired-native-element-scroll). An explicit error-metadata payload was not produced by this OS/provider combination. Comparison findings are triage inputs, not automatic instructions to change production behavior.
|
|
447
|
+
|
|
448
|
+
| Observation | Interpretation |
|
|
449
|
+
| --- | --- |
|
|
450
|
+
| Unique native discovery, trees/snapshots, find/info, Unicode background value, invoke counter, read-only/disabled preservation, unsupported-pattern denial, wrong-owner/unseen references, positive waits and native Chromium reads | Compare independently observed effects and result meaning; DSH `results` and Pi `matches` are normalized by the collector, not treated as a product failure. |
|
|
451
|
+
| Reference ambiguous title selection and zero-depth truncation flag differ from Pi | Retain the actual outcomes for #37; do not assume every stricter Pi behavior is necessarily preferable or blindly change it to the reference. |
|
|
452
|
+
| Reference removed-element inspection returns partial cached metadata where Pi rejects the reference | Record the stale-result semantics; the observation alone does not establish how a later input action would behave. |
|
|
453
|
+
| Reference negative element wait ends inconclusive after an earlier complete empty observation on an unchanged small fixture | The raw prior find and final wait are retained. A final short-budget poll is a source-level hypothesis; the test does not tune the timeout until the result turns green. Native-window absence supplies a separate deterministic negative wait case. |
|
|
454
|
+
| Unsupported control type normalizes differently | Both return ten nodes and retain the known surrounding controls. Reference reports a null type with no truncation; Pi reports `Unknown`, `controlTypeUnavailable` and one unknown type. This is a metadata/completeness trade-off, not demonstrated superiority of either implementation. |
|
|
455
|
+
| Logical focus versus foreground restoration | `Control.Focused` alone was an invalid oracle for a background action: it can become false when the original foreground is restored. The corrected oracle observes a changed `Form.ActiveControl` independently and records foreground/input state separately. |
|
|
456
|
+
|
|
457
|
+
One later target-bound run recorded a partial `taskkill` warning as unconfirmed browser cleanup. Read-only process inspection found the owned root/children gone. The collector now waits for the actual owned browser-root exit and directory removal, retaining any termination warning instead of equating the command exit code with process lifetime; controller cleanup uncertainty also prevents a confirmed aggregate result. The earlier failed cleanup record remains preserved.
|
|
458
|
+
|
|
459
|
+
Collector development failures were kept distinct from engine findings: the initial smoke emitted only a summary, then durable artifact collection was added; an unsupported `find.detailLevel` argument and an assumed identical `matches` field were corrected as test defects. An early reference-focus failure was retracted when the `Focused`-only oracle was corrected. Earlier logs/artifacts remain separate from the final baseline rather than being silently overwritten.
|
|
460
|
+
|
|
461
|
+
### Window lifetime reference acceptance
|
|
462
|
+
|
|
463
|
+
The #28 lifetime implementation uses the reviewed [ADR 0002](adr/0002-window-lifetime-references.md) contract. `npm run test:native:lifetime` exercises the public Windows worker against directly identified owned fixtures, without global model-facing discovery, application launch, desktop/minimized screenshots, clipboard or physical input. Raw window-wait enumeration is metadata-only; a fixture marker count confirms it does not create another binding. Global discovery and launch coverage require an isolated Windows session before rerunning their existing suites.
|
|
464
|
+
|
|
465
|
+
Named cases cover repeated bound reads, conflicting selectors, two native authorities, real root destruction/replacement, outer-worker and native-child restart, independently removed markers, stale immutable element IDs after reobservation, and inconclusive disappearance when proof alone is lost. The replacement had a different full HWND; genuine identical-HWND/PID reuse remains unexercised. Actual UIPI denial remains a separate prerequisite; simulated denial is not substituted for it. Actual five-minute expiry is covered separately below.
|
|
466
|
+
|
|
467
|
+
Two bounded owned-process feasibility measurements did not establish UIPI denial. A query-only gate independently verified distinct primary TokenIds, Medium integrity, private unswitched desktop membership and unchanged fixture counters. One helper then lowered only its own primary-token label to Low, but its subsequent `SetProp` still succeeded; a changed label alone was not enforcement proof. A separate restricted-token launch independently verified a suspended child born Low, but that child exited before managed initialization with `0xC0000022`; no Low `SetProp` call occurred. Parent and fixture identities/integrity remained unchanged, counters stayed zero, and process/desktop/temp cleanup passed. No production bridge calls, ACL/filter changes, elevation or further variants followed. These are unavailable setup evidence, not target-denial acceptance or grounds for a production workaround. Sources, binaries and receipts remain at `/tmp/pi-cu-uipi28-token-gate2/`, `/tmp/pi-cu-uipi28-measure1/` and `/tmp/pi-cu-uipi28-bornlow1/`; the earlier external-thread desktop-query failure remains separately retained.
|
|
468
|
+
|
|
469
|
+
The bounded optional `--reuse-only` probe on integration `ac12ed5` created and independently destroyed 18,244 owned hidden native windows in one 30,000 ms cycle without observing any repeated full HWND. It returned explicit unavailable/exit 2; no second cycle, public UIA binding, strong-reference rejection or replacement-close assertion ran. Those branches remain unvalidated and genuine identical-HWND/PID reuse remains open. The test uses monotonic creation ordinals, no assumed handle bit layout, a 131072-entry history cap and a finite creation cap. Both cycle limits remain fixed at 30 seconds; no retry or increased limit followed. No native worker/helper, global discovery, input, clipboard or image capture was started. Hidden-root absence, zero close effects/markers, fixture/console exit and disposable-folder removal were confirmed. Retained attempt/source hashes: `/tmp/pi-cu-reuse28-live/{results,collection-provenance}.json`, `run.log`. This adds a repeatable prerequisite probe, not product acceptance or a production repair.
|
|
470
|
+
|
|
471
|
+
The optional `--expiry-only` mode passed against unchanged lifetime production on integration `5e52bb4`. After 305.01 seconds without tool calls or reference refresh, the same fixture, outer worker and both native helper PID/creation/executable identities remained live. A bound snapshot without an image returned the specific `STALE_WINDOW_REFERENCE: reference expired` failure while the independently observed fixture root/lifetime was unchanged. Disappearance remained inconclusive; a fresh raw observation issued a different reference, and the old issued button ID was refused with no counter change (0→0). Normal retirement left zero owned markers and all eight recorded owned processes absent. This is real elapsed-time evidence, not a shortened clock or restarted authority. The fixture's optional six-minute timer leaves its ordinary 60-second behavior unchanged. Receipts and collection source hashes: `/tmp/pi-cu-expiry28-live/{results,collection-provenance}.json`, `run2.log`. An initial fixture/process-preflight assumption and malformed output path failed before the timed case; their sanitized setup receipt remains separate, with all owned processes confirmed absent. No production repair or physical input was needed.
|
|
472
|
+
|
|
473
|
+
Window-bound snapshot/PNG and OCR/hit-test composition retain the originating token; positive window waits validate it. The existing snapshot default remains a separately labeled desktop image by source/portable review; this session did not capture personal desktop pixels to reprove that default. The independent WGC-helper case captures actual owned pixels using a stateless trusted marker descriptor, then refuses that same descriptor after the fixture removes its marker. This lower seam is not automatic fallback acceptance: the existing black-fixture fallback failed before handoff in `Graphics.CopyFromScreen` with “The handle is invalid,” on both the candidate and unchanged integration `ad28859`. Input-desktop metadata reported `Default`; no lock attribution was made. The subsequent [targeted handoff repair](#wgc-handoff-after-screen-copy-failure) records automatic fallback separately from this earlier lifetime evidence.
|
|
474
|
+
|
|
475
|
+
A held provider pauses preparation after root validation; marker removal before release yields no invocation and an independent counter of zero. A separate provider invocation increments its counter and removes the marker during dispatch. That result retains `verification: sent`, `dispatchAttempted: true`, `effectsUncertain: true` and `WINDOW_REFERENCE_LOST_AFTER_DISPATCH`, with no physical fallback/replay. Cleanup failure retains priority; key/button release does not depend on target proof. These are scoped nonphysical cases, not renewed physical cancellation acceptance.
|
|
476
|
+
|
|
477
|
+
Review regressions now cover real enumeration on an unswitched private desktop: the exact fixture/native thread desktop names are verified before the actual callback runs. Its `WM_NULL` probe removes the lifetime marker during metadata collection. The pinned old callback removed zero markers and then stamped earlier metadata; the fixed callback detects the removed witness, omits that row and marks the observation incomplete, while a later fresh observation can bind again. Marker cleanup, both owned process exits and desktop destruction are independently checked. This is enumeration/proof-loss evidence, not interactive-desktop UIA or genuine numeric handle reuse. Earlier desktop-isolation setup failures were retained as setup failures; no normal-desktop binding fallback was used.
|
|
478
|
+
|
|
479
|
+
An owned replacement plus an unverifiable title-constrained disappearance wait remains inconclusive. `element_info` and unbound nodes retain explicit unavailable-reference reasons and no issued IDs. An actual owned `close_window` returned posted/sent and a separate wait observed its disappearance. The immediate `targetState: absent` completion branch is source-reviewed but was not observed in that live receipt; it preserves an intended terminal disappearance rather than falsely reporting generic post-effect failure. Live-window marker loss after another action still retains uncertain effects, and cleanup failures retain priority.
|
|
480
|
+
|
|
481
|
+
The runner retains raw sanitized receipts/source hashes, checks marker cleanup before destroying its root, and independently verifies owned fixture/worker/helper process exit. The test Node process's own console host is recorded separately because it lives until the runner exits; helper console hosts remain in cleanup checks. An earlier overly broad cleanup assertion and a cold 100 ms raw-wait setup timeout were fixture errors, not product passes. One OCR compiler startup returned `spawn UNKNOWN`; an exact compile/EOF-launch control and fresh composed run succeeded without production retry changes. The original failure remains unattributed.
|
|
482
|
+
|
|
483
|
+
Paired warm reads use ten samples per engine on the same owned fixture, excluding cold compile/start and releasing desktop ownership sequentially. The pre-review `c926c32` candidate measured medians 73.70 ms bound versus 74.95 ms on unchanged `ad28859`; this small noise-limited sample is neither a speedup claim nor an isolated validator-cost guarantee. No sleeps, public timing operation or extra model round were added. Scoped receipts and remaining prerequisites do not close #28 or certify a release.
|
|
484
|
+
|
|
485
|
+
Independent review accepted `9caed0e`, integrated as `5695662`. The original 70 receipts retain their `c926c32` source identity in `final-provenance.json`; focused title/close and enumeration red/green evidence for the review fixes is separately hashed in `review-final-provenance.json`. No claim is made that all 70 were repeated on the final source. The independent portable run passed 137 tests with one skipped (`review-merger-check.log`); build and the 87-entry package/documentation check passed. Immediate terminal-absence and zero-root unavailable-reason branches remain source-reviewed rather than new live proof.
|
|
486
|
+
|
|
487
|
+
### Native Chromium UIA action acceptance
|
|
488
|
+
|
|
489
|
+
The existing collector adds a bounded `--native-chromium-only` mode for discovery/find/info plus native `focus`, `set_value` and `invoke`. `--plan` works without builds/backends or Windows access; the portable CLI regression first failed on backend import, then passed. There is no production change or new runner. The owned page reports actual DOM value, logical active control and click count over loopback HTTP, including periodic read-only reporting so ValuePattern does not have to fire an input/change event. These reports never fill/focus/click controls. No browser-protocol input, clipboard action or native physical fallback is used; value and invoke explicitly disable their fallbacks and require actual UIA method names.
|
|
490
|
+
|
|
491
|
+
One serialized paired run on fresh owned Edge profiles/pages passed **all eight checks**: discovery/find/info, logical button→editor focus, exact Unicode value and exactly one invocation per engine. Both initial receipts reported `browser fixture text`, body focus and zero clicks. Pi wrote `Native UIA pi 中文 café 😀` using `uia_value` and invoked using `uia_invoke`; DSH wrote the corresponding reference string using `ValuePattern` and invoked using `Invoke`. Each page reported exactly its intended value and a click-count change 0→1. Native input ticks were unchanged. Foreground HWND was unavailable (0 before/after), so these logical-action passes do **not** prove foreground restoration or the broader #10.2 guard criterion. Pointer coordinates were not observed.
|
|
492
|
+
|
|
493
|
+
Independent review tightened the collector to assert initial body focus and unchanged native input ticks for each action, retaining the observed effects even if that assertion fails. These assertions were checked against the retained raw paired outcomes and portable checks; no equivalent live run was repeated. Cleanup now skips `taskkill` for an already-exited owned root, so a recorded stale PID is not reused as termination authority. The original live-source hash remains in `source-provenance.json`; the review-only changes are recorded separately in `review-assertions.json`.
|
|
494
|
+
|
|
495
|
+
The collector confirmed controller/fixture/browser-root exit and temporary-directory cleanup. Raw report and calls: `/tmp/pi-cu-native-chromium-live/paired/accessibility-comparison.json` and `paired.log`. An initial successful action run reused one browser between engines; it is retained in `initial-shared-state/` but is not credited as reset-fixture comparison. The corrected run uses independent profiles plus run-tagged receipts, and verifies initial state before actions. Existing earlier failures remain in their original evidence sections. Native Chromium scrolling/other provider actions, actual inaccessible roots and true same-process HWND reuse are not exercised; #28 stays open.
|
|
496
|
+
|
|
497
|
+
Reproduce after build under the shared live-test lock:
|
|
498
|
+
|
|
499
|
+
```sh
|
|
500
|
+
npm run benchmark:accessibility -- /path/to/dsh-computer-use-win --native-chromium-only --plan
|
|
501
|
+
npm run benchmark:accessibility -- /path/to/dsh-computer-use-win --native-chromium-only
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
### Agent tasks
|
|
505
|
+
|
|
506
|
+
These are outcome briefs, not step-by-step tool scripts. Supply identical goals and disposable starting states to each host. Agent tests may re-observe, scroll, refresh stale references, handle fixture dialogs and choose supported alternative methods. Explicit method-specific diagnostic tests retain their method constraint.
|
|
507
|
+
|
|
508
|
+
| ID | Ordinary task brief | Controlled variant and pass criteria |
|
|
509
|
+
| --- | --- | --- |
|
|
510
|
+
| A01 | Use an existing Notepad window to create a separate test document, enter two multilingual lines, append a third and verify the result | Existing unrelated tabs and a distractor window; exact three-line result, existing content unchanged, no unnecessary new app instance |
|
|
511
|
+
| A02 | Complete the local form with supplied values, submit it and report the delayed confirmation | Control initially offscreen and delayed content; correct payload and confirmation, no unnecessary user help |
|
|
512
|
+
| A03 | Navigate between fixture pages and complete a second form in the intended browser context | Navigation invalidates IDs and opens a fixture dialog; fresh identification and correct dialog handling, no duplicate submission |
|
|
513
|
+
| A04 | Read a known label and operate its associated fixture control | Incomplete accessibility with supported visual/OCR alternative; correct intended result, or accurate limitation if evidence is insufficient; no unrelated target |
|
|
514
|
+
| A05 | Upload the disposable sample and download the resulting fixture file, verifying its expected content | Reference-supported file/native-dialog boundary; correct owned files and preserved unrelated windows/profile |
|
|
515
|
+
| A06 | Complete a disposable input task with physical stop, attempted interference and explicit human handback | Under the accepted exclusive-control contract, ordinary physical input has no app effect; stop releases control and blocks retries; handback permits user input and pauses automation until explicit continuation. Existing shared-input evidence is historical, not suppression acceptance |
|
|
516
|
+
| A07 | Submit the local form, use its returned code to select one neutral painted native control, and confirm the browser acknowledgement | Separate browser/native references, unavailable native semantic labels, one matching native effect and preserved other control; readonly status evidence and independent HTTP/native oracles |
|
|
517
|
+
|
|
518
|
+
A01–A05 require outcome success unless a limitation is explicitly accepted; an accurate blocker is useful evidence but not a completed task. A06 has intentionally different success criteria. Each required task/recovery scenario needs three consecutive successful reset runs on the accepted candidate; retain earlier failures in the record.
|
|
519
|
+
|
|
520
|
+
## Comparison and diagnosis
|
|
521
|
+
|
|
522
|
+
Two comparisons answer different questions:
|
|
523
|
+
|
|
524
|
+
1. **Tool comparison:** equivalent public calls, identical fixture state, independently observed effects. Compare meaning, not literal JSON, generated IDs or identical internal call sequences. Extend the existing paired benchmark (`tests/benchmark-reference.mjs` in the source checkout), which currently covers background native Edit behavior only. Reset between engines and alternate run order where practical.
|
|
525
|
+
2. **Agent comparison:** ordinary goals through real host/model sessions. Pi uses the user's GPT-6.1 Sol low-reasoning setup; DSH uses the available OpenRouter model because OpenAI access there is geographically restricted. Record the exact DSH model and both hosts' effective settings. These compare host/model combinations, not isolated model or extension superiority. Existing Pi faux-provider tests do not supply this evidence.
|
|
526
|
+
|
|
527
|
+
If an agent fails, retain its tool trace and reproduce the relevant calls against a reset fixture. A direct call failure points toward a tool, target or environment issue; a successful direct call does not alone prove a reasoning failure because timing and state may differ. Check tool descriptions, returned evidence, fixture state and model decisions before assigning cause. Mark unresolved attribution as unknown.
|
|
528
|
+
|
|
529
|
+
Do not build an elaborate new recovery controller. Investigate how the reference makes recovery possible through guidance, actionable results and supported internal fallbacks. Runner watchdogs bound hung tests; they do not impose a new production recovery policy.
|
|
530
|
+
|
|
531
|
+
## Execution and evidence
|
|
532
|
+
|
|
533
|
+
Automate preparation, reset, tool calls, independent assertions and reporting wherever possible. Investigate supported DSH/Pi host interfaces before promising unattended model runs. Human participation remains for genuine interference, physical stopping and visual/display checks; group these into short sessions instead of asking the user to paste every test prompt.
|
|
534
|
+
|
|
535
|
+
Every expanded case records:
|
|
536
|
+
|
|
537
|
+
- Scenario/case ID, purpose, reference contract and involved tools.
|
|
538
|
+
- Owned fixture setup/reset, expected outcome, allowed recovery, stop conditions and scoped cleanup.
|
|
539
|
+
- DSH/Pi source and installed versions, host, model/reasoning settings where relevant, enabled tools/instructions, OS/app/browser versions, display/input state and run order.
|
|
540
|
+
- Exact expected/actual state, tool outcomes, independent observations, timings, interventions, cleanup and relevant sanitized evidence.
|
|
541
|
+
- Result: pass, fail, blocked or not run; cause: implementation, agent decision/guidance, environment, test defect, shared limitation or unknown. Cause attribution requires supporting evidence.
|
|
542
|
+
- Fix/deviation decision, targeted rerun and affected regression results. Do not discard failed attempts to report only a final pass.
|
|
543
|
+
|
|
544
|
+
Continue independent cases after ordinary assertion failures once cleanup and reset are confirmed. If a stop occurs or cleanup/desktop ownership is uncertain, halt that physical run and report dependent cases blocked; never auto-resume stopped input merely to complete a batch. Preserve unrelated work. Do not reuse the reference Notepad E2E script's process-wide kill cleanup: target only owned disposable fixtures.
|
|
545
|
+
|
|
546
|
+
Reconcile historical manual reports with [validation evidence](#review-trace-and-evidence). Reuse unchanged, adequately identified evidence; rerun when changed code, missing environment details or an unresolved failure makes it insufficient. Three consecutive passes are a practical initial gate, not a statistical reliability guarantee.
|
|
547
|
+
|
|
548
|
+
## Reference benchmark
|
|
549
|
+
|
|
550
|
+
Run on the same interactive machine under the same serialized live-test discipline. From WSL2, the configured command relays to the package-managed Windows Node and translates paths; from Windows it uses the invoking Node executable:
|
|
551
|
+
|
|
552
|
+
```sh
|
|
553
|
+
npm run benchmark:reference -- C:\path\to\dsh-computer-use-win 3
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
For WSL2 use a Linux reference path and prefix with `flock -w 180 /tmp/pi-cu-live-tests.lock`.
|
|
557
|
+
|
|
558
|
+
The benchmark creates its own non-activating native Edit fixture. It compares reference Node/MCP/PowerShell calls with this package's Windows worker using the **same Windows Node executable** and alternating engine order. It measures process-cold health, process-cold native-ready find, warm find, background value dispatch, and a find → set_value → read-and-verify workflow. `fallbackType: false` prevents physical typing fallback; the fixture never requires clipboard input. Full browser/physical/model-driven workflows are outside this benchmark.
|
|
559
|
+
|
|
560
|
+
Both engines receive an untimed warmup before measured new-process samples. Runtime downloads, helper file compilation caches and OS caches are therefore warm; process-cold means a new controller process, not installation-cold or clean OS. Health payloads differ, so health timing alone is not an equivalent-feature comparison. Native-ready and verified-workflow timings compare useful equivalent effects. Pi model/agent overhead is excluded. JSON includes versions, OS/CPU, artifact hashes, individual samples, aggregates and methodology. Each measured case records status/cause separately, expected/actual text, independent reset evidence, timing and scoped cleanup. Failed attempts remain in `cases`; timing summaries include passing samples only. Use at least three repetitions; no statistical significance is claimed from three samples. Set `PI_CU_RELEASE_OUTPUT` for `benchmark.json`.
|
|
561
|
+
|
|
562
|
+
### Comparison report and failure collection
|
|
563
|
+
|
|
564
|
+
The fixture resets its own editor to the literal `initial` before and after each engine. Its UI thread independently returns the actual text over the owned fixture pipe, in addition to the engine's `element_info` readback. This prevents a tool response alone from proving the intended edit. Ordinary assertion failures are retained while later cases continue only after controller disposal and editor reset are confirmed. Cancellation/stopping or unconfirmed cleanup blocks remaining dependent cases. Final cleanup closes only the owned fixture and removes its temporary directory; this is not a claim that all product cleanup paths pass.
|
|
565
|
+
|
|
566
|
+
The CLI exits nonzero when a case, warmup or cleanup fails, but still emits its structured report, including through the WSL relay. Invalid invocation arguments remain immediate CLI errors. Run the passive reporting regression from WSL2 after building:
|
|
567
|
+
|
|
568
|
+
```sh
|
|
569
|
+
flock -w 120 /tmp/pi-cu-live-tests.lock npm run test:benchmark:report -- /path/to/dsh-computer-use-win
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
This regression runs the same public benchmark CLI with `--verify-failure-collection`. It deliberately changes the first verification expectation, labels that case `injected: true` and `cause: test-defect`, and asserts the benchmark exits 1 with the failed case retained, five later passing cases, reset text before every case, alternating engine order and confirmed fixture cleanup. The regression itself exits 0 only when that reporting behavior is correct. Do not count the injected mismatch as a DSH/Pi product defect or include it in ordinary comparison evidence. No physical input, clipboard mutation, daily profile access or production behavior is added by either command.
|
|
573
|
+
|
|
574
|
+
The separate stop regression substitutes one deliberate MCP `isError` response at the reference request seam, before the first measured health dispatch. Both warmups still use the real engines. It checks that all text blocks and the complete error result survive in the report, the owned editor remains `initial`, all five later cases are blocked without execution, and cleanup completes:
|
|
575
|
+
|
|
576
|
+
```sh
|
|
577
|
+
flock -w 120 /tmp/pi-cu-live-tests.lock npm run test:benchmark:stop -- /path/to/dsh-computer-use-win
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
This uses `--verify-stop-collection`, labels the failed case as injected/test-defect, and does not exercise a real emergency-stop mechanism. Its red run exposed the old generic `Reference health failed` assertion discarding cancellation evidence and continuing later cases; the corrected collector retains the MCP error and blocks them. Keep this deliberate failure separate from normal product outcomes.
|
|
581
|
+
|
|
582
|
+
On 2026-10-30 this regression failed against the old collector (`ok: true` concealed the requested diagnostic expectation) and passed after the reporting/reset extension. A normal three-repetition run against reference 0.5.3 and Pi 0.1.0 passed all six measured cases and both warmups on Windows Node 22.23.4 via WSL2. The independently observed values and resets matched, and controller/editor plus final fixture cleanup were confirmed. These are background native Edit results only; physical, browser and real-agent workflows remain separate tickets.
|
|
583
|
+
|
|
584
|
+
### Paired capture and OCR comparison
|
|
585
|
+
|
|
586
|
+
Run from WSL2 after building, under the same serialized live-test discipline:
|
|
587
|
+
|
|
588
|
+
```sh
|
|
589
|
+
PI_CU_RELEASE_OUTPUT=/tmp/pi-cu-capture-evidence flock -w 120 /tmp/pi-cu-live-tests.lock npm run test:reference:capture -- /path/to/dsh-computer-use-win
|
|
590
|
+
npm run test:reference:capture:report -- /path/to/dsh-computer-use-win
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
Serialize the report-contract command too when other live checks are active. `test:reference:capture` relays to the package-managed Windows Node and compares the public reference MCP and Pi worker interfaces. It creates only owned, non-activating capture/OCR fixtures; no physical input or clipboard actions are sent. The fixtures independently report geometry and minimized state. A separate offscreen rendering of the known painted label supplies ink coordinates without using either engine's screenshot/OCR implementation. PNG dimensions, center pixels, origins/scales, literal queries, word bounds, clipped text and unavailable-target results are retained. Screenshots remain in memory; the optional JSON artifact contains sanitized metadata, source hashes and observations rather than image payloads. A minimized-target fallback can capture desktop pixels internally, but those pixels are not persisted.
|
|
594
|
+
|
|
595
|
+
The public CLI contract was exercised red → green as scaled capture, native-resolution capture, fallback and OCR evidence were added. Its pass means the collector faithfully reports both engines and propagates the comparison exit status; it does **not** require every product observation to pass. Ordinary case failures remain recorded while independent cases continue. Cancellation/stopped evidence blocks later tool calls and fixture scenarios; uncertain fixture cleanup halts collection. Report cleanup confirms owned fixture exit and temporary-directory removal, not universal product cleanup. For a focused rerun, append `--scenario minimized --engine reference`; a partial rerun does not replace full coverage.
|
|
596
|
+
|
|
597
|
+
On 2026-10-30, reference **0.5.3** and Pi **0.1.0** ran from WSL2 through private Windows Node **22.23.4**, Windows build series **26200**. The final 24-case report recorded **23 passing checks and one retained reference minimized-capture failure**, with cleanup confirmed:
|
|
598
|
+
|
|
599
|
+
| Observation | Reference | Pi | Disposition |
|
|
600
|
+
| --- | --- | --- | --- |
|
|
601
|
+
| Normal native/scaled and covered green fixture | Correct green center pixels, PrintWindow, physical mapping within independent fixture bounds | Same known content and valid mapping | Scoped fixture pass, not every display/capture path |
|
|
602
|
+
| Black target behind magenta cover | Flagged `screen-region`, `occludedPossible: true`; target content was not established | WGC with independently verified black center | Both uncertainty reporting and actual method are retained; no general performance/superiority claim |
|
|
603
|
+
| Independently minimized green target | `ok: true`, unflagged PrintWindow caption at offscreen bounds near (-31993,-32000), no known green client content | Desktop fallback explicitly marked `windowCaptureFailed` | Reference outcome fails the fixture's “known target content or explicit unavailable/inconclusive” oracle; retain for #37 disposition rather than copy it into Pi |
|
|
604
|
+
| Wrong owner and closed target | Explicit failure, no image | Explicit failure, no image | Expected negative outcomes |
|
|
605
|
+
| OCR native/scaled and literal metacharacter miss | Recognized expected text; no regex interpretation or invented IDs | Same semantic checks | Known-label fixture pass |
|
|
606
|
+
| Painted-ink localization diagnostic | Native first-word X offset **+7 px**, scaled **+6 px** relative to independently rendered ink; Y offset 0 | Native offset 0; scaled approximately (+0.13,-0.36) px | Diagnostic difference, not a pixel-perfect OCR assertion; investigate before generalizing coordinate accuracy |
|
|
607
|
+
| Clipped fourth row | Three expected labels plus garbled extra recognized text | Three expected labels | Actual text retained; no assumption that clipped OCR must agree |
|
|
608
|
+
| Minimized OCR | Empty caption OCR with no query match and no conclusive-absence claim | Explicit `OCR_CAPTURE_FAILED` refusal | Different observable outcomes, not silently normalized to identical results |
|
|
609
|
+
|
|
610
|
+
The existing Pi native capture and OCR regressions also passed against the extended non-activating fixtures. Type checking, linting, all 42 portable tests, build and package/documentation checks passed. The live Pi regressions used a temporary Windows-readable copy of the runtime test dependency because Windows Node cannot resolve the worktree's absolute Linux dependency symlink; production source was unchanged.
|
|
611
|
+
|
|
612
|
+
The original overly specific minimized assertion required Pi's fallback flag from both engines. It was replaced with the semantic oracle above and a fixture-reported minimized-state check. The retained reference caption result still fails that broader oracle; the test adjustment did not erase the observation. No production capture/OCR code was changed.
|
|
613
|
+
|
|
614
|
+
The original #7 OCR/literal-query/mapping criterion is supported by these named native/scaled fixtures; this does not certify every display layout or pixel-perfect recognition. Remaining capture/OCR acceptance includes: (1) 150/200% and mixed-DPI layouts, changed primary/display layout, plus negative-origin OCR (the screenshot-only 100% two-monitor slice below is now covered); (2) missing-language/WinRT availability and protected/elevated surfaces on suitable installations; (3) cancellation during active recognition, helper retirement and recovery, since existing OCR checks only pre-abort; and (4) physical visual targeting. The user now grants standing idle-test authorization for scoped disposable targets in the current session. Actual fixture isolation and environment prerequisites still apply; #6/#7/#21 retain these broader obligations.
|
|
615
|
+
|
|
616
|
+
### Current negative-origin screenshot mapping
|
|
617
|
+
|
|
618
|
+
The existing `test:reference:capture` collector adds only the focused `--scenario monitor-placements` selection; `--plan` lists it without backend imports, Windows calls or fixture files. Its portable plan regression first failed on a missing backend import and then passed. The owned capture fixture gains private NOACTIVATE/NOZORDER/NOSIZE placement IPC and independent physical Win32 window/client plus DWM extended-frame (attribute 9) oracles under a temporary per-monitor-aware thread context. A failed/empty DWM frame query blocks setup. Focused PrintWindow bounds and origin must exactly equal that frame; a uniformly colored image and center-inside-client check alone are insufficient. No production capture code, public tool parameter or display setting changed. The fixture's window remains system-DPI-aware; these results cover only the measured 96-DPI setup.
|
|
619
|
+
|
|
620
|
+
The reviewed frame/scale proof verifies **all 12 recorded captures**: primary, negative-X secondary and monitor-boundary placement, native and reduced-width PNG, for each engine. The corrected-oracle collection retained nine passing checks and three DSH scaled-image checker failures: the initial assertion assumed an exact scale, while pinned `windows-uia.ps1` lines 2354/2359 publish four-decimal `imageScale`. The reviewed saved-report checker verifies the same independent measurements without another equivalent live run and preserves those original statuses/errors. Pi ratios remain exact; DSH X precision is bounded by ±0.00005, with at most half an output pixel of resized-height rounding plus the propagated published-scale precision in Y. PNG aspect ratio is checked separately against the measured frame. Shifted-origin/bounds, wrong size/height and outside-bound scale regressions fail. Fresh fixture metadata rechecked primary `(0,0,1920,1080)` and secondary `(-1920,0,1920,1080)`, both 96×96 DPI, with respective work areas `(0,0,1920,1032)` and `(-1920,0,1920,1032)`. The metadata audit identifies these as DISPLAY33/34. Only the owned 320×200 fixture moved; its HWND/PID, size, requested physical position and combined-desktop containment were independently verified before capture.
|
|
621
|
+
|
|
622
|
+
| Placement | Observed origin, both engines | Native / scaled PNG | Actual capture |
|
|
623
|
+
| --- | --- | --- | --- |
|
|
624
|
+
| Primary | `(87,80)` | `306×193` / `80×50` | PrintWindow; known green center |
|
|
625
|
+
| Negative-X secondary | `(-1833,80)` | `306×193` / `80×50` | PrintWindow; known green center |
|
|
626
|
+
| Across x=0 boundary | `(-153,80)` | `306×193` / `80×50` | PrintWindow; bounds extend across x=0 |
|
|
627
|
+
|
|
628
|
+
Decoded pixels, exact independent DWM frame geometry, origins and both scale axes support the scoped mapping proof; screen-region uncertainty could not pass as known fixture content. Available input-tick samples were unchanged during placement/capture. Three precision-check failures occurred before their post-capture oracle samples; the offline frame proof does not invent those missing samples. Foreground was unavailable (0 before/after), so unchanged samples do not prove foreground restoration. No input, OCR or desktop-scope capture ran. Images stayed in memory; artifacts retain only owned geometry, known pixel samples, sanitized tool outcomes, actual source hashes and metadata. Existing #29 failures were not rerun or reclassified.
|
|
629
|
+
|
|
630
|
+
`/tmp/pi-cu-capture6-live/capture-comparison.json` and `paired.log` retain the corrected-oracle collection's 12 raw outcomes, including its three precision-check failures; identical originals are retained under `frame-scale-rounding/`. `frame-revalidation.json` records the reviewed frame-only proof and distinguishes collection-runner and reviewed-assertion hashes; the independent fixture hash matches the captured data. `initial-weak-oracle/` preserves the earlier 12 pixel/containment passes and their source hashes, which are not credited as exact origin proof. `/tmp/pi-cu-capture6-monitors.json` retains the separate metadata audit. After controller/fixture disposal, a separate OS process query required every recorded Pi-worker, reference-controller and fixture root PID to be absent; all four were absent and temporary-directory cleanup succeeded. Query failure, missing/duplicate process rows or any live recorded root would fail cleanup and retain artifacts. This establishes those recorded root exits, not universal descendant cleanup.
|
|
631
|
+
|
|
632
|
+
Independent review accepted coverage `777b12f`, merged as `29e8ff0`; its portable rerun passed 127 tests with one skipped (`/tmp/pi-cu-capture6-live/check-merger.log`). The reviewer rechecked all recorded frame/pixel/hash and scoped cleanup evidence without another live capture batch.
|
|
633
|
+
|
|
634
|
+
150%, 200%, mixed-DPI transitions and actual display/primary/topology changes remain unexercised: this desktop exposes two 100% monitors, and no global setting was changed. Application movement and PNG resizing do not replace those cases. #6 stays open, with manual/setup obligations remaining under #21. Inspect the focused plan and run only under the shared live-test lock:
|
|
635
|
+
|
|
636
|
+
```sh
|
|
637
|
+
npm run test:reference:capture -- /path/to/dsh-computer-use-win --scenario monitor-placements --plan
|
|
638
|
+
npm run test:reference:capture -- /path/to/dsh-computer-use-win --scenario monitor-placements
|
|
639
|
+
npm run test:reference:capture -- --verify-monitor-report=/path/to/capture-comparison.json
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
### WGC handoff after screen-copy failure
|
|
643
|
+
|
|
644
|
+
The owned same-target diagnostic in `/tmp/pi-cu-wgc6-same-fixture/` reproduced the original failure on both unchanged `ad28859` and lifetime candidate `c926c32`: rejected blank PrintWindow pixels were followed by an unhandled `Graphics.CopyFromScreen` Win32 exception, preventing the existing WGC handoff. Direct existing-helper capture of that same black window behind its unchanged magenta cover returned actual black pixels and independent DWM frame geometry. That diagnostic is the pre-repair failure; direct delegation alone did not prove automatic fallback.
|
|
645
|
+
|
|
646
|
+
Repair `56eeea4` / diagnostic retention `963cf43` catches only that final visible-window screen-copy Win32 failure, preserves it as `nativeCaptureError`, and allows the existing private target to reach WGC without inventing native pixels. Other identity, cancellation and cleanup errors do not satisfy the failed-stage discriminator. Existing `native-capture.mjs` black-window checks now compare automatic results to the fixture's independent DWM frame/origin and unchanged frame/input tick; foreground 0 remains unavailable evidence.
|
|
647
|
+
|
|
648
|
+
The pre-lifetime missing-helper control on `963cf43` in `/tmp/pi-cu-wgc6-repair/missing-helper-results.json` passed through the actual public worker using a disposable package copy missing only `assets/wgc.cs`. Source/package/lock/compiled capture hashes matched its recorded candidate. The result was `ok:false`, `SCREEN_REGION_CAPTURE_FAILED`, the original invalid-handle diagnostic, a separate `NATIVE_RESOURCE_MISSING` WGC error, and no image/private handoff. The same owned HWND/PID and frame `(30,40,320,200)` persisted with unchanged input tick; all eight recorded fixture/worker/helper/console PIDs were independently absent after disposal. Images were not stored. Two preceding collector setup failures (Windows copy of a Linux dependency symlink, then malformed UNC URL) are retained separately and are not product failures or capture evidence.
|
|
649
|
+
|
|
650
|
+
After integrating reviewed lifetime source `2c7767e`, the public-worker automatic capture on `8779f61` passed (`/tmp/pi-cu-wgc6-repair/automatic-results.json`). A fresh observed reference alone selected the same owned black HWND/PID behind its magenta cover. The actual invalid-handle screen-copy error was retained while the automatic WGC result returned genuine 80×50 black pixels, exact independent DWM bounds `(30,40,320,200)`, origin `(30,40)`, both scales 0.25 and the same original reference on the result and image. No private descriptor leaked. A fresh read validated the reference after capture; an unknown reference returned failure without an image or pixel-stage handoff. Frame and input-tick samples stayed unchanged. Foreground remained unavailable (0), so restoration is not established. All eight recorded owned processes were absent after disposal.
|
|
651
|
+
|
|
652
|
+
The older failure control and final automatic capture retain distinct source manifests; the unchanged native pixel-failure discriminator was exercised in both. Integrated checks passed 137 tests with one skipped, plus build and the 87-entry package/documentation check. No additional model, physical input, desktop/minimized capture, unrelated-window binding or stored screenshot was involved. This repairs the observed handoff gap; 150/200%, mixed-DPI/topology and the other #6 obligations remain open.
|
|
653
|
+
|
|
654
|
+
### Same-worker kept-profile reconnect
|
|
655
|
+
|
|
656
|
+
The existing profile host/server adds a focused `--reconnect` mode, with a safe `--plan` that first failed in a copied script lacking the backend and then passed without creating fixture files. No production browser/profile module changed. The test uses its existing HTTP-only `remembered` cookie and disposable settings/root, public new-tab/read/health calls and fixture-only CDP lifecycle control. It never invokes native discovery, writes unrelated window markers, launches a daily profile or uses real credentials/sign-in.
|
|
657
|
+
|
|
658
|
+
The actual headless Edge run on coverage source `c7a2ba8` retained worker PID `20444` through browser closure and reconnect. The fixture independently matched the fresh kept directory/lease, browser PID, OS creation time, executable and exact user-data-dir argument before sending one `Browser.close`. PID `10804` (creation `2026-10-31T16:12:58.3948920Z`) was confirmed absent before the next public new-tab request. The replacement PID `36148` (creation `2026-10-31T16:13:04.5586310Z`) used the same kept path and returned `Cookie: remembered`; old public tab observation returned `STALE_BROWSER_REFERENCE`. No fallback, automatic mutation retry or production repair was needed. Worker continuity here is repeated public health PID on the retained host, without independent worker OS creation-time attestation.
|
|
659
|
+
|
|
660
|
+
Both browser roots were absent and the kept directory existed without its lease lock after shutdown. The fixture removed its directory and exited zero; success is printed only after that exit. A separate terminating OS query confirmed all three recorded browser/worker PIDs absent. Later coverage assertions require that exact stale error and include worker retirement inline; their conditions are already established by the retained actual result and post-query, not another equivalent browser run. Query/ownership uncertainty is failure, and fixture cleanup refuses to delete storage under a live or unknown recorded owner. No orphan is killed through an old lease.
|
|
661
|
+
|
|
662
|
+
Independent review found a fixture cleanup gap: its lease-only scan could delete storage after an observed root's lease vanished. The fixture now retains successful root observations (PID, creation, executable and owned profile) and rechecks them before deleting anything, independently of lease existence. Query failure or any live/reused PID blocks cleanup. The actual EOF negative `--cleanup-control` uses a harmless fixture-owned Node child plus canary with no lease: the old gate exited zero/deleted storage; the fixed gate exited one with `PROFILE_CLEANUP_BLOCKED` and retained the canary. Only afterward did the fixture close that child's retained stdin handle; a separate check proved child exit before removing the test directory. This is a causal cleanup-fixture regression, not a real browser crash/orphan test. The successful browser run remains on `c7a2ba8`; no equivalent browser run was repeated after this fixture fence.
|
|
663
|
+
|
|
664
|
+
Private artifacts: `/tmp/pi-cu-profile18-live/reconnect.log`, `post-cleanup.json`, `source-before.json`, `cleanup-control-{red,green}.log` and `final-provenance.json`; safe-plan red/green and configured check logs retain their named source scopes. Chromium coverage here is Edge-only. This reconnect slice alone does not test a surviving live browser; the controlled component check below now covers that refusal/recovery mechanism. The historical Firefox residue cause remains unproved. The later [manual Bitwarden check](#manual-bitwarden-sign-in-and-restart) records interactive login and removal; real-site remembered authentication remains unverified under #18. Firefox kept-cookie restart already passed the separate paired profile workflow below; the affected-engine post-repair cleanup recheck below now passed, without adding another persistence test.
|
|
665
|
+
|
|
666
|
+
### Controlled dead-writer/live-browser recovery
|
|
667
|
+
|
|
668
|
+
One headless Edge `--live-orphan` run passed on unchanged coverage source `4f475e1`, using the existing profile host/server and real production lease acquisition/recording. No production code, daily profile, credential, native discovery or physical input changed. Safe-plan and fixture-proof regressions cover absent actor metadata, changed identity/lease and live or unknown writers before the Windows run.
|
|
669
|
+
|
|
670
|
+
The fixture independently pinned lease writer PID `24640` and browser PID `8172` by creation time/executable, plus the browser’s exact owned profile argument. The writer exited normally without releasing its lease while the fixture retained the real browser handle. Contender worker `21912` passed the actual public `BROWSER_PROFILE_BUSY`/still-alive refusal assertion; the original lease hash, readable page and synthetic cookie remained unchanged, with no recovery artifacts. The fixture then closed only its retained browser handle and proved the old root absent. Recovery worker `14684` opened browser `15576` with a different creation identity at the same kept path, retained `Cookie: remembered`, and acquired a different token whose lease owner matched that worker. The fixture used production APIs for every lease write; no stale PID was killed or failed action replayed.
|
|
671
|
+
|
|
672
|
+
Normal disposal and the reused independent fixture-retirement check passed. A final terminating CIM query proved the six reported writer/browser/contender/recovery/fixture roots absent and the exact owned fixture directory absent. This is not a universal-descendant claim; the initial setup-worker absence is asserted inside the case, without a separately serialized identity receipt. Unknown ownership/query/cleanup retains the real owners and pipes rather than deleting storage.
|
|
673
|
+
|
|
674
|
+
Evidence is `/tmp/pi-cu-profile-orphan18-live/{result.json,run.log,post-cleanup.json,live-provenance.json}`. The manifest pins actual `4f475e1` source/build hashes separately from later baseline/document integration. Together with the prior genuine worker-crash/cookie-flush, restart and cleanup checks, this establishes the #18 ownership/recovery criterion without stealing live owners. A natural `worker.js` crash leaving a surviving browser was not observed; that causal scenario is a coverage limit, not an additional acceptance requirement. The later [manual Bitwarden check](#manual-bitwarden-sign-in-and-restart) records interactive login, expected logout and removal; real-site remembered authentication still keeps #18 open.
|
|
675
|
+
|
|
676
|
+
### Manual Bitwarden sign-in and restart
|
|
677
|
+
|
|
678
|
+
On 2026-11-01, a user-assisted Edge check used unchanged production source `8002123`, actual Pi 1.4.0 RPC sessions and a local scripted provider. Isolated settings enabled a visible browser and a kept profile in one disposable root; personal settings and daily browser profiles were not used. The provider performed only health and initial navigation. No network model received page contents, and automation stayed idle during human authentication.
|
|
679
|
+
|
|
680
|
+
The initial page-open step did not report successful readiness; its detailed error was not retained, so its cause remains unknown and it is not a passing tool-open result. The user independently reported successful manual login at `https://vault.bitwarden.com/#/login`. After shutdown, the original Pi process and recorded worker/browser roots were absent, the kept profile remained, and its lock was absent. A second Pi session successfully opened `about:blank` using the exact same kept path, with new worker/browser identities. The user then navigated manually and reported **“Login form — signed out.”** No authenticated DOM, cookie values, credentials or screenshots were read for the check.
|
|
681
|
+
|
|
682
|
+
Both Pi sessions used the installed RPC host's registered graceful SIGTERM shutdown path, which awaits normal runtime disposal; actual Pi exit codes were not serialized. The restart coordinator's operator stdin was closed, so its attempted `close` command was not delivered. Independent checks subsequently confirmed both Pi processes and all four recorded worker/browser roots absent, no matching profile process, and no ownership lock. Only then was the exact disposable settings/profile root removed and its absence verified; passive coordinators were retired after those checks. These are scoped cleanup proofs, not universal-descendant assertions.
|
|
683
|
+
|
|
684
|
+
[Bitwarden documents](https://bitwarden.com/help/vault-timeout/) logout when the web-vault tab or browser closes. The human observations therefore support real interactive login and expected site logout, while the profile/process receipts support same-path reuse and removal. They do **not** establish a real account remaining authenticated across restart; existing synthetic-cookie persistence evidence retains its separate scope. Private metadata and failure records are in `/tmp/pi-cu-signin18/result.json` and its referenced receipts. No production code or new checked-in test runner was added.
|
|
685
|
+
|
|
686
|
+
### Manual GitHub remembered sign-in
|
|
687
|
+
|
|
688
|
+
On 2026-11-02, production source `d0dfe04` and a fresh build passed #18's remaining real-account check using actual Pi 1.4.0 RPC hosts from WSL2, Windows Node 22.23.4 and installed visible Edge. Isolated settings enabled `browserSignIn`; both sessions used the exact same dedicated kept profile, with different observed Pi/worker/browser identities. A local scripted provider called only health and initial navigation; no network model, daily profile, credential, authenticated DOM, cookie value or screenshot was used.
|
|
689
|
+
|
|
690
|
+
The user reported successful manual GitHub login. After Pi's registered graceful SIGTERM shutdown, independent checks found the first Pi process and its recorded worker/browser absent, the profile preserved and its lock absent. The restarted Pi host opened `about:blank` successfully through the extension. The user manually visited GitHub and confirmed **“Still signed in”**, without reauthentication. The final graceful shutdown returned Pi's expected SIGTERM exit code 143; all four recorded worker/browser roots and both Pi processes were absent, no process command line matched the dedicated storage root, and its lock was absent before removing that exact disposable root and verifying removal.
|
|
691
|
+
|
|
692
|
+
The reused temporary coordinator initially expected exit code zero, although Pi's graceful SIGTERM handler exits 143; it conservatively retained the first receipt. Independent absence/lock checks cleared restart, and the coordinator's expectation was corrected for final shutdown. The first Pi exit code was not serialized and is not claimed. This was a coordinator assertion issue; no production change or extra login run was needed. Private metadata-only receipts are in `/tmp/pi-cu-github18/`, including human confirmations, both session identities, the initial independent shutdown check and `result.json`. This completes the agreed real-site persistence/removal gate; it does not claim every site's policy or visible Firefox sign-in is supported.
|
|
693
|
+
|
|
694
|
+
### Headless Firefox temporary-profile disposal
|
|
695
|
+
|
|
696
|
+
One focused recheck on `0c5b988` (base `6f36d11`) passed through the real WorkerClient using the existing profile fixture, temporary storage and official Firefox 144.0 executable. Windows Node was 22.23.4. Health, one local-page open and an owned-tab read succeeded before normal disposal. No production source, browser visibility policy, cookie workflow, global native discovery or desktop input changed.
|
|
697
|
+
|
|
698
|
+
The fixture matched its temporary lease, exact Firefox profile argument/headless flag and OS PID/creation/executable identities before disposal: worker `14092` (creation `2026-10-31T18:57:19.2816470Z`), browser `35796` (`18:57:28.4275910Z`) and an additional exact-profile process `9724`. The profile-prefix matcher had a positive browser-root control. After disposal, terminating queries required all recorded roots absent and zero profile-prefix matches; the temporary profile and lock were absent **before** fixture-directory removal. The fixture exited zero, and a separate terminating query required its recorded PID `6616` absent plus its directory absent. Query failures or live/reused identities cannot pass; the scoped mode retains its owned pipes/storage on uncertainty instead of inheriting the full suite's teardown timer.
|
|
699
|
+
|
|
700
|
+
Evidence is `/tmp/pi-cu-firefox18-live/run.log`, `source-before.json` and `stage.log`. The source manifest pins actual source/build hashes. The final success proves the post-fixture assertions ran; a later report-only change includes their parsed booleans explicitly rather than the older `fixtureStorageRemoved` field. That serialization change is not another live run. This confirms the affected engine's current normal temporary-profile cleanup, not the cause of the historical action-profile residue, surviving-live-orphan handling, real account sign-in/removal or whole #18 acceptance. Existing paired Firefox kept-cookie restart evidence remains separate and was not repeated.
|
|
701
|
+
|
|
702
|
+
### WSL Pi human handback and continuation
|
|
703
|
+
|
|
704
|
+
On 2026-11-02, the existing scripted actual-Pi fixture passed `handback` from WSL2. One normal operation wrote `x`, settled, and released control before the human was invited. The user typed `abc` into the owned disposable editor and explicitly replied to continue. A fresh user operation required a successful scoped snapshot before Ctrl+End/one further `x`; the independent fixture required exactly `xabc` before continuation and `xabcx` afterward. Mutation replies required confirmed cleanup, operation-specific release acknowledgments, fault-free trace and no extension errors. Both handbacks confirmed exclusive control false and released held counters/OS keys. Pi exited zero and all recorded Linux/Windows actors and the fixture exited before test-directory removal. Two-axis review corrected observation-result and release checks before the live run. Metadata-only summary: `/tmp/pi-cu-held31/handback-result.json`; the successful runner removed its raw temporary trace/settings. This satisfies ordinary human input, explicit continuation, fresh targeting and preservation for #31; it is not a real-model/native-task acceptance replacement for #35.
|
|
705
|
+
|
|
706
|
+
### Control interruption acceptance
|
|
707
|
+
|
|
708
|
+
Issue #31 is accepted on 2026-11-02 using the narrowed safety scope and the following composed evidence. This does not relabel the failed lock-cycle attempts as passes or claim an actual OS lock during held input.
|
|
709
|
+
|
|
710
|
+
| Safety behavior | Evidence retained |
|
|
711
|
+
| --- | --- |
|
|
712
|
+
| Refuse input on a locked/unavailable interactive desktop | Existing locked-session refusal evidence and the retained pre-dispatch guards; see [locked-session correction](#locked-session-diagnosis) and the historical attempts below. |
|
|
713
|
+
| Detect availability loss while control is held | `npm run test:stop -- --desktop-loss` passed with Windows Node 22.23.4 on 2026-11-02. A disposable copy of `stop.cs` adds only a file-availability guard at the start of `InteractiveDesktop`, retaining the real OS check, normal 100 ms timer and stop/release code. The ordinary-state negative control stayed controlled; injected unavailability emitted the normal operation stop event, set cancellation, released exclusive control and border, and rejected same-operation reacquisition. Disarm, helper exit and desktop-mutex release succeeded. No keyboard/mouse input or real OS lock occurred. |
|
|
714
|
+
| Propagate stop and prevent more dispatch | Actual native Pi Esc, actual WSL Pi Ctrl+Alt+F9, registered command-stop cases, real-worker protection/listener-loss regressions and scoped native listener-exit evidence. |
|
|
715
|
+
| Release held input on interruption/error | Four [known-held Ctrl/button cases](#known-held-input-release), each with independent OS release and native cleanup/settlement, plus the actual host stop receipts. |
|
|
716
|
+
| Retain uncertainty rather than replay or replace an input owner | Existing input-preparation, client and worker regressions for unconfirmed release, owner exit and queued settlement; no-input host-exit evidence retains its separate scope. |
|
|
717
|
+
| Resume only after explicit user activity and fresh observation | [Actual WSL Pi handback](#wsl-pi-human-handback-and-continuation) preserved exactly `xabcx`, with separate operations and cleanup acknowledgments. |
|
|
718
|
+
|
|
719
|
+
The injected native run's source hash is `8be42957967575829c38abf3597b71d2be13fe59aca586f1209a8cbc98f57a5a`; seam and assertions are retained in `tests/stop-host.mjs`. Receipt: `/tmp/pi-cu31-desktop-loss.log` and `C:\Users\fei\AppData\Local\Temp\pi-cu-desktop-loss-BzbmFX\result.json`. The copied native sources/executable were removed after confirmed exit; the helper used the production desktop mutex. Two-axis review found no outstanding Standards or Spec findings. Windows hook timeout removal remains the accepted platform limit; abrupt destruction of an actual held-input owner is not empirically claimed. Such uncertainty must retain ownership and block automation. Broader presentation/display, text, pointer and real-agent tasks remain with their existing issues.
|
|
720
|
+
|
|
721
|
+
### Lock safety scope and prior attempts
|
|
722
|
+
|
|
723
|
+
Current scope, clarified by the user on 2026-11-02: reuse existing locked-input refusals and ordinary explicit handback/continuation evidence. The #31 interruption/cleanup question is now covered by the [composed acceptance evidence](#control-interruption-acceptance). Target survival, a complete unlock/resume cycle and seamless task recovery are not first-release gates. No further #31 human lock action is queued. The failed attempts below remain failed evidence, not newly passed tests.
|
|
724
|
+
|
|
725
|
+
The 2026-11-02 lock/unlock attempt did not pass. A temporary cycle probe first masked its original exception with an assertion requiring `exclusiveControl: false` even when the listener was explicitly unstarted. It retained the controller. Independent inspection showed no stop/native-input helper and zero held OS inputs; the passive controller was then retired, worker/helper exits confirmed and its exact directory removed. The fixture now reports the primary error and recognizes successful health with `control.started: false` as no acquired suppression. An unlocked negative control correctly failed the initial locked prerequisite before input and cleaned up.
|
|
726
|
+
|
|
727
|
+
A prepared second attempt then returned `WINDOWS_ERROR: WINDOW_IDENTITY_CHANGED: refresh window observations` at activation while the user had locked Windows; no resume typing occurred. It exited nonzero with normal cleanup. This is a safe refusal but does not establish the expected session classification, target lifetime across lock, or post-unlock continuation. Cause remains unproved. The unproved temporary cycle extension was removed; only isolated settings, exact session-refusal expectations, primary-error reporting and conservative cleanup improvements remain in the existing runner. The target-identity diagnosis is not a release blocker by itself; investigate it only if needed to establish the retained interruption/cleanup requirement. Evidence: tool transcript, `/tmp/pi-cu-held31/{retained-lock-state.json,lock-retirement.json,unlocked-negative-control.log}`. No application code changed or passing stop/handback result was invalidated.
|
|
728
|
+
|
|
729
|
+
### WSL Pi physical shortcut
|
|
730
|
+
|
|
731
|
+
On 2026-11-02, the existing actual-Pi fixture was extended to the WSL2 host, keeping Linux `/proc` identities separate from Windows process identities, mapping observer/settings paths and forwarding overrides only to the owned child. Fresh same-launcher normal-stop and no-input abrupt-host-exit preflights passed with all recorded Linux/Windows participants absent. The user then physically pressed Ctrl+Alt+F9 during one 2,000-character disposable typing request. Pi stopped with `COMPUTER_USE_STOPPED`, confirmed native cleanup and operation release, and independently observed text stable at 251 characters, no unexpected or leaked shortcut characters, released OS inputs and zero listener-held counters. Post-release health confirmed exclusive control/border off. Pi exited zero and all recorded participants and the fixture retired normally. This closes the missing WSL physical-stop integration clause; native Esc was not repeated.
|
|
732
|
+
|
|
733
|
+
The physical source fingerprint was `59cb02048585a978ae8b2a6f910f41272e4305eadbb299c84a41d86a5253030c`, before the later optional handback mode. Scoped summary is `/tmp/pi-cu-held31/wsl-shortcut-result.json`; fresh prerequisite receipts are `/tmp/pi-cu-stop-preflight-{K6P15z,EqOjAh}/`. The successful physical runner removed its temporary trace/settings directory, so its raw receipt remains in the tool transcript. This is recorded-participant cleanup, not a universal descendant or abrupt held-input death guarantee.
|
|
734
|
+
|
|
735
|
+
### Known-held input release
|
|
736
|
+
|
|
737
|
+
On 2026-11-02, the existing worker request interface and disposable editor fixture passed four Windows cases with unchanged production input/control code: Ctrl held at cancellation, Ctrl held at target-disable error, left mouse button held at cancellation, and left button held at owned source-handle replacement. A passive fixture hook accepted only the agent marker on the owned foreground target and independently checked Windows held state during a later event before synchronously triggering interruption. No clipboard, daily document, production delay or new public tool was involved.
|
|
738
|
+
|
|
739
|
+
Both cancellation responses were `COMPUTER_USE_STOPPED`; both target failures were `TARGET_IDENTITY_CHANGED`. Every case required `cleanupConfirmed: true`, independent OS key/button release, successful operation settlement, exclusive control false, zero listener-held counters and observed worker exit. All fixture processes exited normally; their executable was removed and metadata-only reports retained. Evidence: `/tmp/pi-cu-held31/{run.log,source.json}` and the reported Windows fixture directory's `result.json`. This establishes #31's known-held cancellation/error clause, not abrupt-owner-death cleanup or the [remaining locked-target/session investigation](#lock-safety-scope-and-prior-attempts). WSL shortcut and handback passed in their named receipts above. Two-axis review corrected the initial asynchronous trigger and control-retirement gating before any input run.
|
|
740
|
+
|
|
741
|
+
## Paired browser-form comparison
|
|
742
|
+
|
|
743
|
+
Run `npm run test:browser:comparison -- /path/to/dsh-computer-use-win edge 3` from WSL2 under the shared live-test lock. The command relays to the private Windows Node, uses the same explicit installed executable for both engines, and runs the existing local browser-actions server's form route. It creates isolated headless profiles and disposable settings; no physical pointer/keyboard, clipboard or daily profile is used. `PI_CU_RELEASE_OUTPUT` retains `browser-comparison.json`, including nonzero-result evidence through the WSL relay.
|
|
744
|
+
|
|
745
|
+
The outcome oracle is the fixture application's submitted HTTP payload plus the visible confirmation read through normal tools. Tests do not fill fields through injected page JavaScript. Each navigation resets the fixture's receipt state, and each engine starts in a new browser/controller. The workflow reads/fetches IDs, inspects restricted fields without editing them, focuses/types/chords into Name, sets multilingual Notes and selection/checkbox values, clicks Submit, waits for the receipt, invokes a delayed result, scrolls, captures a PNG and rejects an old ID after navigation. The report retains page-change evidence and before/after native foreground, pointer and last-input tick.
|
|
746
|
+
|
|
747
|
+
On 2026-10-30, reference **0.5.3** and Pi **0.1.0** passed **three alternating pairs (six workflows)** using installed Edge **156.0.4314.50**, Windows Node **22.23.4**, driven from WSL2. Every independent payload matched `Pi 中文 café 😀`, the exact two-line Notes, accepted=true and choice=beta. Delayed waits were observed, restricted values were inspected before input, screenshots were PNGs of width 400, old references were rejected after navigation and native foreground/pointer/input ticks were unchanged. Controller/fixture exit and owned-folder removal were confirmed. The final assertion check additionally records positive page-scroll movement, requires a stale/document error rather than any generic failure, and verifies each owned process's actual executable/version and headless command-line flag.
|
|
748
|
+
|
|
749
|
+
A review found that the original `valuesPreserved` report was based only on the initial inspection. The workflow now re-finds both restricted controls and reads their values through public element_info after form actions, scrolling and screenshot, before navigation destroys the document. It records literal initial/post-action values and sets `valuesPreserved` only after both post-action values equal their originals. Run `npm run test:browser:comparison:oracle -- /path/to/dsh-computer-use-win edge --filled` to check this evidence and phase in both engine reports; this check first failed on the missing post-action evidence. A targeted paired rerun on 2026-10-30 passed for both engines: each fresh post-action observation returned exactly `Disabled value` and `Read-only value`, and cleanup was confirmed. The earlier six runs do not establish this post-action preservation result.
|
|
750
|
+
|
|
751
|
+
The deliberate `--verify-unfilled` mode established red before the workflow: both engines submitted the known empty/default payload, and exact payload assertions failed. It is labelled `diagnosticInjection: true` with a test-defect cause and kept separate from ordinary results. `test:browser:comparison:oracle` verifies both deliberate failures, their actual payloads, nonzero CLI status and cleanup through the public command. An earlier new-runner attempt observed Pi `spawn UNKNOWN` once; the existing root headless fixture passed, the failure did not recur in subsequent paired runs, and its cause remains unknown. Another early assertion incorrectly required the same disabled metadata from each engine's element_info; this was a test defect corrected by using each engine's public find/info evidence. These attempts are retained in the local evidence directories rather than counted as successful runs.
|
|
752
|
+
|
|
753
|
+
Observed semantic differences remain visible: DSH returns compact diff page changes, whereas Pi returned full page changes in this fixture. At the time of this baseline, DSH element_info exposed disabled but not readonly; Pi's find/tree exposed both while element_info omitted those flags. A later Pi change added disabled and readonly metadata to element_info; an isolated headless Edge fixture verified editable, disabled, readonly, aria-disabled and aria-readonly inputs through registered Pi tools. The known restricted controls were inspected without attempting to edit or bypass them. This does not establish equivalent reference output or real-agent behavior.
|
|
754
|
+
|
|
755
|
+
This is a paired **tool/backend** baseline, not a DSH or Pi model/session benchmark. It establishes the named headless Edge form workflow. The following advanced-browser baseline covers additional navigation, transfers, profiles and browser combinations; visible/native-dialog focus, real-agent recovery and physical input retain their existing release gates. User input during a run can invalidate foreground/pointer preservation attribution; retain the observations rather than assuming an engine caused any change.
|
|
756
|
+
|
|
757
|
+
## Paired advanced-browser comparison
|
|
758
|
+
|
|
759
|
+
The existing `test:browser:comparison` runner accepts `--advanced` after its reference path, browser and repetition count, or `--profiles` for the separate synthetic-cookie lifecycle workflow. For example, run `npm run test:browser:comparison -- /path/to/dsh-computer-use-win edge 3 --advanced` under the shared live-test lock. `test:browser:comparison:oracle -- /path/to/dsh-computer-use-win edge --advanced` checks the public CLI's exact transfer/dialog/identity evidence. The advanced-report oracle first rejected the old form-only runner because it did not advertise or exercise advanced coverage. An earlier Windows test-copy attempt omitted native assets and failed with `NATIVE_RESOURCE_MISSING`; that was a staging defect, retained separately from product outcomes.
|
|
760
|
+
|
|
761
|
+
The paired workflow navigates to another document and rejects the old element ID, opens and closes a child tab and rejects its old tab ID, handles JavaScript prompt/confirm/alert through normal tools, intercepts a file chooser, and transfers known fixture bytes. The application server independently records uploaded file contents and request count; downloads have a unique fixture filename, their actual disk bytes are checked, and the server must see exactly one download request. Only that exact downloaded fixture file is removed. It then terminates only the discovered owned headless browser root, verifies withdrawal of the old tab, explicitly opens a new context with a different ID, and cancels a passive wait. No uncertain action is automatically replayed.
|
|
762
|
+
|
|
763
|
+
On 2026-10-30 three alternating pairs against installed Edge **156.0.4314.50** passed all six workflows through Pi 0.1.0's public worker and the pinned reference 0.5.3's public MCP backend, using Windows Node **22.23.4** from WSL2. Both initial and replacement browser roots were independently confirmed gone before fixture-root removal. All six sampled desktop foreground/pointer/last-input values were preserved. This is scripted backend evidence; neither the installed DSH host nor any model was exercised. The first earlier pair completed every workflow phase but observed a changed pointer/input tick during the Pi case. Its origin was unproven; current reports classify desktop preservation separately as `preserved` or `inconclusive` rather than attributing such changes to automation while the user is working.
|
|
764
|
+
|
|
765
|
+
A further paired installed Chrome **155.0.8059.85** run passed both advanced workflows with native state preserved. On the official unmodified Firefox **144.0** fixture, Pi passed navigation, tab lifecycle, dialogs, supported disconnect/reconnect and cancellation; upload/download refusals are separate from successful transfers. The reference's file-input value attempt returned `BROWSER_NOT_EDITABLE`, while Pi returned `BROWSER_UNSUPPORTED`; exact messages remain in the report. Reference BiDi provides no download tracking or dedicated download path, so its download action was not dispatched and is explicitly untested. This avoids claiming either a supported transfer or a verified refusal. Firefox popup results lack Chromium's `openedTabs` metadata; fresh public tab discovery found the single new owned URL/ID without replaying the click. The initial metadata-specific assertions were runner defects, retained separately.
|
|
766
|
+
|
|
767
|
+
The reference Firefox disconnect case retained an actual backend limitation: after the owned root was terminated, discovery returned `browserLane.error: BROWSER_DISCONNECTED`, the old tab was refused, and an explicit `new-tab` request also failed with `BROWSER_DISCONNECTED: restart lane after disconnect; mutation replay is unsafe`. That case remains failed and its discovery is inconclusive, not an empty successful listing. No action was repeated, no hidden restart was performed, and the later Firefox-reference browser-wait cancellation step was unexecuted. Pi withdrew the old tab, explicitly created a different context and cancelled the subsequent wait. Reference browser-wait cancellation was established on Edge/Chrome, not inferred for this failed Firefox continuation.
|
|
768
|
+
|
|
769
|
+
The existing Firefox endpoint fixture, with its optional reference-path argument, passed for both backends on the same explicitly owned loopback endpoint: the pre-existing tab, each backend's new tab and synthetic cookie survived disconnect, the external process stayed alive, and neither backend created an owned profile. Reference tab discovery returned empty titles for existing contexts; their fixture URLs established identity and independent browser reads confirmed the actual titles after disconnect. This metadata difference remains recorded rather than being called missing tabs. Automatic Firefox launches remain headless and experimental; visible/native-dialog/account sign-in support is not established.
|
|
770
|
+
|
|
771
|
+
Cancellation retains the different public outcomes: the reference returned an MCP `isError` cancellation text; Pi rejected with `AbortError`. The optional signal in the shared test transport sends standard MCP `notifications/cancelled`. A separate harmless nonexistent-method regression demonstrated that a pre-aborted signal previously dispatched a request (actual RPC method-not-found response); it now rejects the original abort reason before writing a request. `test:reference:transport -- /path/to/reference --cancel-wait` additionally verified active passive-wait cancellation in about 213 ms, preserving its raw error. This is not DSH's web stop button or physical key/button cleanup.
|
|
772
|
+
|
|
773
|
+
The profile mode runs one complete paired lifecycle per command (repeat the command for a new root), using installed Edge, Chrome or experimental Firefox. It uses an HTTP-only synthetic cookie and a new dedicated storage root for each engine. It records live contender results, closes all fixture-created controllers, independently samples old/new browser process IDs around reconnect, and distinguishes browser restart from attaching to a surviving kept browser. Temporary-cookie isolation, directory existence after controller exit, browser liveness and removal on the next launch are separate fields. A failed cleanup expectation remains a finding and a nonzero CLI outcome even when later isolation checks succeed. Real account sign-in, visible native dialogs, physical input, idle/crash branches not rerun here, Firefox forks/ESR and real-agent recovery retain their existing release gates.
|
|
774
|
+
|
|
775
|
+
The final paired Edge profile report established actual browser restarts in both engines: the old kept-browser root was independently dead before reconnect, a different root PID opened, and the synthetic cookie persisted. The reference shared its live dedicated browser with the second MCP client; Pi refused the contender with `BROWSER_PROFILE_BUSY` after the first operation ended normally. Both temporary contexts started without the kept cookie and lost their own cookie across restart. Reference's temporary browser was dead, its controller exited normally (code 0, no termination signal) and all fixture-created controllers were closed, but its temporary directory remained after 10 seconds. It disappeared on the next launch. This remains a failed cleanup finding and a nonzero runner result; it is not blamed on a forced transport shutdown. Pi removed its temporary directory before runner cleanup. All tracked owned browser roots were gone before final fixture-root removal. The public `test:browser:comparison:oracle -- /path/to/reference edge --profiles` passed its reporting contract while preserving that reference failure.
|
|
776
|
+
|
|
777
|
+
Focused paired profile coverage also ran on installed Chrome **155.0.8059.85** and official unmodified Firefox **144.0**. Chrome matched the Edge distinction: reference shared its dedicated live browser and later left a dead temporary directory until next launch; Pi refused the contender and removed temporary storage before runner cleanup. Both Firefox backends refused the live contender and passed kept-cookie persistence across proven browser restarts, temporary cookie isolation and immediate temporary-directory cleanup. In every focused Edge/Chrome/Firefox case, the original tab remained readable and its same root PID remained alive after the contender disconnected. These are headless synthetic-cookie checks, not real sign-in or visible Firefox support claims.
|
|
778
|
+
|
|
779
|
+
Review found that the first profile collector merely recorded restart predicates and could still claim persistent cookies after a controller-only reconnect. It now requires both independently observed old-root exit **before** reconnect and a different new root PID before setting `cookiePersisted` or marking the kept-restart step passed. A missing predicate produces a retained `kept profile restart` finding and a failed step; cookie observation across controller reconnect is recorded separately. Safe temporary-isolation checks continue, and later cleanup findings append rather than overwrite the restart finding. After the competing controller detaches, fresh public tree/discovery observations and an OS liveness probe must also prove the original tab remains readable in its original browser root before that owner closes.
|
|
780
|
+
|
|
781
|
+
The public reporter accepts saved evidence with `--report <browser-profiles-comparison.json> --exit-code <recorded CLI status>`. Add `--verify-restart-gaps` to `test:browser:comparison:oracle` with `--profiles` and a saved report to run labelled diagnostic counterexamples. The weak checker accepted false old-exit/same-root reports before the fix; the corrected checker rejects an alive old root, a same PID, and a contradictory different-root flag. It also accepts a truthful nonpassing restart finding while preserving independent temporary coverage. These synthetic report diagnostics are distinct from live browser results.
|
|
782
|
+
|
|
783
|
+
A subsequent review found that the restart catch treated stop/cancellation and uncertain cleanup as ordinary recoverable findings. Those errors now retain their interruption evidence and propagate to the outer halt before any new controller or temporary-tab work; later engine cases are blocked. `AbortError`, textual stop/cancellation, cleanup-unconfirmed errors and structured `cleanupConfirmed: false` are halt conditions. The advanced workflow's deliberately handled final per-call cancellation remains a separate, explicit case.
|
|
784
|
+
|
|
785
|
+
Run `test:browser:comparison:oracle -- /path/to/reference edge --verify-profile-interruptions` for the labelled kept-reconnect diagnostics. Each injects a test-only interruption immediately before new-tab dispatch; a diagnostic guard prevents any real post-fault controller launch even if the collector regresses. The red run recorded one forbidden controller attempt after the broad catch swallowed the stop. The corrected checker requires zero attempts, no temporary-profile work, retained original interruption evidence and a blocked later case for stop, cancellation, `AbortError`, textual cleanup uncertainty and structured cleanup failure. These headless synthetic fault cases do not claim native key/button release or DSH host stop-button acceptance.
|
|
786
|
+
|
|
787
|
+
The live runs use a private Windows-readable copy of the worktree's tests, built worker, native assets and locked runtime dependencies. Windows Node cannot follow the worktree's absolute Linux dependency symlink. Source/copy hashes are recorded with the local evidence; the copy is removed afterward. No production code, daily profile, live-model request, physical input or clipboard mutation is part of this baseline.
|
|
788
|
+
|
|
789
|
+
### Consolidated Chromium tool acceptance
|
|
790
|
+
|
|
791
|
+
The #16 tool deliverable and transferred #15 criteria are accounted for separately from #36 real-model workflows and the remaining release/manual gates. Existing trustworthy results are reused where production paths are unchanged; the 2026-10-31 Chrome headless recheck covered current shared restriction/focus guards, stale IDs and reconnect. The added launch-failure case passed through registered Pi tools without production changes.
|
|
792
|
+
|
|
793
|
+
| Criterion | Named evidence |
|
|
794
|
+
| --- | --- |
|
|
795
|
+
| Installed Chrome/Edge and background behavior (#15.1) | Corrected named-browser read/action runs and focused visible Edge foreground evidence in [browser validation](browser.md#validation); current Chrome headless read/guard/lifecycle pass. |
|
|
796
|
+
| Both browsers, native/WSL paths, disconnect, cleanup and startup failure (#15.4) | Chrome/Edge WSL-controller read/actions and profile runs; native Windows Node Edge profile fixture through registered Pi tools; read fixture disconnect/reconnect; `test:browser -- edge --headless --startup-failure`. |
|
|
797
|
+
| Actions, JavaScript dialogs and explicit waits (#16.1) | `browser-actions-host.mjs` Edge/Chrome action results, paired form evidence and current shared-guard regressions. |
|
|
798
|
+
| Transfers, tab effects and post-action observations (#16.2) | Paired advanced Edge/Chrome known upload/download bytes and exactly-once server requests, new/closed tabs and returned page changes. |
|
|
799
|
+
| Targeting, serialization, cancellation and honest results (#16.3) | Stale/root identity checks in read/advanced fixtures, worker/ownership ordering regressions, actual passive-wait cancellation and same-operation refusal/new-operation recovery. |
|
|
800
|
+
| Navigation, overlays, dialogs, transfers and failure paths (#16.4) | The existing read/action/advanced fixtures plus the named launch-failure case. |
|
|
801
|
+
|
|
802
|
+
The launch-failure executable is an owned .NET fixture that records its PID and exits 42 without launching children. The public result reports `BROWSER_PROFILE_RETAINED` and no browser session. Independent process checks prove the fixture and worker exited before test-only storage removal; removal is checked afterward. Unknown launch ownership remains conservatively retained in production. Earlier fixture `taskkill` and staging failures remain recorded; this acceptance does not erase them. No physical input, daily profile, real-model result or unrestricted application coverage is inferred.
|
|
803
|
+
|
|
804
|
+
### Cooperative worker cleanup control
|
|
805
|
+
|
|
806
|
+
A 2026-10-31 no-input Edge lifecycle pinned the actual worker process handle before disposal and independently observed its Windows exit code. Each fresh profile had a positive command-line-prefix control matching eight owned browser processes before disposal; subsequent scoped samples found no matching live processes.
|
|
807
|
+
|
|
808
|
+
| Candidate / existing shutdown exit grace | Disposal return | Worker exit | Temporary profile |
|
|
809
|
+
| --- | --- | --- | --- |
|
|
810
|
+
| Before correction, default 1000 ms | 435 ms | 0 | Empty |
|
|
811
|
+
| Before correction, deliberately short 1 ms | 285 ms | 1 | Retained across 15 seconds of samples |
|
|
812
|
+
| Before correction, ample 10000 ms | 430 ms | 0 | Empty |
|
|
813
|
+
| Cooperative protocol, 20 ms exit grace | 417 ms | 0 | Empty |
|
|
814
|
+
|
|
815
|
+
The short control proves premature retirement can produce the residue class. It does not establish whether the earlier 1003 ms disposal was forced; that historical exit signal was not observed. The repair uses shutdown-start/complete/failure notifications and the existing operation deadline, rather than a fixed wait. Red/green WorkerClient cases reproduced incomplete cleanup beyond exit grace, repeated-disposal retention and lost uncertainty after process exit. Additional regressions cover cooperative timeout, out-of-order notices/silent-peer bounds and physical input-state precedence; the existing stop/replacement test remains unchanged and passes. Controlled workers only emitted messages; no native input or clipboard access occurred. The live post-correction sample found worker exit 0, no matching live browser processes and empty profile storage. Local controlled evidence is `/tmp/pi-cu-dispose18-live/control-{1000,1,10000,20}.json`. The controlled live-browser recovery check above now complements this cleanup evidence; interactive sign-in and broader release obligations remain open.
|
|
816
|
+
|
|
817
|
+
## Pointer comparison preparation
|
|
818
|
+
|
|
819
|
+
Historical preparation boundary; see the later [dedicated-session evidence](#dedicated-physical-comparison-evidence).
|
|
820
|
+
|
|
821
|
+
Ticket #30 preparation adds a safe WSL `npm run test:native:pointer:physical -- --list` plan and an optional pinned-reference backend to the existing runner. Portable subprocess tests copy the runner alone into a fresh directory: Pi/reference listing succeeds without build/resources, both execution modes refuse without desktop opt-in before backend import or fixture creation, invalid options fail, and no extra files appear. The original test failed on the static missing-backend import, then passed after moving startup behind the gate.
|
|
822
|
+
|
|
823
|
+
At this historical compile-only stage, the safe CLI boundary and both modified Windows fixtures compiled successfully; neither binary was executed. No fixture, clipboard access or native input occurred. The counter/hover/button-release oracle and physical branches were then unvalidated, and #30 remained open. Later [Pi pointer acceptance](#scoped-pointer-and-restoration-acceptance) and [workspace decision acceptance](#workspace-decision-acceptance) record the completed supported scope; the old preparation is not the current queue.
|
|
824
|
+
|
|
825
|
+
## Dedicated physical-input runners
|
|
826
|
+
|
|
827
|
+
These runners require **Windows Node on a dedicated interactive test desktop**. A WSL `npm` command normally runs Linux Node and is not the right entry point. Build the checkout and call the health tool once to provision the verified private runtime. Then open Windows PowerShell on the dedicated desktop, change to the built checkout, read the runner sources, and use the tested Windows x64 runtime:
|
|
828
|
+
|
|
829
|
+
```powershell
|
|
830
|
+
$piCuRuntime = Join-Path $env:LOCALAPPDATA 'pi-computer-use\runtime\node-22.23.4-win-x64\node.exe'
|
|
831
|
+
$env:PI_CU_DEDICATED_INPUT_DESKTOP = '1'
|
|
832
|
+
try {
|
|
833
|
+
& $piCuRuntime .\tests\native-pointer-physical.mjs
|
|
834
|
+
if ($LASTEXITCODE -ne 0) { throw 'Pointer checks failed; stop and inspect the output.' }
|
|
835
|
+
} finally {
|
|
836
|
+
Remove-Item Env:PI_CU_DEDICATED_INPUT_DESKTOP
|
|
837
|
+
}
|
|
838
|
+
```
|
|
839
|
+
|
|
840
|
+
This path matches the tested runtime pin in this release; use the package's verified runtime if that pin changes. The pointer command sends real input. The legacy `native-text-physical.mjs` runner now refuses execution before loading a backend: its old fixture overwrote the original clipboard and could retire an unsettled input owner. Use the ownership-aware OLE runner for supported clipboard checks; it does not establish cancellation acceptance. Record results alongside the remaining manual checks below; passing scripted cases alone is not full acceptance.
|
|
841
|
+
|
|
842
|
+
## Manual release gates
|
|
843
|
+
|
|
844
|
+
Only genuinely human/environment-dependent Pi checks belong here; automated failure cases stay with their capability owners. Reuse the accepted native Pi Esc and existing physical/interference evidence. A shared prepared session may satisfy several issues; no DSH side-by-side work is required.
|
|
845
|
+
|
|
846
|
+
- [x] Actual native Windows Pi-host physical Esc: canonical input stop/cleanup, operation release, stable partial text, no leaked Esc, held state zero and clean exit. See [receipt](#exclusive-control-candidate).
|
|
847
|
+
- [x] #31 shared control: [actual WSL Pi shortcut](#wsl-pi-physical-shortcut) and [scoped human editing/explicit continuation](#wsl-pi-human-handback-and-continuation) passed; reuse these results.
|
|
848
|
+
- [x] #31: [control interruption/cleanup acceptance](#control-interruption-acceptance) reconciles the scoped passes; no additional lock/unlock cycle is required. Broader text/restoration/presentation cases retain their own #26/#30/#20 scopes; do not repeat accepted shared steps.
|
|
849
|
+
- [x] #6/#20: actual available scaling and changed-arrangement checks passed; #6 practical first-release scope accepted, with unavailable configurations recorded. #20 local Snipping Tool visibility phases were human-confirmed; [composed acceptance and limits](#snipping-tool-recording-acceptance). Display restoration and its vertical alignment difference remain recorded.
|
|
850
|
+
- [x] #18: [GitHub sign-in persisted across Pi restart](#manual-github-remembered-sign-in), confirmed privately by the user; owned processes/locks retired and test storage removed.
|
|
851
|
+
- [ ] #2: clean package installation outside the development tree in a disposable Windows/WSL-capable environment. This remains user-deferred; do not repeatedly request a guest or modify the user's host virtualization setup.
|
|
852
|
+
- [ ] #21: final user acceptance of the supported Pi workflows and documented limitations after agent-owned gaps are resolved.
|
|
853
|
+
|
|
854
|
+
Clipboard contention/exclusion/copy acceptance is complete in #27. Scoped OCR availability/language/cancellation and targeting/provider acceptance are complete under #7/#28; they do not become manual DSH tasks. Closure/disposition is recorded by each owner and reconciled by #21.
|
|
855
|
+
|
|
856
|
+
## Review trace and evidence
|
|
857
|
+
|
|
858
|
+
Independent review at integration `3771e77` separated Standards and Spec axes. Standards found no hard rule breaches and two judgement calls (duplicate guarded-input lifecycle and obsolete optional native-source handling). Spec found user-interference restoration and browser key-alias gaps. Root additionally identified popup targeting/drag activation parity cases. Corrective work landed in `5fd9d12` and `29a8a13`, merged as `a7ae50f`. Independent re-review of that candidate reported **Standards: zero unresolved findings; Spec: zero unresolved findings**. Physical restoration/drag acceptance remains pending even after passive fixes and clean reviews.
|
|
859
|
+
|
|
860
|
+
Initial production preflight at `b988e86` passed real Pi CLI health/list execution and cleanup on both hosts using a production omit-peer install. Updated checked-in runners must be rerun against the final corrected integration before release. See the generated sanitized reports for exact versions/timings rather than promoting historical successful runs into current full-parity evidence.
|
|
861
|
+
|
|
862
|
+
Validation slice evidence on 2026-10-29, before the corrective branch: `npm run check` passed 42 portable tests plus type/lint checks; the package link regression went from 19 missing links to passing; reference declarations matched all 25 tools and supported parameter fields, with only reported additional signed-32-bit movement bounds. The checked-in real Pi CLI runner passed its production omit-peer package from both WSL2 and native Windows processes, including settlement and confirmed worker exit. These checks use Pi 1.4.0, Windows Node 22.23.4, Windows 11 x64 and WSL2 Ubuntu.
|
|
863
|
+
|
|
864
|
+
The three-sample same-machine background benchmark produced these means (milliseconds):
|
|
865
|
+
|
|
866
|
+
| Measurement | Reference 0.5.3 | Pi 0.1.0 |
|
|
867
|
+
| --- | ---: | ---: |
|
|
868
|
+
| Process-cold health | 2141.68 | 390.52 |
|
|
869
|
+
| Process-cold native-ready find | 2752.56 | 1064.14 |
|
|
870
|
+
| Warm find | 183.16 | 25.28 |
|
|
871
|
+
| Background set_value dispatch | 146.97 | 11.14 |
|
|
872
|
+
| Find → set_value → observed value | 349.86 | 28.51 |
|
|
873
|
+
|
|
874
|
+
Environment: same private Node executable and AMD Ryzen 9 7940HS/Windows build 26200; alternating engine order, warm compilation/runtime caches. These numbers support only the benchmarked background-edit path; they are not whole-product speedups, installation-cold measurements or physical/browser/model-driven workflow evidence. Rerun the checked-in harness after corrective changes rather than extrapolating these samples.
|
|
875
|
+
|
|
876
|
+
Seventeen serialized passive suites also passed on this validation slice: native health/windows/accessibility/capture/OCR/controls/waits/window-management/pointer-guards/text, cross-host ownership/stopping/settings/offscreen indicators, and headless Edge reads/actions/profiles. These are the named configured runners in the coverage map; Chromium/Firefox cross-browser results from their feature slices remain documented in [browser validation](browser.md), and must be rechecked where corrective changes affect them.
|
|
877
|
+
|
|
878
|
+
## Corrected-candidate rechecks
|
|
879
|
+
|
|
880
|
+
Against `a7ae50f` on 2026-10-29, configured type/lint checks and 42 portable tests passed, the production package's 83 entries had no broken documentation links, and schema comparison still matched all 25 reference tools/parameters. Real Pi CLI loading and health/list execution passed again from both WSL2 and native Windows processes with dev/peer dependencies omitted, empty stderr, final settlement and confirmed worker exit. This remains a clean package install on the existing machine, not a clean-OS or physical acceptance claim.
|
|
881
|
+
|
|
882
|
+
Representative Firefox 144.0 read/actions and external-endpoint preservation passed using the official unmodified executable staged on the Windows local filesystem. A previous attempt to spawn its UNC-extracted executable failed before browser actions; it was not accepted as a product result. Shared Chromium-only cue assertions were corrected in the action fixture so Firefox's documented lack of cues is tested rather than dereferenced as an assumed Chromium capability. Full Firefox actions, including the restored key aliases, and external process/tab preservation then passed.
|
|
883
|
+
|
|
884
|
+
Targeted corrected native controls, same-process popup guards, background text and window management passed without physical input or clipboard mutation. These checks supplement the earlier passive batch; the entire batch was not repeated without a new concern.
|
|
885
|
+
|
|
886
|
+
Corrected headless Edge actions also passed. Because shared activation/restoration code changed the timed path, the same three-sample benchmark was rerun: reference/Pi means were health **2233.11/389.47 ms**, native-ready **2860.27/1028.12 ms**, warm find **205.20/25.53 ms**, direct background dispatch **151.65/12.55 ms**, and verified workflow **355.06/28.65 ms**. The methodology and limitations above are unchanged; no broad performance or physical-workflow claim follows from these fixture samples.
|
|
887
|
+
|
|
888
|
+
### Focused visible foreground diagnosis
|
|
889
|
+
|
|
890
|
+
Run `npm run test:browser:foreground` with Windows Node after building, serialized with other live fixtures. It starts an isolated visible Edge profile and samples foreground HWND/PID/process plus last-input tick before opening, after opening/reading/value-setting/nonmodal click, after settlement and after disposal. PowerShell probe windows are hidden and their unused stdin is closed; probe PIDs are included to expose console contamination. No native dialogs, physical input, clipboard actions or daily profiles are involved.
|
|
891
|
+
|
|
892
|
+
The corrected candidate retained the **same original foreground HWND/PID and last-input tick through every sampled stage**; the owned browser PID and each probe PID were different. Classification: `preserved`. The previous broad visible fixture's HWND change was not reproduced in this controlled case. Its earlier cause is not proven to be a product defect, a probe console or user/native-dialog interference; do not infer a general cause from the focused pass. Human visual cues, dialogs and broader visible foreground acceptance remain manual gates.
|
|
893
|
+
|
|
894
|
+
## Unicode comparison preparation
|
|
895
|
+
|
|
896
|
+
Historical preparation boundary; the later [dedicated session](#dedicated-physical-comparison-evidence) supersedes the unrun status for executed cases.
|
|
897
|
+
|
|
898
|
+
Ticket #26 preparation on 2026-10-30 extends the existing uniquely named Notepad-file runner to select Pi worker or pinned-reference MCP. `npm run test:native:notepad:unicode -- --list` prints the six cases on WSL without Windows interop, desktop opt-in, resources, backend startup or applications. Portable CLI tests cover listing and refusal without opt-in, including a nonexistent reference checkout. No physical opt-in was set and no Notepad/input/clipboard operation was run. The physical Pi/reference branches remain **unvalidated**, and #26 remains open.
|
|
899
|
+
|
|
900
|
+
The runner records each case's seed, requested/observed/saved text, engine, method diagnostics, elapsed time, raw dispatch and owned cleanup. Acceptance compares exact normalized text and saved bytes, without requiring a 50 ms delay or Pi-specific method label. It never retries uncertain input and saves/closes only its uniquely named files after checking current tab identity. This preparation supplies neither root-cause evidence for pacing nor app/IME/focus environment capture or event-construction experiments; those remain dedicated-session work. Historical regression runs below do not establish reference parity or necessity of the workaround.
|
|
901
|
+
|
|
902
|
+
## Notepad Unicode acceptance regression
|
|
903
|
+
|
|
904
|
+
On 2026-10-29, explicit `sendinput` typing reproduced corrupted text in installed modern Notepad while a standard WinForms editor received the same string correctly. The opt-in [Notepad regression](text.md#notepad-unicode-regression) failed on the original source, then passed with cancellable 10 ms pacing for the exact acceptance string and a longer ASCII/CJK/accent/emoji sequence. UIA values and independently saved test-file bytes agreed. Only uniquely named temporary test tabs/files were edited, saved and closed; the clipboard and existing documents were untouched. This is targeted worker-interface evidence, not a completed Pi-session retest or proof that automatic activation, physical Esc, clipboard restoration and all other physical-input paths pass.
|
|
905
|
+
|
|
906
|
+
Follow-up on 2026-10-29: the Pi-session append test disproved the sufficiency of 10 ms pacing: characters were corrupted and a leading LF was dropped. The expanded installed-Notepad regression reproduces that seeded append failure on the prior source. Enter/Tab mapping, acceptance of whitespace-only input, and cancellable 50 ms spacing replace the earlier workaround. The regression now includes whitespace-only strings, seeded append, mixed Unicode, and LF/CR/CRLF/Tab cases and historically checked the actual helper delay in its result (the current comparison records it as diagnostics rather than an acceptance requirement). All six expanded cases passed three consecutive runs (18 case checks), including comparisons against saved bytes; portable tests and existing native text/stop-control checks also passed. This remains a compatibility workaround requiring Pi-session acceptance, not proof of universal input correctness.
|
|
907
|
+
|
|
908
|
+
## Pi clipboard contention and privacy acceptance
|
|
909
|
+
|
|
910
|
+
Issue #27 is accepted on 2026-11-02 through the real Windows Pi worker and the existing owned OLE fixture. Production code was unchanged; prior rich/OLE preservation, standard virtual-file refusal and newer-copy results are reused.
|
|
911
|
+
|
|
912
|
+
| Case | Independently checked result |
|
|
913
|
+
| --- | --- |
|
|
914
|
+
| `--probe-locked-backend` | An owned lock holder and a separate contender proved contention before/after the actual call. Pi returned `CLIPBOARD_BUSY` in 720.5 ms with native/clipboard cleanup confirmed and `clipboardRestoreOutcome: unchanged`. Lock release confirmed an unchanged sequence; the seed survived and the editor stayed blank. |
|
|
915
|
+
| `--case privacy-handback` — exclusion | During the real paste, the consumer observed the transaction format plus zero DWORD values in all three Windows exclusion formats. Exact editor text and the original synthetic seed were checked separately. Windows reported history enabled and roaming disabled. This validates the [documented Windows exclusion contract](https://learn.microsoft.com/en-gb/windows/desktop/dataxchg/clipboard-formats); history contents and cross-device synchronization were not inspected or claimed. |
|
|
916
|
+
| `--case privacy-handback` — copying after release | Successful operation settlement and health proved control/held counters released before the owned application copied newer text. It survived an idle interval and a subsequent paste under a distinct operation after fresh targeting; exact appended editor text and the newer copy were independently checked. #31 supplies the separate real-human handback evidence; this case does not claim a new physical Ctrl+C test. |
|
|
917
|
+
|
|
918
|
+
The fixture privately preserved the starting clipboard, seeded only disposable content, restored the original after confirmed backend cleanup and exited normally. Unsupported originals still refuse before seeding; uncertain input or fixture commands retain their owners. Logs: `/tmp/pi-cu27-locked-backend2.log`, `/tmp/pi-cu27-privacy-handback.log`, and metadata-only `/tmp/pi-cu27-history-status.json`. No personal clipboard payload/history was logged; no history/roaming setting was changed. These cases satisfy the issue's locked **or** delayed backend, exclusion-contract and copying clauses without a universal clipboard-provider or cloud-service guarantee.
|
|
919
|
+
|
|
920
|
+
The first locked run returned the correct busy/cleanup result but failed an extra four-second fixture cutoff while its five-second lock was still held; the unsupported stricter cutoff was corrected, with the original log retained in `/tmp/pi-cu27-locked-backend.log`. A separate delayed-provider experiment did not establish concurrent delayed-backend timeout coverage: two attempts completed a valid restored paste, one failed compilation before starting, and a later 347 ms report could not attribute asynchronous provider entry to the backend call. That report is not used for acceptance. The unproved delayed fixture/STA experiment was removed; `/tmp/pi-cu27-delayed-render*.log` retains the investigation. The measured locked-backend case satisfies the required bounded-failure alternative; no mandatory internal snapshot-timeout or explicit-cancellation claim is added.
|
|
921
|
+
|
|
922
|
+
## OLE clipboard acceptance regression
|
|
923
|
+
|
|
924
|
+
On 2026-10-29, an ordinary Unicode-text OLE clipboard reproduced `CLIPBOARD_SNAPSHOT_UNSUPPORTED` because the helper rejected OLE transport markers without examining the public FORMATETC descriptors. A synthetic OLE clipboard through the normal worker reproduced the same failure. The corrected helper validates public OLE formats, excludes process-bound transport markers, and duplicates all preservable native payloads. The regression also exposed sequence changes during format synthesis that previously caused restoration to be skipped; hidden-owner plus transaction-nonce checks distinguish that case from a genuinely newer copy. The opt-in [OLE clipboard regression](text.md#ole-clipboard-regression) passed actual paste, Unicode/HTML/binary preservation, indexed-format refusal before input, and synthetic newer-copy preservation. That was the historical worker-fixture checkpoint. The later [#27 clipboard acceptance](#pi-clipboard-contention-and-privacy-acceptance), composed with [#31 human handback](#wsl-pi-human-handback-and-continuation), completes the scoped requirement; no repeat user clipboard-preservation test is queued.
|
|
925
|
+
|
|
926
|
+
Historical preparation update, 2026-10-30 (#27), before the later dedicated sessions: the existing OLE runner now selects the normal Pi worker or pinned reference MCP engine through the shared test adapter. Portable public CLI checks pass for plan/list output, rejected unknown flags, and both engines refusing execution without the opt-in before backend imports or fixture files. The fixture's future-run oracles compare exact editor text independently with UIA, verify Unicode/HTML/binary and indexed payload preservation, and check the synthetic newer copy. Raw results/errors remain available; Pi-only restoration labels/counts are diagnostics rather than mandatory DSH assertions. These are preparation checks only: no clipboard was read or changed, no native fixture was compiled/launched, and no paste/input/restoration was run. Paired physical outcomes and the broader clipboard matrix remain deferred; #27 stays open. See [runner scope and prerequisites](text.md#ole-clipboard-regression).
|
|
927
|
+
|
|
928
|
+
## Locked-session diagnosis
|
|
929
|
+
|
|
930
|
+
On 2026-10-29 the live activation probe observed LockApp in the foreground, `AttachThreadInput` access denied, and WTS session flag 0 (locked). The generic foreground-refusal result was replaced with explicit `DESKTOP_SESSION_LOCKED` refusal before activation and physical pointer/text input. The opt-in [locked-session regression](windows.md#locked-session-refusals) reproduced the prior misleading result, then passed activation/movement/text refusal, cleanup and quiet observation on its disposable fixture. This does not establish the cause of every earlier refusal; the unlocked acceptance-bench retest and foreground-restoration checks remain pending.
|
|
931
|
+
|
|
932
|
+
## Unlocked foreground correction
|
|
933
|
+
|
|
934
|
+
On 2026-10-30, an unlocked VS Code → Notepad transition succeeded but the warm-helper return failed. Instrumentation showed input-thread attachment succeeded and SetForegroundWindow still returned false. The reference's BringWindowToTop step was missing from the attached fallback. Adding it (with a fresh ownership check before the second foreground request) corrected that live transition without injecting keys or changing lock/input guards. The [unlocked round-trip regression](windows.md#unlocked-activation-round-trips) failed on the prior source, then passed six disposable native/Chrome transitions, independently observed native hover, and return to prior foreground. The user's full acceptance-bench pointer workflow and automatic foreground-restoration cases remain pending.
|
|
935
|
+
|
|
936
|
+
## Dedicated physical comparison evidence
|
|
937
|
+
|
|
938
|
+
On 2026-10-30 the user explicitly authorized an idle, unlocked Windows desktop. Tests ran serially from WSL2 under the live-test lock using Windows Node 22.23.4, Pi 1.4.0, Windows build 26200 and Notepad 11.2607.14.0. Foreground initially belonged to VS Code, not the resident LockApp process. Production source/assets stayed unchanged from the earlier baseline. Private Windows-readable copies of reviewed runners and pinned DSH 0.5.3 / `6fb6421` were hash-verified; local raw evidence is `/tmp/pi-cu-physical-evidence`. This is scripted public-tool/native behavior, not model-driven task acceptance.
|
|
939
|
+
|
|
940
|
+
The initial opt-in did not cross WSL automatically; the runner refused before creating resources or dispatching input. Explicit `WSLENV` forwarding corrected that environment issue. Initial and corrected runs are retained separately.
|
|
941
|
+
|
|
942
|
+
| Coverage | Pi | Pinned DSH | Interpretation |
|
|
943
|
+
| --- | --- | --- | --- |
|
|
944
|
+
| Six Notepad Unicode cases | All six passed exact UIA and saved UTF-8 content, normalizing line endings only | Two whitespace-only cases refused; four mixed-text cases failed exact content/saved-byte checks | Concrete difference; pacing necessity and event-construction cause remain unisolated |
|
|
945
|
+
| Scaled-point click, exact double-click, hover, inner scroll | Corrected fresh-fixture sequence passed | Corrected fresh-fixture sequence passed through scrolling | Initial DSH Y-coordinate failure was runner scale handling; initial Pi hover lacked an explicit foreground precondition |
|
|
946
|
+
| Cancellation after actual drag button-down | Passed, including fixture release and OS button-up | Native backend timed out after 30 seconds; independent OS probe found left button still held | Reference failure retained; no drag replay. Cleanup-only LEFTUP released the button, independently confirmed afterward |
|
|
947
|
+
| Clipboard Unicode/HTML/binary preservation | Exact pasted text and fixture formats passed | Exact pasted text and fixture formats passed | Scoped supported OLE case only |
|
|
948
|
+
| Indexed clipboard preservation/refusal | Initially refused, then fixture check mismatched | Initially accepted, contradicting the runner's refusal expectation | Corrected pre-action seed check fails `QueryGetData` with `80040064` before dispatch. Seed validity is not established; neither initial result proves indexed preservation/corruption |
|
|
949
|
+
| Newer-copy clipboard case | Not reached | Not reached | Blocked by indexed fixture prerequisite; not a pass |
|
|
950
|
+
| Window management | Existing owned-fixture suite passed launch, move, activation, close veto, stale owner, worker survival and honest unresponsive result | Not paired in this session | Scoped Pi regression only |
|
|
951
|
+
|
|
952
|
+
DSH rejects whitespace-only text at `scripts/windows-uia.ps1`'s `IsNullOrWhiteSpace` guard. Test-only commit `d27fece` adds validated `--case=N` selection with original IDs, allowing previously untested cases to start from fresh files without replaying an uncertain action. DSH cases 4–6 independently saved corrupted text matching the UIA observation. Case 3's saved file remained at its original seed while its UIA content was corrupted; this is retained as a failure, not an independently confirmed saved append. Pi reports 50 ms delay, but acceptance no longer asserts that constant. No experiment in this session isolated pacing from batching, control-character mapping or event construction, and no production fix was adopted.
|
|
953
|
+
|
|
954
|
+
The same reviewed correction derives reference vertical coordinates from its documented uniform screenshot scale, verifies actual fixture foreground before hover and polls read-only hover observations without repeating movement. It also checks indexed clipboard payload validity before the tool touches it and reports the failing query stage. The original incorrect fixture result is not relabeled as a product defect. Typecheck, lint and 46 portable tests passed; scoped Standards/Spec review found no blocking issues.
|
|
955
|
+
|
|
956
|
+
Both clipboard fixtures reported original restoration; the corrected Pi run also restored before closing. After the DSH drag timeout, the independent cleanup probe recorded `beforeHeld:true`, dispatched release only, then `afterHeld:false`. Final OS inspection found no held mouse buttons/modifiers and no remaining owned runner/fixture processes. Uncertain DSH Notepad cases retained only their uniquely named disposable files/tabs for inspection; existing user documents were not edited. No physical input was sent after the final cleanup check.
|
|
957
|
+
|
|
958
|
+
### Unicode mechanism probes and clipboard startup — follow-up
|
|
959
|
+
|
|
960
|
+
In a second authorized idle session, the existing six-case runner was extended with isolated test-only source copies. The original Pi/DSH sources remained untouched, and each variant changed exactly one asserted source occurrence. Each run used a fresh owned Notepad file, case 4 (`Pi input check 中文 😀`), exact UIA and saved-byte comparison, and an independent target-thread foreground/focus/keyboard probe. Original/variant SHA-256 values and raw outcomes are retained in `/tmp/pi-cu-followup-evidence`. Windows Node was 22.23.4, Notepad was 11.2607.14.0, target process and foreground/focus process matched, and the target keyboard layout was `0x04040404` (language ID 1028). Legacy IMM context was unavailable; this does not establish TSF or IME state. The helper's compatibility-reported OS version is not the actual Windows build; the independently recorded build remains 26200.9711.
|
|
961
|
+
|
|
962
|
+
| Controlled change | Observed exact case 4 | Interpretation |
|
|
963
|
+
| --- | --- | --- |
|
|
964
|
+
| Unchanged Pi, 50 ms | Pass; UIA and saved UTF-8 matched | Same-session control |
|
|
965
|
+
| Pi delay 50 to 0 ms only | Fail; UIA and saved UTF-8 both `Pi nnput �` | Nonzero pacing protected this one case under this recorded state; 50 ms is not established as the minimum or universal requirement |
|
|
966
|
+
| Unchanged DSH | Fail; UIA and saved text corrupted | Same-session control |
|
|
967
|
+
| DSH Unicode key-up scan 0 to the key-down character only | Fail; UIA and saved text corrupted | This construction change alone did not fix this case |
|
|
968
|
+
| DSH SendInput batch 64 to 2 events only | Fail; UIA and saved text corrupted | This batch-size change alone did not fix this case |
|
|
969
|
+
|
|
970
|
+
The runner now also prepares a read-only [legacy input-context enumeration](https://learn.microsoft.com/en-us/windows/win32/api/imm/nf-imm-immenuminputcontext) for the target thread. Windows compilation passed without executing the probe. Raw API returns are recorded as observations only: focused-context identity and legacy open state remain unknown unless independently established, and this does not establish TSF state. Native execution of the additional probe remains pending.
|
|
971
|
+
|
|
972
|
+
These are single experiments per variant, not statistical reliability claims. Other interactions, timing minima and TSF state remain unresolved; no production delay or event construction was changed. The DSH calls returned success dispatch even though independent text checks failed. Its temporary-directory removal then produced `EBUSY` after the test's text-result record was emitted; those runs independently confirmed their disposable tabs closed but did not establish full temporary-directory removal. Do not treat `ownedCleanupConfirmed` as proof of directory/process cleanup. A reviewed test-only reporting fix now retains both the original failed assertion and a separate bounded cleanup report; it has portable regression coverage, while a fresh Windows `EBUSY` reproduction of the revised reporter remains unrun.
|
|
973
|
+
|
|
974
|
+
The first fixture-only indexed-clipboard probe exited before a window was ready. A subsequent bounded startup diagnostic reported `unsupported-original-value`, `clipboardChanged: false`, no seed and no tool dispatch. The user then supplied a plain-text sentinel. The corrected probe read the payload directly with index 0, but `OleGetClipboard` enumerated the custom format with index -1 and rejected the index-0 query with `80040064`. No tool was called. The fixture restored the sentinel and exited. This establishes an invalid custom fixture precondition, not Pi or DSH corruption. A separately labeled fixture using the documented [FileContents and FileGroupDescriptor formats](https://learn.microsoft.com/en-us/windows/win32/shell/clipboard#cfstr_filecontents) also passed its direct descriptor/bytes check, but its `OleGetClipboard` indexed-content query returned `80040064`; its descriptor was readable. An independent follow-up established that the descriptor and indexed bytes are actually readable via `OleGetClipboard` `GetData` despite `QueryGetData` returning `80040064`. Direct-object query/get also passed. Query is diagnostic rather than definitive evidence that retrieval fails; neither implementation was called during these fixture-only probes. The sentinel was restored and fixture exit confirmed. The subsequent comparison used the real descriptor plus exact `GetData` byte checks before and after each tool action. Pi explicitly refused with `CLIPBOARD_SNAPSHOT_UNSUPPORTED` before input and retained the descriptor/content; its editor remained empty. DSH returned successful dispatch, but indexed content was unavailable from the clipboard afterward (`80040064`); the editor was not independently read after the failed preservation assertion, so exact DSH paste is not claimed for this case. Both fixtures restored the starting sentinel and confirmed exit.
|
|
975
|
+
|
|
976
|
+
An independent newer-copy case used fresh owned fixtures after the indexed probe. Pi pasted the exact Unicode text and the fixture observed its synthetic intervening copy preserved. DSH pasted the same exact text but the fixture observed `newer-mismatch`. Both fixtures restored the starting sentinel and confirmed exit. The test uses a synthetic copy triggered by the owned editor's text change. Reference source `scripts/windows-uia.ps1` restores its saved clipboard object unconditionally in `finally`, without checking clipboard sequence or ownership; that behavior is consistent with overwriting an intervening copy, though the trace does not independently establish precise event timing. Pi's existing helper checks sequence and ownership before restoring. The first Pi attempt stopped before seeding/input because UIA omitted the blank editor value. A test correction records UIA availability without inferring an omitted value and retains the independent fixture text oracle; the corrected run above passed.
|
|
977
|
+
|
|
978
|
+
### Exclusive-control candidate
|
|
979
|
+
|
|
980
|
+
The candidate reuses the stop helper, native interaction guard and existing operation lifecycle; it introduces no new dependency, model-facing tool or ownership controller. Physical acquisition requires an affirmative helper response and a visible local border. Foreign injected/unconsumed input remains guarded; listener exit and explicit protection-loss results block subsequent operation input. Final settlement checks control release before ownership handoff. Human handback uses normal Pi settlement and a new user message, with fresh observation before resuming.
|
|
981
|
+
|
|
982
|
+
Scoped checks on 2026-11-01 and 2026-11-02:
|
|
983
|
+
|
|
984
|
+
| Case | Observed result and limit |
|
|
985
|
+
| --- | --- |
|
|
986
|
+
| Portable regressions | 165 passed, one skipped. Added actual-worker/fake-native cases for refused/unconfirmed acquisition, unconfirmed release, loss of protection and explicitly coordinated listener exit. Build/package/local documentation links passed. |
|
|
987
|
+
| Native Windows and WSL clients with real Windows worker, no input | Acquired protection and border, refused an invalid target, released protection at operation end and blocked the operation after listener exit. The final native runner uses cooperative message-loop exit; an earlier WSL receipt exercised a no-input listener termination. Neither proves cleanup of an active held input or actual Pi-host physical stopping. |
|
|
988
|
+
| Actual native Windows Pi RPC, control acquired without input | The shared physical/preflight launcher loaded the default extension and scripted provider. A fixed invalid target failed before clicking with cleanup confirmed; subsequent health confirmed active hooks/control. Independent OS inspection correlated Pi PID 22956, worker 25764 and the three direct native children with worker spawn receipts, executable paths, birth/parentage and assembly roles (`OwnershipBridge`, `StopBridge`, `WindowsBridge`); the listener PID also matched health. `/computer-stop` cancelled the exact pending wait; its operation released before stdin EOF. Pi exited 0 and all nine recorded participants were absent. No keyboard/mouse/clipboard input was sent. This is orderly-cleanup evidence, not crash containment, physical stop or a real-model run. |
|
|
989
|
+
| Actual native Windows Pi-host exit without input | The same launcher/provider reached the independently identified pending wait after invalid-target cleanup and active-control confirmation. Only the retained Pi host (26468) was terminated; no native helper was forcibly ended. Independent OS polling subsequently found all nine recorded participants absent. This proves one no-input host-exit cleanup path, not held-input cleanup or universal descendant containment; the physical guard was still disabled at that checkpoint. Receipt: `C:\Users\fei\AppData\Local\Temp\pi-cu-stop-preflight-6pcwPi\`; external source hashes/log: `/tmp/pi-cu31-rpc-host-exit{,-source.sha256}` (log suffix `.log`). |
|
|
990
|
+
| Genuine Ctrl+Alt+F9 with attempted physical interference | User typed `abc`, moved the mouse and clicked the disposable editor while agent typing continued. The listener reported 12 suppressed key events, 291 mouse events and one button-down; the editor had zero unexpected characters. The stop returned `COMPUTER_USE_STOPPED` with cleanup confirmed; text stayed at 340/2000 characters, physical-held counts reached zero, same-operation work was refused and a new operation recovered. This is worker/listener evidence on the recorded production sources, not actual Pi/DSH-host acceptance. |
|
|
991
|
+
| Actual native Windows Pi RPC with physical Esc, 2026-11-02 | Both fresh same-launcher prerequisites passed, and independent HWND/PID/parentage checks confirmed the disposable editor foreground. Real Pi 1.4.0 dispatched one finite sendinput request through Windows worker 33736. User Esc produced the matching worker stop event and `COMPUTER_USE_STOPPED` input response with cleanup confirmed; the key did not reach the editor. Text remained at 256/2000 characters with zero unexpected characters. Operation-specific release preceded fresh health with suppression off and physical-held key/button counts zero; independent OS key checks passed. Pi and the coordinator exited 0, the fixture closed, all runtime-checked participants were absent and a separate CIM query found the six directly recorded actor PIDs absent. This accepts one scripted native-Pi physical Esc case, not WSL/DSH-host, configured shortcut or known-held-modifier cancellation. |
|
|
992
|
+
| Teardown of that successful worker case | Worker/listener/fixture exited and fixture directory was removed. A passive Windows console reader remained; only that completed coordinator was retired after independent cleanup proof. The fixture now closes its stdin after resource cleanup; an isolated real-Windows TTY start-gate probe with that closure exited 0 without starting owners. |
|
|
993
|
+
| Fresh Esc setup | Independent foreground was 0, so the start gate was deliberately cancelled before input; fixture/recorded actors exited and directory was removed. Physical Esc on this candidate was not exercised. |
|
|
994
|
+
| Owned drag/drop attempt | Windows refused activation with foreground unavailable before pointer input; dispatch reported cleanup confirmed and the independent fixture reported button-up. The old report incorrectly called cleanup unconfirmed because the objective failed. Its offline regression now separates acknowledged release from task success; unacknowledged/rejected results still retain owners. No drag success is claimed. The retained suppressor exited through normal message-loop cleanup, the native input actor exited, the fixture closed normally, and only the proven passive keeper was then retired; all recorded actors and the disposable directory were removed. |
|
|
995
|
+
|
|
996
|
+
The earlier worker Ctrl+Alt+F9 run's recorded production hashes match candidate `50f634b`; its subsequent fixture-only repairs do not relabel that run as evidence for the later settlement fix. Raw source/result/cleanup receipts: `/tmp/pi-cu31-exclusive-j4l0h39e/`. Recorded-PID absence establishes those actors' exit, not universal descendant containment. Process-tree inspection excludes entries predating their recorded parent lifetime; parent PID alone is insufficient.
|
|
997
|
+
|
|
998
|
+
Actual-RPC receipt: `C:\Users\fei\AppData\Local\Temp\pi-cu-stop-preflight-43urq4\{participants.json,worker.jsonl,result.json}`; source hashes and external runner log: `/tmp/pi-cu31-rpc-preflight-source.sha256` and `/tmp/pi-cu31-rpc-preflight-final.log`. The first attempt failed a fixture assertion that expected the error code without its explanatory suffix. Its normal failure-stop produced matching cancellation, native-input-helper exit and operation release; the passive coordinator was retired only after those receipts were checked, and all six recorded actor PIDs were subsequently absent. That attempt is retained as a failure in `pi-cu-stop-preflight-jADDGs` and `/tmp/pi-cu31-rpc-preflight{.log,-passive-retired.json,-cleanup-probe.json}`. The corrected assertion accepts only the expected error-code prefix. Both attempts used unchanged production sources. The participant-observer regression failed before implementation and passed afterward; final portable checks passed 166 tests with one skipped.
|
|
999
|
+
|
|
1000
|
+
The bounded physical runner now requires both same-launcher preflights fresh in the same invocation, matching source fingerprints and its own participant/setup proof before authorizing one exact finite typing request. The oracle consumes actual worker stop/cleanup, operation release and post-release control state; it rejects SDK-abort-only evidence and leaked stop keys. Portable evaluator controls failed before repair and passed afterward. The default command plan remains importable without a build or SDK resolution; its focused regression caught and corrected eager CLI resolution in the test helper.
|
|
1001
|
+
|
|
1002
|
+
Two starts on 2026-11-01 remained pre-input. In `/tmp/pi-cu31-host-esc-S1DnwC/`, both preflights passed but a missing fixture-spawn import prevented window launch; that import is restored. In `/tmp/pi-cu31-host-esc-komNic/`, both fresh preflights passed, the owned blank fixture opened and independent HWND/PID/parentage checks identified it, but it never became foreground during the start-gate interval. The gate timed out, the fixture closed and no physical Pi-host typing or Esc acceptance is claimed. No input owner was started or forcibly retired in either physical stage. These are retained test-start failures, not product stop failures or passes. Independent CIM checks subsequently found the recorded physical-stage actors absent; the orphaned pre-launch directory from the missing-import attempt was removed after verifying its exact creation identity and test settings. Cleanup receipt: `/tmp/pi-cu31-physical-start-cleanup.json`. At that checkpoint, the manual check still needed a coordinated foreground click followed by Esc after the explicit typing signal.
|
|
1003
|
+
|
|
1004
|
+
**Accepted platform limit, 2026-11-01:** the user chose hooks with documented Windows limits for the first release after the nonelevated `BlockInput` denial (Win32 error 5). [ADR 0003](adr/0003-exclusive-desktop-control.md) records the decision; it does not turn silent hook removal into a passed test or guarantee physical suppression/stop keys after removal.
|
|
1005
|
+
|
|
1006
|
+
On 2026-11-02 the first retry stopped in its no-input prerequisite before any physical test window opened. Cold startup exceeded the fixture's former 20-second initial wait; its normal stop cancelled a queued `operation_end`, which returned `COMPUTER_USE_STOPPED` instead of releasing ownership. The native input helper had already confirmed cleanup and exited without dispatch. The retained listener subsequently exited 0 through a verified normal message-loop quit; only the passive coordinator was then retired to close Pi stdin, and all recorded actors were independently absent. Failure/cleanup receipts remain in `C:\Users\fei\AppData\Local\Temp\pi-cu-stop-preflight-uuZrag\` and `/tmp/pi-cu32-{listener-quit,passive-retire,cleanup}.json`; controller log: `/tmp/pi-cu31-host-esc-v24V2w/`. This remains a failed prerequisite, not a physical stop pass.
|
|
1007
|
+
|
|
1008
|
+
The repair exempts tracked settlement requests from stop-triggered cancellation. Its deterministic actual-worker/fake-native test failed before the fix and passed afterward; all eight preparation/cleanup tests and the full suite (167 passed, one skipped) passed. Only initial test-harness startup waits were aligned with the existing 90-second worker budget; production deadlines and later cleanup gates were unchanged. The subsequent successful physical receipt is `/tmp/pi-cu31-host-esc-k3rFby/{result.json,source.json,foreground.json,absence.json}`. Its source fingerprint matches both fresh prerequisite receipts (`pi-cu-stop-preflight-GcjHYl` and `pi-cu-stop-preflight-2CBWa2`), and its input call was not retried or automatically replayed.
|
|
1009
|
+
|
|
1010
|
+
**Current Pi-only gaps:** #31 control interruption/cleanup is accepted in the [composed evidence](#control-interruption-acceptance); broader capture/idle presentation stays with #20. Seamless unlock recovery and target survival are not gates. Known-held Ctrl/button cancellation/error, actual WSL Pi Ctrl+Alt+F9 and human handback/resume have passed in their named receipts. Reuse them and native Pi Esc; DSH-host stopping is removed. The [delivery plan](implementation-plan.md#exclusive-control-delivery) retains the other owners' gates; #31 is complete for its accepted scope.
|
|
1011
|
+
|
|
1012
|
+
### Remaining cancellation and locked-clipboard test boundaries
|
|
1013
|
+
|
|
1014
|
+
Worker shortcut follow-up (2026-11-01, `e5e6bc4`): an initial attempt never left the start gate because independent foreground observation returned HWND 0; the gate timed out without input. A fresh user-requested run independently confirmed the owned fixture foreground and observed physical Ctrl+Alt+F9 stop/settlement, stable partial text (160/2000), released keys after two polls, same-operation refusal and fresh-operation recovery. Dispatch returned `USER_INPUT_CHANGED` with cleanup confirmed rather than `COMPUTER_USE_STOPPED`, so the runner exited 1. This proves the observed worker stop/release behavior, not correct error classification, input suppression or actual Pi-host stopping. Shortcut-modifier/interference ordering is a hypothesis, not a proven cause. Independent cleanup found all four recorded actor identities absent, the fixture folder removed and lab lock available. Private source/result/cleanup receipts: `/tmp/pi-cu-stop31-retry-oojbw4yu/`. The new control contract is a product decision, not a retrospective pass for this test.
|
|
1015
|
+
|
|
1016
|
+
Historical boundary: the lock-only fixture's five-second UI timer can release the lock while a timed-out backend request is still active. The later [accepted Pi backend case](#pi-clipboard-contention-and-privacy-acceptance) privately preserves the original and seeds owned data before locking, so a late backend can encounter only test data; uncertain cleanup still retains the fixture and owners. Pi abort rejection and DSH MCP-parent termination do not independently prove that all input owners have settled. Consequently the existing lock-only prerequisite cannot safely be extended into a timed-out physical backend test without independently supervised process ownership and a verified settlement/cleanup boundary. No backend lock comparison was dispatched.
|
|
1017
|
+
|
|
1018
|
+
Source inspection found that both physical stop hooks ignore injected keys, so synthetic keystrokes cannot establish real Esc or custom-shortcut behavior. DSH's recognized stop key is consumed by its hook, whereas Pi's hook forwards it; this is a source-level difference, not a paired live result. Public keypress calls send complete chords and do not provide a proven held-modifier cancellation boundary. The earlier manual wait cancellation remains scoped evidence, not held-key acceptance.
|
|
1019
|
+
|
|
1020
|
+
A first authorized Pi worker stop-fixture run began typing before its short prompt could be relayed to the user. It reported a stopped and settled operation, a stop-specific result with cleanup confirmed, stable partial text (44 characters), and successful same-operation refusal/new-operation recovery, but its immediate key-release check failed. The user subsequently confirmed pressing Esc manually; the specific key or button still held at the immediate observation was not identified. A subsequent independent OS check found all inspected mouse buttons, modifiers, Esc and F9 released and no remaining test processes. This is partial physical-Esc evidence with an inconclusive release check, not a pass; no input was replayed. The test coordination and release observation require correction before another attempt.
|
|
1021
|
+
|
|
1022
|
+
After a reviewed coordination correction, a fresh authorized Pi-worker run waited for a start signal and prompted the user during typing. A physical Esc stopped the operation with `COMPUTER_USE_STOPPED` and confirmed cleanup; the input settled at 80 of 2,000 characters, remained stable, and the stopped operation was refused while a new operation recovered. Bounded post-settlement checks observed released keys on the second poll. A separate OS check found mouse buttons, modifiers, Esc and F9 released and no owned stop-test processes. An initial preparation attempt stopped at the closed start gate without typing; it was relaunched with interactive stdin before the single physical input run. This covers the Pi worker/listener only, not the real Pi host, DSH, a custom shortcut, or interruption while a modifier is known held.
|
|
1023
|
+
|
|
1024
|
+
### Passive owner-thread IMM fixture
|
|
1025
|
+
|
|
1026
|
+
A no-input Windows run created a hidden owned TextBox on its STA creator thread and sampled its legacy IMM context on that thread and another thread in the same process. Each returned an available handle and a raw `ImmGetOpenStatus` value of false. This is one synthetic, unfocused fixture sample with no controlled IME-open condition; the raw false values do not establish that either thread can reliably read another target's open status, nor that Notepad's IME is closed or TSF is inactive. No keyboard layout, focus, clipboard or physical input was changed by the fixture. This test does not explain the recorded DSH text corruption.
|
|
1027
|
+
|
|
1028
|
+
### Unicode append with verified editor focus
|
|
1029
|
+
|
|
1030
|
+
On a user-authorized idle Windows desktop, a fresh Pi run and a fresh pinned-reference run each executed Notepad case 3 with the reviewed editor/focus gate. Both observed the intended window and editor HWND/PID, focus inside that editor, target foreground, and keyboard layout `0x4040404`. Pi's appended text matched exactly in both accessible text and saved UTF-8 text. The reference reported Unicode input sent, but both independent observations showed a missing line break and corrupted appended characters; the expected text did not match. Each runner reported its owned tab closed, no retained tabs and client shutdown acknowledged; backend process retirement was not independently verified by the runner. A separate OS check found no held mouse buttons or modifiers and no owned Unicode runner. No automatic replay occurred. Each external probe enumerated one legacy context and returned a raw closed-looking value. That is not evidence that the focused editor IME was closed: Microsoft documents that [IMM access is subject to handle-creator thread checks](https://learn.microsoft.com/en-us/windows/win32/intl/developing-ime-aware-multiple-thread-applications), even though [context enumeration accepts another process’s thread ID](https://learn.microsoft.com/en-us/windows/win32/api/imm/nf-imm-immenuminputcontext). The separate probe runs on its own thread and does not establish the focused context or TSF state. This single paired case does not establish a minimum Pi delay or cause of the reference corruption. Raw reports: `/tmp/pi-cu-drop-evidence/unicode-editor-pi.jsonl` and `unicode-editor-reference.jsonl`.
|
|
1031
|
+
|
|
1032
|
+
On 2026-10-31 an authorized fresh Pi worker physical-Esc fixture ran with the new input-preparation acknowledgement protocol. The fixture reported started, stopped and settled, stable partial text (29 of 2,000 characters), and released keys; `type_text` returned `USER_INPUT_CHANGED: intervening input stopped automation` with `cleanupConfirmed: true`, rather than the required stop-specific error. The test failed its acceptance assertion. The user subsequently reported accidentally clicking the left mouse button before pressing Esc; this is consistent with the intervening-input result, but exact event attribution and any relationship to the acknowledgement barrier are not established. The run is not a physical stop pass. A subsequent independent OS check found the inspected keys/buttons released and no owned stop-test processes. No input was replayed.
|
|
1033
|
+
|
|
1034
|
+
A second fresh authorized physical-Esc run with the input-preparation acknowledgement protocol passed on the Pi worker fixture: typing stopped with `COMPUTER_USE_STOPPED` and confirmed cleanup, the partial text remained stable at 48 of 2,000 characters, the stopped operation was refused and a new operation recovered. Fixture polling and a subsequent independent OS check observed checked keys/buttons released; no owned stop-test processes remained. This is a single Pi worker/listener run, not full Pi-host, DSH, known-held-modifier or comprehensive race acceptance. The preceding failed run and user-reported intervening click remain recorded above.
|
|
1035
|
+
|
|
1036
|
+
### Pi-only ordinary native-control pilot
|
|
1037
|
+
|
|
1038
|
+
On 2026-10-31, the installed Pi CLI used OpenAI GPT-6.1 Sol with `--thinking low` and a natural outcome request for a uniquely titled disposable controls window. The agent used list_windows, accessibility_tree, set_value and accessibility_tree; the owned fixture independently confirmed the requested `Pi acceptance 中文 café 😀` text and unchanged read-only/disabled fields. The agent settled and exited 0; the fixture exited, its HWND disappeared and checked keys/buttons were released. Sanitized tool/status evidence is retained locally at `/tmp/pi-cu-agent-pilot/result.json`; raw model reasoning and final wording were not retained. This is a single Pi-only owned-control task, not a Notepad, recovery, physical-input or DSH comparison; #35 remains open. The current shell lacks the configured DSH OpenRouter credential environment variable, so no real DSH model call was made. An isolated generic-MCP discovery exposed the pinned Windows-node reference server's 25 tool declarations to a synthetic provider; it did not call the backend or validate the unchanged reference adapter.
|
|
1039
|
+
|
|
1040
|
+
A separate Pi-only ordinary Notepad pilot opened a uniquely named, seeded temporary file in an observed Notepad window and asked the same model to append multilingual text, save, and close only that document. The agent used `list_windows`, `snapshot`, then `keypress`; the keypress returned `ok: false` with `cleanupConfirmed: true`, and no later completed tool call was recorded. Pi settled and exited. Independent inspection confirmed the owned file still contained exactly its original seed, and an OS check found the inspected mouse buttons and modifiers released. The exact keypress error was not retained by the sanitizer, so its cause and whether a different method would help are unknown. The owned tab and file were retained; the file path is in mode-600 `/tmp/pi-cu-agent-notepad/owned-path.txt`, and sanitized outcome is in `/tmp/pi-cu-agent-notepad/result.json`. The retained coordinator was stopped only after Pi settled and cleanup/key state were confirmed. Unrelated documents were not inspected, so their unchanged state is not independently established. This single failed Pi run does not close #35 or establish a DSH comparison; no input was replayed.
|
|
1041
|
+
|
|
1042
|
+
### Pi Notepad activation refusal
|
|
1043
|
+
|
|
1044
|
+
On 2026-10-31, after the user cleared personal Notepad tabs, the actual Pi CLI with GPT-6.1 Sol low received a natural append/save task on a uniquely owned temporary file. The agent discovered windows, opened the owned file in Notepad and observed it. Its first Ctrl+End returned `TARGET_ACTIVATION_REFUSED` with cleanup confirmed; the agent settled and no later completed tool call was recorded. The saved file remained its original seed. The file and tab were retained; an independent check found checked buttons/modifiers released and the settled coordinator exited. No unrelated document contents were inspected. A later read-only check found the owned Notepad process, an unlocked session and foreground HWND 0, but cannot reconstruct the foreground at the failure. Pi source uses `SetForegroundWindow`, foreground-thread attachment and `BringWindowToTop` before refusal; the reference has an additional Alt-key fallback, whose safety and applicability to this refusal are not established. The result is one failed Pi-only task, not DSH parity or #35 acceptance. Sanitized evidence: `/tmp/pi-cu-agent-notepad/result-unguarded.json`.
|
|
1045
|
+
|
|
1046
|
+
A later fresh owned-file Pi Notepad task stopped before physical input when an activated snapshot returned `TARGET_ACTIVATION_REFUSED`. New coarse diagnostics recorded initial `SetForegroundWindow=false`, no foreground window before or after the fallback, no foreground-thread attachment, `BringWindowToTop=true`, and fallback `SetForegroundWindow=false`. Pi settled, the owned file remained its seed, checked keys/buttons were released and the coordinator exited; the file was retained. A subsequent read-only probe reported the same session and input-desktop name for Notepad and the probe, WTS unlocked, and foreground HWND 0. One independent Pi `activate_window` request against the owned Notepad window also returned activation unconfirmed with OS foreground 0; no keyboard or mouse input was sent. These observations do not establish why Windows reported no foreground or prove that DSH's Alt fallback would be safe or effective. No action was replayed. This is not a successful Notepad task or DSH comparison.
|
|
1047
|
+
|
|
1048
|
+
After a user click brought the retained owned Notepad window to the foreground, a fresh Pi GPT-6.1 Sol low task proceeded past snapshot, sent click and keypress with cleanup confirmed, then received `ELEMENT_WRONG_OWNER` from `set_value`. The agent settled and no later completed tool call was recorded. The owned saved file remained its seed; checked mouse buttons/modifiers were released and the coordinator exited. The sanitized trace did not retain trustworthy target-match evidence, element IDs, coordinates or key names, so the cause of the ownership error and effects of earlier input are unknown. Later source review found that this pilot initialized its comparison target to null and never assigned it; its false target-match flags therefore do not prove wrong-window selection. Its prompt also required stopping on any error, so that attempt cannot measure ordinary recovery. This was one failed Pi-only task with user foreground intervention, not autonomous acceptance or a DSH comparison; the file/tab remain retained. Sanitized result: `/tmp/pi-cu-agent-notepad/result-foreground-pilot.json`.
|
|
1049
|
+
|
|
1050
|
+
A fresh scoped Pi GPT-6.1 Sol low task used a newly named seeded Notepad file in the existing app. Direct public snapshot and element-info first confirmed the observed root/editor pair and exact seed. The model then selected that same observed root, used background set-value, and read back the exact requested multilingual append. Independent selected-tab/value inspection also matched. Its first Ctrl+S was blocked by the temporary fixture's requirement for preexisting foreground/editor focus; it tried focus and re-observed before settling. That guard refusal is not a product error. Source inspection showed production keypress already activates and verifies its target before input, so the temporary scope was corrected to permit owned-document Save without preexisting focus. A subsequent direct public-worker Ctrl+S was the first dispatch attempt: production returned `TARGET_ACTIVATION_REFUSED` with cleanup confirmed, both foreground requests false, foreground unavailable before/after/refusal and no input-thread attachment. No key input was sent. The saved file remained its seed while the exact edited text and owned tab were retained unsaved. No menu-save alternative was exposed by this limited scope; it does not establish that such an alternative would fail.
|
|
1051
|
+
|
|
1052
|
+
The Pi task and direct-save coordinator exited; checked buttons/modifiers were released and no disposable identity-probe process remained. Worker disposal returned, but native worker/helper PID retirement was not independently traced. An added UIA-focus probe timed out and was abandoned; the unchanged selected-tab control and narrow Win32 identity/focus checks subsequently completed. This is fixture evidence, not a product failure. The first scoped collector still had a colon-dependent error parser and classified a successful snapshot warning as an error code; that temporary parser was corrected before the direct-save diagnosis. Correctly initialized opaque identity aliases establish this run's matching root, not the cause of the earlier ownership failure. Machine-readable local evidence is retained privately in `/tmp/pi-cu-notepad35-live/{owned,result,direct-save-result,cleanup}.json`. This is one scoped Pi append success plus an accurately refused save, not a complete append/save task, three reset successes, unrelated-document preservation proof, DSH comparison or #35 completion. No production change was justified by these observations.
|
|
1053
|
+
|
|
1054
|
+
### Semantic Save and visible descendant discovery
|
|
1055
|
+
|
|
1056
|
+
Accepted scoped outcome (2026-10-31): actual Pi completed multilingual append-and-save in three consecutive fresh UUID-owned documents on reviewed revision `5972914`, with identical production and private guard/context hashes. Effective assistant metadata consistently reports OpenAI `gpt-6.1-sol`, `openai-responses`, `thinkingLevel: low`. Each outcome-only task made nine successful calls with no guard/product errors, used ordinary default menu discovery and semantic editing/File/Save with physical fallbacks disabled, then settled with `aborted: false` and exit 0. Independent selected-tab/editor inspection and the known UTF-8 file both exactly matched the requested append after normalizing only line endings. Each worker's PID/creation identity was observed during its task and later strict OS queries confirmed the recorded PID absent with no matching staged worker (`$ErrorActionPreference` and `Get-CimInstance -ErrorAction` both `Stop`; query failure cannot establish absence). The coordinator created/opened each seeded file; the model did not create a document or tab. Unrelated documents were not inspected, so their invariance is not independently proven. Owned files/tabs remain available for inspection; this is worker retirement, not global application cleanup. This accepts the preopened-document task, not controlled obstacle/stop/interference recovery, document creation, DSH or full #35. Results/traces and cleanup: `/tmp/pi-cu-notepad35-menu-model{3,4,5}/{result,trace,guard,process-live,process-cleanup}.json*`; summary `/tmp/pi-cu-notepad35-menu-live/accepted-summary.json`.
|
|
1057
|
+
|
|
1058
|
+
The earlier temporary scope omitted `invoke`, so keyboard Save refusal did not establish that semantic File → Save would fail. Its simplified focus probe also checked root/editor/title/visibility rather than the selected-tab proof its message claimed. New UUID-owned files used the existing independent selected-tab/runtime-ID/editor/value probe instead. One semantic Save on an unmodified seed succeeded with fallback disabled; menu collapse and unchanged seed were verified, proving the route but no persistence delta.
|
|
1059
|
+
|
|
1060
|
+
Two fresh actual Pi tasks on `2ff1118` remain incomplete. Their effective assistant metadata reports OpenAI `gpt-6.1-sol`, `openai-responses`, `thinkingLevel: low`. Each model exactly edited and re-read its coordinator-prepared owned document, but disk bytes remained the seed. The first recovered through ordinary and raw/offscreen observations, then a temporary guard rejected its legitimate compact Save reference because it lacked full-detail pattern metadata; that guard also discarded earlier File observations unnecessarily. These fixture defects were regressed and corrected. The second task had no guard/product error: it expanded File, tried default/control/raw observations without `includeOffscreen: true`, then accurately reported saving unverified. No Save was sent in either task. Both exited normally without physical input; the second worker's observed PID/creation identity was later absent. No input was replayed against either retained document. The private File/Save-once limit is a diagnostic constraint, not production recovery policy.
|
|
1061
|
+
|
|
1062
|
+
A passive same-menu comparison proved a product/reference gap: with File independently Expanded and Save itself `isOffscreen: false`, Pi's default control/raw find omitted Save while pinned DSH found the same runtime ID. Both found it with offscreen inclusion. An intermediate WinUI `Popup` reported offscreen even though its Menu/Save descendants were visible. DSH composes visibility into its TreeWalker condition, promoting matching descendants; Pi pruned entire offscreen subtrees. The native bridge now uses the reference's projected-view filtering. The existing nullable-provider fixture gained an offscreen ancestor with a visible native child: public tree/find regression failed before the fix and passed for control/raw/content afterward, retaining the ancestor only with explicit offscreen inclusion. The same retained Notepad menu then matched DSH under default views without another mutation.
|
|
1063
|
+
|
|
1064
|
+
Reviewed repair `2a1ec6b` was merged as `43094fd`. Portable checks and the independent review rerun passed 125 tests with one skipped (`offscreen-check-merger.log`). Affected passive nullable/quiet-scroll, accessibility and Chromium-read suites passed, including unknown roles, incomplete absence, wrong/stale ownership, depth/node bounds and cancellation ownership. No production retry, new API or guidance workaround was added. The accepted model slice above does not complete #35 or #28. Private failure/mechanism evidence: `/tmp/pi-cu-notepad35-menu-model{1,2}/{result,guard}.json*`, model2's `passive-compare-before-fix.json`, corrected raw `passive-compare.json`, `menu-state.json` ancestor flags, and `offscreen-regression-{red,green}.log`. Earlier collector wrapper/field mistakes are retained separately; they are not product failures.
|
|
1065
|
+
|
|
1066
|
+
### Visual OCR association preflight
|
|
1067
|
+
|
|
1068
|
+
A04's existing OCR fixture now has an optional painted-button mode. Its two ordinary native buttons retain Invoke but expose no labels/codes through public UIA; creation order, label assignment and positions are randomized independently. The direct public-tool regression first failed with zero required buttons, then passed: a reliable window-only PrintWindow image and `zh-Hant-HK` OCR exposed both exact codes; mapped APPROVE text selected one opaque public button ID by its bounds; `native_button` invocation with fallback disabled changed the independent APPROVE counter 0→1 and IGNORE 0→0. Image bounds stayed within the independently reported owned window and contained its client. PNG/base64 payloads were not persisted. Default HELLO/literal/scaling/sparse/minimized checks also passed. One initial environment-forwarding attempt ran only the default case; its log is staging evidence, not the visual regression red.
|
|
1069
|
+
|
|
1070
|
+
Installed Pi CLI/SDK 1.4.0 source places `tool_result` replacement before image normalization, final tool events and provider/history insertion. Its extension runner catches handler exceptions, so the private guard catches its own verification/redaction failures and returns a literal blocked result instead of throwing. An actual offline scripted-provider Pi run verified four cases: unsafe screenshot, unsafe OCR text, nested find OCR text and verifier exception were absent from the next provider context and persisted events. Positive controls confirmed approved owned-window image content and safe OCR text reached the next provider context; only receipt booleans/image hashes were retained. Image bytes are removed from trace serialization even for approved owned images. Native screenshot/OCR implementations currently emit no streaming update payloads; this is not a blanket claim about arbitrary extension updates. The guard/collector integration and native receipts were independently reviewed before the model runs below; these scripted controls alone do not establish model recovery or full #35 acceptance. Evidence: `/tmp/pi-cu-ocr35-direct/{fixture-red,fixture-final-target}.log`, `direct-receipts.json`; `/tmp/pi-cu-ocr35-guard/{sdk-source-evidence,sdk-result,sdk-receipt}.json`, `visual-guard.mjs` and sanitized `sdk-trace.jsonl`.
|
|
1071
|
+
|
|
1072
|
+
Three actual Pi/GPT-6.1 Sol low fresh resets on source `1c052c0` then completed the scoped A04 visual-to-semantic task. Public native button labels/codes were absent; each model read the owned window image, selected a genuine opaque public button ID, invoked it once through `native_button` without fallback and reported the exact APPROVE code (5461, 3077, 1862). Each used snapshot → Invoke → snapshot, with no OCR tool call, product error or guard refusal. The models accurately reported that the fixture showed no visible confirmation; independent IPC nevertheless recorded APPROVE=1 and IGNORE=0. All effective metadata matched, settlement was not aborted, exact observed worker identities retired, fixture processes/temp folders retired and traces contained no image bytes. Fixture preparation was by the coordinator; no general app launch, document creation or action-error recovery is claimed. Results: `/tmp/pi-cu-ocr35-model-{789fb2b9-bc07-43a4-9668-ee047e201824,404be0a1-93fd-486b-9139-4a94b88490c9,2a4496c3-c451-4034-b5b0-1794b0070519}/result.json`; combined `/tmp/pi-cu-ocr35-guard/model-summary.json`. Review caught private guard/protocol/lifecycle gaps before these model runs; no production repair was needed for this slice.
|
|
1073
|
+
|
|
1074
|
+
The repository runner is `npm run test:pi:visual` (plan by default); [scoped visual agent instructions](windows.md#scoped-visual-agent-check) cover explicit execution and retained owners. Its existing-fixture IPC, finite guard and model collector replace private-path-only reproducibility. Portable scope/metadata/journal/retention negatives run through `npm run check`. The three original successes remain pinned to their original source. After independent port review and integration of lifetime tracking plus the WGC repair, one fresh repository-command reset on `3099091` passed: exact APPROVE code3239, APPROVE=1/IGNORE=0, all four effective assistant rows openai/gpt-6.1-sol/low, no tool or guard errors, and the same snapshot → Invoke → snapshot sequence. The model naturally used a genuinely returned `windowRef` and opaque `u:` element ID; no reference was injected. It accurately reported no visible confirmation. The independent oracle verified the effect; worker13932/creation and fixture29540/creation retired, the fixture folder was removed and traces remained image-free. Evidence and source/compiled hashes: `/tmp/pi-visual-model-wQAojy/1-Gy8x2y/result.json`, with sequential `guard.jsonl`/`trace.jsonl`. This single integrated run validates port wiring on that candidate; it is not three reset runs on the new source. Full #35, DSH model comparison and OCR availability/language/protected-content/cancellation requirements remain open.
|
|
1075
|
+
|
|
1076
|
+
### Scoped Pi browser-agent form pilot
|
|
1077
|
+
|
|
1078
|
+
Current accepted subscenario (2026-10-31): the actual Pi CLI with GPT-6.1 Sol low completed exact multilingual form submission and delayed confirmation in three consecutive independently reset headless Edge runs. Each used a fresh local server/profile, the same production revision `d7a9da5` and fixture hash `8060c3c99733dc3805bbdace7d72a0d1f5e1a4ed736be0f0c3c913eb64c44310`. The outcome prompt prescribed no tool sequence. Each run made eight successful tool calls ending in a positive `wait_for` observation. The server independently matched name/notes/terms/Beta and recorded exactly one submission, delayed start and ready event. Pi and the fixture exited, and profiles were empty. A corrected later process check found zero matching/live Edge processes for all three owned prefixes; this is not a termination-latency measurement. No native input or clipboard action occurred. Sanitized results: `/tmp/pi-cu-browser36-live/result-{1,2,3}-verified.json`. The guard restricted actions to the trusted owned tab and observed elements, permitting supported recovery; no error occurred, so recovery itself was not exercised. This form acceptance alone did not cover DSH, navigation/dialog/transfer recovery or mixed native tasks; later scoped results are recorded below.
|
|
1079
|
+
|
|
1080
|
+
Two subsequent scoped advanced-page tasks on `bb69cbc` remain incomplete. Both naturally opened the trusted child tab, observed its identity, returned to the advanced context and produced the exact prompt response, then stopped before confirmation, alert or transfers. The first collector retained successful tool-end events but omitted warning fields; the fresh diagnostic retained full owned-fixture tool/lifecycle evidence. It confirmed a product warning defect: prompt acceptance succeeded with the exact page response, but `presentation.warning` said `BROWSER_CUE_UNAVAILABLE: Error: COMPUTER_USE_CANCELLED`. Pi settled with `aborted: false`; the model treated that warning as the requested stop condition. The server recorded zero transfer requests, profiles were empty, the corrected matcher found zero owned Edge processes and fixtures exited. Neither operation was replayed. Results: `/tmp/pi-cu-browser36-advanced-live/result-1.json` and `result-diagnostic2.json` (the earlier sandbox startup attempt never reached the fixture).
|
|
1081
|
+
|
|
1082
|
+
The mechanism was a cosmetic JavaScript cue update attempted while a modal dialog paused page execution; its own one-second deadline was labelled cancellation, although the caller remained live and Enter then succeeded. An assertion in the existing browser action host failed on that exact warning before the fix. Cue marking now preserves the existing cue while a modal dialog is pending, after checking actual caller cancellation. The full headless Edge action/dialog/transfer suite passed afterward, including its existing genuine cancellation checks. This establishes a targeted product repair; its tool regression alone did not establish agent acceptance. The reviewed integrated acceptance follows. The initial worktree host attempt failed to resolve dependencies through an absolute Linux symlink; copying the installed dependencies reached the meaningful red. No fixture or production retry policy was added.
|
|
1083
|
+
|
|
1084
|
+
Post-fix scoped advanced acceptance passed three consecutive independent resets on reviewed production revision `a100fd4`, using the same fixture hash as the form pilot. Actual Pi/GPT-6.1 Sol low naturally opened the trusted child tab, verified its identity, returned to the existing advanced context, answered the prompt exactly, rejected confirmation, dismissed the alert, uploaded the exact owned sample and downloaded the fixture once. Each server oracle independently recorded one exact-content upload and one download; Windows filesystem reads verified the known download bytes before removing only that uniquely named fixture file. Each final report named the actual completed download path. Tool warnings and observation errors were absent; all runs settled with `aborted: false`, exited normally, left empty profiles, had zero matching owned Edge processes and exited their fixture servers. Run one safely recovered from a **guard** refusal after offering the sample path to the upload button instead of its file input; the other two had no errors. That slice proves the scoped task and guard recovery; controlled stale-document/second-form coverage follows below. Mixed native workflows, DSH and full #36 remain open. Original failures remain above. Private results/traces: `/tmp/pi-cu-browser36-advanced-live/result-accepted{1,2,3}.json`, `trace-accepted{1,2,3}.jsonl` and `guard-accepted{1,2,3}.jsonl`. No new fixture, framework or production source change was needed for these acceptance runs.
|
|
1085
|
+
|
|
1086
|
+
Controlled stale-document recovery and the second-form workflow then passed three consecutive reset Pi/GPT-6.1 Sol low runs using the unchanged fixture and an isolated staged build at `9c4206f`. Each task submitted an exact first form, navigated the same owned tab to the advanced page, answered its prompt, then returned for an exact second form. After the model observed the second document and attempted a field mutation, the private fixture wrapper performed **one real public-tool reload** and dispatched the original old-ID call. The product returned `STALE_BROWSER_REFERENCE`; the existing HTTP oracle showed no second submission and a separate public element read showed the intended field still blank. The model then made its own fresh observation, used a new reference and completed the exact second payload with one submission. First-form payload/count evidence was saved independently before navigation reset the fixture. Hidden oracle reads did not provide fresh IDs to the model. All three final reports matched the observed task/recovery, with no warnings, guard refusals, global abort or unknown-effect replay. Each run settled and exited with empty profiles, zero matching owned Edge processes and exited fixture server. Private evidence: `/tmp/pi-cu-browser36-stale-live/result-{1,2,3}.json`, `trace-{1,2,3}.jsonl` and `guard-{1,2,3}.jsonl`. Source and compiled hashes for browser, browser-actions, browser-profiles and browser-indicators matched root `7552fd5` (`browser-path-provenance.json`); this does not revalidate its later native/worker changes. No fixture, production change or public test API was needed. Mixed/native, partial-observation and cancellation/interference agent scenarios plus DSH remain outside this accepted slice.
|
|
1087
|
+
|
|
1088
|
+
The existing form fixture now exposes resettable delayed-event/submission counters while preserving `/form/state`'s payload contract. Its HTTP regression failed before the endpoint existed and passed after the change; portable checks passed 118 tests with one skipped. The delayed observation oracle rejects an echoed query with no match. The inherited process oracle used JSON escaping inside PowerShell and was unreliable; original immediate process flags are superseded by the corrected literal-prefix recheck, with prior reports retained.
|
|
1089
|
+
|
|
1090
|
+
A separate read-only `WorkerClient.dispose` lifecycle diagnostic retained a cleanup failure for #18: the corrected matcher saw eight live owned Edge processes before disposal; disposal returned in 1003 ms, and samples at 2.4–15.9 seconds found no matching/live browser processes but a nonempty profile. Both this and an earlier diagnostic's residual leases remained `running` while their recorded worker/browser PIDs were absent. The worker's 1000 ms retirement deadline versus browser/profile cleanup is a source-level candidate, not proven signal attribution. No test-sent termination or residue deletion occurred. Artifacts: `/tmp/pi-cu-browser36-live/bounded-cleanup.json`, `cleanup-resample.json` and `profile-owner-state.json`. This separate failure does not erase the Pi-host task outcomes or certify the general shutdown path.
|
|
1091
|
+
|
|
1092
|
+
Earlier attempts remain failed or scoped as originally observed: the first strict-guard form pilot returned an unclassified invoke error after several successful actions and recorded no submission; the next identified a guard denial with no submission, though the exact condition was not retained. Their coordinators were stopped after Pi/worker exit and profile-empty observations; server PIDs exited, but graceful server cleanup was unverified. A later observed-element/tab-only guard allowed one exact multilingual form submission with normal Pi/fixture/coordinator exit and an empty profile. Those runs' reported zero matching Edge processes used the unreliable PowerShell matcher and are unverified. No action was replayed. Sanitized artifacts remain `/tmp/pi-cu-browser-agent/result.json` and `result-tab-only.json`. These older results do not establish unrestricted-agent, DSH or recovery acceptance.
|
|
1093
|
+
|
|
1094
|
+
A further scoped Pi-only GPT-6.1 Sol low task used an owned fixture with two same-process windows and independently observed editors. A test-only guard limited operations to those windows and background UIA; no physical input or clipboard tools were available. The natural task succeeded: the main editor matched the requested Unicode text and the sibling, read-only and disabled fields retained their original values. Pi and fixture settled and exited; the coordinator exited and released the lock. No error occurred, so this is scoped target-selection/task evidence, not proof of recovery from `ELEMENT_WRONG_OWNER`, Notepad behavior, unrestricted agent use or DSH parity. Sanitized result: `/tmp/pi-cu-recovery-pilot/result.json`.
|
|
1095
|
+
|
|
1096
|
+
On 2026-10-31, after the worker input-acknowledgement and browser changes, the existing `test:pi` runner installed the production tarball without development or peer dependencies and exercised the actual Pi CLI with an isolated scripted local provider. Health and list-windows turns passed on WSL2 and native Windows-from-WSL, both settled and reported worker cleanup; an independent OS check found the recorded worker PIDs absent. No physical input or real provider credentials were used. This is current-host package evidence, not a clean-OS installation, real-model acceptance or physical-input validation. Log: `/tmp/pi-cu-pi-host-current.log`.
|
|
1097
|
+
|
|
1098
|
+
### Scoped held-navigation cancellation
|
|
1099
|
+
|
|
1100
|
+
The existing runner’s optional `cancel` case adds one unique local confirmation URL that holds its HTTP response. Its ordinary goal asks Pi to open the URL, verify the confirmation and report the result, without prescribing a tool sequence. Optional fixture readiness and child-scoped WSLENV forwarding are checked before model startup. The harness calls actual Pi `ctx.abort()` only after independently observing HTTP entry and the sole matching pending navigation frame, with all earlier worker requests settled. No production code, public API or normal fixture behavior changed.
|
|
1101
|
+
|
|
1102
|
+
Three fresh actual resets on unchanged `81824e8` passed using Pi 1.4.0, OpenAI GPT-6.1 Sol and low reasoning; every effective assistant metadata row matched the request. These are controlled cancellation passes, not completed confirmation tasks. Each model naturally dispatched a new-tab navigation, then the real SDK settled aborted. The original request returned canonical `COMPUTER_USE_CANCELLED`; an actual matching causal cancel/stop frame preceded that response and a successful released `operation_end` acknowledgment. Both arrived before the 15-second navigation timeout. No later business action or false completion claim occurred; there was no terminal assistant report.
|
|
1103
|
+
|
|
1104
|
+
| Actual reset | Original reply / released ACK elapsed from request | Authoritative report |
|
|
1105
|
+
| --- | --- | --- |
|
|
1106
|
+
| 1 | 8124.85 / 8128.35 ms | `/tmp/pi-cu-cancel36-model-pilot/cancel-1-yNqfgG/report.json` |
|
|
1107
|
+
| 2 | 7384.11 / 7387.19 ms | `/tmp/pi-cu-cancel36-model-more2/cancel-1-9yQwEe/report.json` |
|
|
1108
|
+
| 3 | 7663.54 / 7666.70 ms | `/tmp/pi-cu-cancel36-model-more3/cancel-1-zPj5S3/report.json` |
|
|
1109
|
+
|
|
1110
|
+
Each independent HTTP oracle recorded exactly one entry, zero completed confirmations and one closed connection. Each worker was pinned by PID, creation time and executable before abort, then independently confirmed absent after settlement (34764, 36916 and 20956 respectively). The existing collector also confirmed empty owned profiles, zero exact-prefix Edge processes and fixture exit; traces contain no image payloads. Empty profile-root directories remain. The additional ownership-helper PID reported by the release ACK was not independently pinned or checked for retirement, and fixture exit is the retained child-handle observation rather than an independent Windows birth query. These are scoped cleanup results, not global process cleanup. Full receipts, 45 unchanged source/build hashes and limitations are indexed in `/tmp/pi-cu-cancel36-acceptance.json`.
|
|
1111
|
+
|
|
1112
|
+
Preparation evidence remains separate: the one scripted public-backend preflight on `81824e8` (`/tmp/pi-cu-cancel36-preflight/result.json`) proved actual held HTTP, original canonical reply and released ACK under 15 seconds, plus recorded worker/browser/fixture retirement. It did not run a model or the actual SDK abort path. Meaningful offline regressions cover canonical navigation cancellation, causal frame/ID/timing/ACK failures, Windows-local fixture-state transport and real SDK dispatch fencing; passive wait still requires `COMPUTER_USE_STOPPED`. A known runner limitation retains ownership when no navigation pin exists instead of classifying a clean no-dispatch episode as unexercised; an unfinished private classification experiment was discarded before all three models. No model evidence is attributed to that experiment. After merging documentation-only `cbb78b1`, the final candidate passed the configured check (159 passed, one skipped), build and 87-entry package/document-link check; all 45 model source/build hashes still matched. Interference, other cancellation workflows, DSH model comparison and full #36 remain open.
|
|
1113
|
+
|
|
1114
|
+
### Scoped partial-observation recovery
|
|
1115
|
+
|
|
1116
|
+
The existing browser runner’s optional `partial` case prepends 200 ordinary neutral paragraphs to its local form. Production outline limits, tool schemas and default fixture behavior are unchanged. The outcome-only prompt requests the Unicode form and preservation/confirmation; it prescribes no read budget or tool sequence. Child-scoped WSLENV forwards the optional fixture flag, and the server’s readiness metadata is checked and recorded before Pi starts.
|
|
1117
|
+
|
|
1118
|
+
Three fresh actual Pi resets on unchanged `9021897` passed: `/tmp/pi-cu-partial36-pilot-fixed/partial-1-8035ND/report.json`, `/tmp/pi-cu-partial36-more/partial-1-XzU2vA/report.json` and `/tmp/pi-cu-partial36-more/partial-2-lmC3EN/report.json`. Every initial new-tab result genuinely stopped at 500 nodes with `truncated:true`, before usable form controls. Each agent then chose larger supported reads, exposing 659 real nodes; the verifier correlates freshly observed opaque IDs/roles to all four successful field effects and Submit, then a genuine noneditable confirmation and post-submit restricted values. Independent HTTP oracles returned exactly `Pi 中文 café 😀`, multiline `First line\n第二行 café 😀`, accepted terms and Beta, with exactly one submission and no delayed-result actions. Requested and every effective assistant metadata row matched Pi 1.4.0, OpenAI GPT-6.1 Sol, low reasoning; Edge was 156.0.4314.50.
|
|
1119
|
+
|
|
1120
|
+
The first accepted run’s regex-like find query matched nothing, but its actual returned full nodes exposed legitimate controls; query echo was not credited. After submission a valid wait for nonexistent “Submitted” text timed out conclusively, then a fresh find verified the real confirmation. The second run received an SDK pre-dispatch validation refusal for an empty find query and safely corrected its read. The third had no tool errors. No uncertain mutation or submission was replayed; these retained read outcomes are not guard failures or demonstrated product defects.
|
|
1121
|
+
|
|
1122
|
+
All three source/build manifests matched, models settled non-aborted and Pi exited zero. The existing collector confirmed fixture exit, empty owned profiles and zero exact-prefix Edge processes; traces contain no image payloads. This nonmixed runner does **not** independently pin/query Windows worker PID/birth/retirement, and its empty profile-root directories are retained rather than removed. Keyboard field-selection and typing without observed focus proof are reported as verifier limitations, rather than attributed to the product or model. No global cleanup or DSH-model parity is claimed. Aggregate hashes, chronology, all error rows and scope are retained in `/tmp/pi-cu-partial36-acceptance.json`; each report’s tool/audit traces remain authoritative.
|
|
1123
|
+
|
|
1124
|
+
Preparation/failures retain their exact scopes. The read-only direct gate on `cc70ece` proved default 500-node truncation, a default find returning all 659 nodes, payload null/submissions zero, and independently recorded worker/browser/fixture retirement before storage removal (`/tmp/pi-cu-partial36-direct/`). Its real same-ID button/StaticText result exposed a verifier bookkeeping defect; a literal regression failed before `dcee3ac` retained genuine actionable roles and rejected contradictory actionable identities. The first paid pilot on `dcee3ac` instead saw 59 untruncated nodes because the flag was not forwarded from WSL: it completed an ordinary form but is **unexercised, not accepted** (`/tmp/pi-cu-partial36-pilot-live/`). A separate passive Windows Node control proved original child flag absent versus forwarded flag present (`/tmp/pi-cu-partial36-transport/`); the final fix also prevents model startup without partial-fixture readiness. The direct AX gate was not repeated or relabeled as running the later source. This completes the named partial-form slice, not all #36 workflows or release acceptance.
|
|
1125
|
+
|
|
1126
|
+
### Scoped mixed browser/native outcome
|
|
1127
|
+
|
|
1128
|
+
Three consecutive fresh actual Pi tasks passed on unchanged `7e28577` from WSL2 on 2026-11-01. Pi 1.4.0 reported OpenAI `gpt-6.1-sol`, `openai-responses`, low reasoning in every effective assistant row; owned headless Edge was 156.0.4314.50 and Windows Node 22.23.4. Each exact form submission issued a code only after submission. The native fixture painted two neutral CODE labels while exposing blank accessible button names; no expected code, native element ID or private counter entered the outcome prompt. Each model read the actual browser status, selected a genuine returned `windowRef`/opaque native ID using the owned image, invoked once and read the browser's actual IPC-driven completion status. Independent HTTP payload/issuance and native counters agreed. No tool/guard error or procedural intervention occurred; this is successful task completion, not exercised error recovery or OCR-tool use.
|
|
1129
|
+
|
|
1130
|
+
| Overall run | Code / tool calls | Authoritative report directory |
|
|
1131
|
+
| --- | --- | --- |
|
|
1132
|
+
| 1 (accepted pilot) | 1244 / 13 | `/tmp/pi-cu-mixed36-pilot-20261101/mixed-1-y7UuHl/` |
|
|
1133
|
+
| 2 | 2491 / 11 | `/tmp/pi-cu-mixed36-final2-20261101/mixed-1-kZUQSJ/` |
|
|
1134
|
+
| 3 | 8307 / 13 | `/tmp/pi-cu-mixed36-final2-20261101/mixed-2-NQH8tt/` |
|
|
1135
|
+
|
|
1136
|
+
Every report retained the same source/compiled manifest, effective metadata, exact payload and one issued code, selected control counter 1 and other counter 0, code observation before correlated successful native Invoke, and readonly acknowledgement afterward. Final model reports matched those observations. All runs settled non-aborted with Pi exit 0, pinned Windows-worker retirement, zero matching Edge processes/empty profiles, native fixture/temp-folder retirement and HTTP fixture exit0. Separate post-run receipts removed only the exact recorded empty profile roots after another terminating zero-process check. Guard/audit and tool traces are image-free; no keyboard, pointer, clipboard, global discovery or unrelated application was used. Models made no OCR tool calls. Aggregate path/hash/chronology proof is `/tmp/pi-cu-mixed36-acceptance.json`; each unique directory's `report.json`, `tools.jsonl`, `trace.jsonl` and `post-profile-cleanup.json` is authoritative.
|
|
1137
|
+
|
|
1138
|
+
The existing `test:pi:browser -- --scenario mixed --runs 3` repeats this named case; safe `--plan` needs no build or credentials. It reuses native-ocr's optional neutral-code mode, the visual host's pinned preparation/IPC/worker query and the browser host's existing retention/reporting. Server feedback comes from actual native counters, not dispatched-tool success. Oracle regressions reject editable code/acknowledgement echoes and inconclusive waits; genuine status snapshots, observed-status element inspection and positive element/status waits remain supported. Central serialization strips both browser/native image payloads from persisted mixed audits while preserving approved owned images for Pi.
|
|
1139
|
+
|
|
1140
|
+
Earlier failures remain separate. The first private direct preflight counted title-bar buttons and stopped after one successful nonactivating native tree; counters remained 0/0. Its verified idle controller received one explicitly authorized normal SIGTERM only after cooperative fixture stop and pinned-process observation; all 12 Windows actors exited, with worker pipe-closure exit 1 preserved. An unrecorded empty profile path was left rather than guessed/deleted. Corrected direct backend preflight on `413800f` then proved real neutral PNG/OCR, public status-to-native-to-status flow and all 24 recorded processes absent, before any model. Its receipts are `/tmp/pi-cu-mixed36-preflight-next/`; the original failure/cleanup remains `/tmp/pi-cu-mixed36-preflight/`. Review's three false-positive oracle probes and the later owned-browser-image audit regression have meaningful retained red/green logs; `7e28577` changed audit serialization/tests only, so the direct preflight retains its exact earlier source scope. After merging unrelated host-stop test/docs integration `73df9be`, all model-run runtime/fixture hashes still matched; final checks passed 150 tests with one skipped, plus build and the 87-entry package/document-link check. No production code or dependency change was needed. Remaining cancellation/interference and broader controlled workflows, DSH model comparison and full #36 remain open.
|
|
1141
|
+
|
|
1142
|
+
### Passive provider-unavailable probe
|
|
1143
|
+
|
|
1144
|
+
A separate owned `ShowWithoutActivation` UIA fixture injected `UIA_E_ELEMENTNOTAVAILABLE` from its provider callback. The callback's independent entry notification established that the fault path ran for each engine. For Pi, a fresh non-activating snapshot returned a partial tree with `truncated: true`, `conclusive: false`, `truncationReason: providerError` and `providerError: An element disappeared during observation`. For DSH, the corresponding snapshot reported `ok: true` and `truncated: false` with no explicit provider-error evidence. The reference case is **blocked**, not a pass: this observation alone does not establish whether Windows normalized the exception or the reference omitted it. The Pi result proves truthful partial-provider evidence in this fixture, not that every explicit `UIA_PROVIDER_ERROR` payload is forwarded. Both fixtures/controllers cleaned up; no physical input, clipboard use or intentional activation occurred. The combined report intentionally returned nonzero due to the blocked reference case. Raw owned-fixture observations and staged hashes are in `/tmp/pi-cu-followup-evidence/provider-unavailable.json` and `provider-provenance.json`.
|
|
1145
|
+
|
|
1146
|
+
A follow-up passive platform probe (`npm run test:accessibility:provider-platform` on Windows; `-- --plan` is portable) directly requested a compact managed UIA cache for the owned custom child. An independent ready barrier confirmed `FromHandle` and cache construction before arming; the subsequent `UIA_E_ELEMENTNOTAVAILABLE` Name callback was observed after the cache-read gate, and `GetUpdatedCache` plus the subsequent cached Name read returned normally with a null name. This demonstrates normalization or suppression before the caller on that direct-child cache path. DSH uses a walker and additional processing; the probe does not establish that the reference traversed the same path or that every provider error is normalized. The existing DSH comparison remains blocked rather than passing. No input was sent; fixture cleanup was confirmed. Raw evidence: `/tmp/pi-cu-provider-platform-barrier.json` (local test artifact).
|
|
1147
|
+
|
|
1148
|
+
A follow-up `test:accessibility:provider-walker` run used a disposable **instrumented copy** of the pinned reference backend: a test-only gate paused its original cached `TreeWalker.GetFirstChild` immediately before traversal. Only after observing that gate did the runner arm the owned unavailable provider, then release the walker. The callback fired and the reference returned `ok: true`, `truncated: false` with the affected child name `null` and no provider-error metadata. The untouched backend's SHA-256 matched the pinned source; the diagnostic copy was modified, so this is not an unchanged-reference comparison. It places the observed suppression/normalization somewhere after the walker gate; it does not establish which layer suppressed the error or settle the original blocked reference case. No input was sent; fixture and controller cleanup were confirmed. Raw local artifact: `/tmp/pi-cu-reference-walker.json`.
|
|
1149
|
+
|
|
1150
|
+
### Successful drag/drop fixture preflight
|
|
1151
|
+
|
|
1152
|
+
The first Pi successful-drop attempt stopped before dispatch because `find` returned no owned `Drop source` control. An independent process check confirmed that its fixture and runner exited; DSH was not attempted. A fresh no-input fixture inspection returned only the root window in both control and raw accessibility views, immediately and after 1.2 seconds. Both WinForms child handles were created. A separately labeled temporary Button-control variant produced the same root-only views and also exited cleanly. These are fixture/discovery failures, not evidence that either implementation's drag/drop action failed. No coordinates were guessed and no drag was sent. Raw owned-fixture reports and source hashes are retained in `/tmp/pi-cu-drop-evidence`.
|
|
1153
|
+
|
|
1154
|
+
A later no-input investigation found that fixtures launched with `windowsHide: true` lacked discoverable children; a separate OS observation found a fixture window was not visible. A fresh fixture launched visibly exposed both controls. These observations involved separate instances. The corrected fixture requires native visibility of the window and controls, checks identity and bounds, and rejects an explicitly offscreen root. Fresh no-input Pi and DSH preflights both found the owned source and target and verified geometry before any drag.
|
|
1155
|
+
|
|
1156
|
+
On a user-authorized idle desktop, one fresh Pi run and one fresh DSH run each dispatched a single drag. The owned target recorded exactly one OLE drop and the fixture independently observed the left button up for each engine. Both fixture/controller runs exited; a subsequent OS probe found no held mouse buttons or modifiers and no owned test processes. Raw reports and staged source hashes are in `/tmp/pi-cu-drop-evidence`. This verifies the same-application fixture case, not cross-application drag, interruption or user interference. The earlier DSH drag-cancellation timeout and held-button finding remains unresolved.
|
|
1157
|
+
|
|
1158
|
+
A pending opt-in `npm run test:reference:focus-foreground -- --plan --engine=pi` comparison prepares two separate owned fixture processes, confirms one is foreground, then requests background focus in the other and observes its logical focus, foreground HWND/PID and last-input tick after dispatch. It is a diagnostic plan only: Windows execution can change foreground and requires an authorized idle desktop. It does not observe the engine's internal restoration decision or establish the cause of the earlier discrepancy. Run each engine on a fresh fixture and retain failures; no physical input or automatic replay is performed. The reference implementation tests foreground owner PID whereas Pi's restoration guard checks the exact target HWND, but this source difference alone does not identify the observed cause.
|
|
1159
|
+
|
|
1160
|
+
### Cross-process foreground diagnostic
|
|
1161
|
+
|
|
1162
|
+
On an authorized idle desktop, the reviewed owned-window diagnostic prepared separate target and prior-foreground processes and dispatched one Pi UIA focus action without physical keyboard or mouse input. Logical focus reached the editor and subsequent observations showed the target's editor HWND in the foreground. Windows last-input tick changed between the pre-action and post-action observations, and Pi reported `left: user activity or unavailable movement evidence`. The diagnostic therefore classified the result as **inconclusive**; the cause of the input-tick change and foreground transition is not established. DSH was not run after this uncertainty. Both fixture processes exited, and the runner reported controller and temporary-folder cleanup. The diagnostic has no observation of Pi's internal restoration decision. Raw owned-fixture output: `/tmp/pi-cu-drop-evidence/foreground-pi.jsonl`.
|
|
1163
|
+
|
|
1164
|
+
The 2026-10-30 Pi cross-process focus attempt observed the target Edit HWND itself as the foreground window after dispatch and a changed Windows last-input tick; the result is inconclusive, not proof of human interference or a restoration defect. [GetLastInputInfo](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getlastinputinfo) is session-specific and can reflect `SendInput`; [UIA SetFocus](https://learn.microsoft.com/en-us/dotnet/api/system.windows.automation.automationelement.setfocus) is provider-dependent. Neither fact establishes what caused this particular tick change. The optional `--provenance` preparation adds a separate low-level-hook observer during the focus dispatch and reports only aggregate counts of unmarked, injected, and project-tag-matching mouse/keyboard events; it records no keys, text, coordinates or event timing. The fixture also records the foreground ancestor derived from the same observed HWND. A tagged count is not proof of origin; unmarked events are not proof of a human source; hooks can miss events and counts do not identify a process. Changed input ticks or unmarked/foreign-injected events remain inconclusive. Hook compilation and a later provenance-enabled Windows run completed as described below. This optional diagnostic can change foreground and requires an authorized idle desktop; it sends no input itself.
|
|
1165
|
+
|
|
1166
|
+
A fresh authorized Pi run enabled the reviewed aggregate-only low-level input observer; no physical input was dispatched by the diagnostic. The post-action samples showed the foreground HWND was the editor and its `GA_ROOT` was the intended target window. The last-input tick changed, and counters showed two injected key events without the observer's expected marker; all other aggregate categories were unchanged. Their source and content were not observed, so the run is **inconclusive**, not proof of human interference or of the foreground guard's internal behavior. DSH was not attempted after that uncertainty. The runner reported cleanup; a separate process check found both owned fixtures and observer exited. The observer stores no keys, text, pointer coordinates or event timing. Raw aggregate-only result: `/tmp/pi-cu-drop-evidence/foreground-provenance-pi.jsonl`.
|
|
1167
|
+
|
|
1168
|
+
Source inspection of the Pi focus path shows the background action calls `AutomationElement.SetFocus` after establishing the activity observer; no explicit keyboard `SendInput` is present in that branch. This does not establish what the UIA proxy, operating system, another process or driver may do. The opt-in `--provenance --direct-uia` control prepares the same owned target using Pi, then uses a separately gated managed UIA client for **only** the focus action, collecting aggregate observer counters before and after that gate and during preparation. It is not a Pi focus call or a DSH comparison. Marker/injected flags cannot identify event origin. The control can change foreground, requires an authorized idle desktop, and retains owned processes if direct-action settlement is uncertain; its first run is recorded below.
|
|
1169
|
+
|
|
1170
|
+
A subsequent authorized direct managed UIA control reached its identity-checked `ready` phase and received the focus gate, but its stdout closed before the expected `sent` response. The runner discarded the child's stderr and did not record its PID or exit status, so whether `SetFocus` ran and why the response was absent remain unknown. It retained its observer, worker and fixture processes. Read-only inspection later found the direct PowerShell caller and both disposable target fixtures had exited; after verifying the owned runner identity and no direct caller, the retained runner was stopped. A separate OS check confirmed the observer, worker and observed helpers exited and the inspected keys/buttons were released. No automatic replay occurred. Raw outcome: `/tmp/pi-cu-drop-evidence/foreground-direct-uia.jsonl`; the retained temporary folder is kept for investigation.
|
|
1171
|
+
|
|
1172
|
+
The diagnostic now retains bounded stderr, child PID, phase, exit/signal and marker evidence. A missing marker, nonzero/unknown exit or signal remains unknown completion and retains owners. An explicit post-`SetFocus` return marker plus successful caller exit establishes the caller boundary only, not the origin of global input or all possible provider behavior. These changes are unvalidated by a further live action.
|
|
1173
|
+
|
|
1174
|
+
After the caller-reporting correction, a second authorized direct UIA control reached the gated focus call. It captured PowerShell exit code 1 and `SetFocus` error `Target element cannot receive focus`; the success marker was absent. The test retained its owner because successful completion was not confirmed. After independently confirming the direct caller had exited and checking the retained runner identity, the runner was stopped; its observer, fixtures and worker then exited, and a separate OS check found inspected keys/buttons released. The failure is a direct UIA control observation, not a Pi/DSH pass or a source attribution for earlier injected events. No input was replayed. Raw result: `/tmp/pi-cu-drop-evidence/foreground-direct-uia-revised.jsonl`; retained temporary folder kept for investigation.
|
|
1175
|
+
|
|
1176
|
+
The failing direct control used Windows PowerShell's default apartment; the Pi native UIA bridge declares `[MTAThread]`. A non-UI read-only probe on this Windows host observed PowerShell's default as STA and `-Mta` as MTA. Microsoft's [PowerShell documentation](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_powershell_exe?view=powershell-5.1) documents the default, and its [UI Automation threading guidance](https://learn.microsoft.com/en-us/windows/win32/winauto/uiauto-threading) recommends a separate MTA thread for specific client scenarios. The direct control now has an opt-in `--direct-mta` variant that records its actual apartment before the gate and refuses focus if requested MTA is not observed. This is a testable difference, not proof of the exception's cause. Both cases require an authorized idle desktop and preserve the existing uncertain-settlement rule; the later MTA run is recorded below.
|
|
1177
|
+
|
|
1178
|
+
A further authorized direct control confirmed its PowerShell thread was MTA, matching the apartment declared on Pi's native helper main thread, but `SetFocus` still returned `Target element cannot receive focus` and exited code 1 without the success marker. The owned runner retained processes until the exited caller was confirmed and the runner was stopped; a separate OS check found the owned observer, fixtures and worker exited and checked keys/buttons up. Matching apartment type alone did not resolve this direct-control failure and does not identify the reason Pi's public action behaved differently. No input was replayed. Raw result: `/tmp/pi-cu-drop-evidence/foreground-direct-mta.jsonl`; retained temporary folder kept for investigation.
|
|
1179
|
+
|
|
1180
|
+
Source comparison identifies additional differences between these separate runs. Pi's `find` walks from the root HWND and stores the observed `AutomationElement` by runtime ID in its persistent native helper; `focus` revalidates that ID, owning root and enabled state, then uses that stored object. The direct PowerShell control instead creates a fresh element from the Edit HWND in a new process and validates HWND and PID; it did not record or compare runtime IDs. Pi also initializes its activity guard and process DPI awareness, while the direct control does not. [Microsoft's UI Automation guidance](https://learn.microsoft.com/en-us/windows/win32/api/uiautomationclient/nf-uiautomationclient-iuiautomationelement-getruntimeid) treats runtime IDs as opaque, desktop-scoped comparison values that can be reused. These are source-level and setup differences, not proven causes: the Pi and direct results came from different fresh fixture instances, and neither test identified the source of the two injected key events. No additional focus action was performed for this comparison.
|
|
1181
|
+
|
|
1182
|
+
The pending `--dialog --provenance` variant of `test:reference:focus-foreground` prepares a fresh owned target and separate prior foreground process. It invokes an owned button through the public semantic invoke seam with physical click fallback explicitly disabled; the fixture opens a nonmodal owned dialog and requests foreground programmatically. Independent fixture observations verify the dialog HWND, owner and PID, its visibility, post-action foreground and input tick. Aggregate hooks record no keys, text or coordinates; input changes make the result inconclusive. This tests only the scoped owned-dialog case, not user interruption, physical menu selection or general restoration. It can change foreground and requires an authorized idle desktop. The dialog variant starts its owned fixtures with explicit-stop-only lifetime; other fixture users retain their existing timeout. After dispatch, failed or inconclusive observation retains the controller and fixtures with a referenced coordinator keepalive for separately verified cleanup; the test does not replay. The no-input retention regression verifies the coordinator remains alive without stdin, but live uncertainty/cleanup has not been exercised. Fixture compilation and offline plan/evidence checks passed; the live variant is unrun.
|
|
1183
|
+
|
|
1184
|
+
### Owned-dialog foreground comparison
|
|
1185
|
+
|
|
1186
|
+
On an authorized idle desktop, fresh Pi and pinned DSH fixtures each invoked an owned nonmodal dialog without physical keyboard/mouse input. Independent observations confirmed the visible dialog's HWND, owner and process ID, and showed the dialog remained foreground across four post-action samples. Last-input tick and aggregate hook counters were unchanged during both runs. Each runner reported cleanup, and an independent process check found the owned fixture/observer processes gone and inspected keys/buttons released. This is one paired owned-dialog case; it does not establish user-interference, menus, external dialogs or every restoration path. Raw results: `/tmp/pi-cu-drop-evidence/dialog-pi.jsonl` and `dialog-reference.jsonl`.
|
|
1187
|
+
|
|
1188
|
+
A separate pending `--menu --provenance` variant of `test:reference:focus-foreground` prepares two owned processes and invokes a fixture button without click fallback. The button programmatically opens an owned Windows Forms `ContextMenuStrip`; the independent fixture oracle records its HWND, source control, PID, native visibility and item count, as well as [GUI thread menu-mode flags](https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-guithreadinfo). Foreground/root and input observations are recorded separately. A pass requires the same owned menu to be independently observed visible with Windows menu mode during each post-action sample, target-process foreground and no observed input interference. Foreground and menu state are sampled successively, not atomically. A visible managed strip without that flag is explicitly inconclusive; it must not be described as a native menu-mode pass. The fixture may change foreground and has an explicit-stop lifetime. After uncertain dispatch or observation, the runner retains its owned processes with a referenced keepalive and never replays. This menu case is distinct from the owned-dialog comparison; its first Pi run is recorded below. Further live runs require an authorized idle desktop. It does not cover physical menu selection or user interference.
|
|
1189
|
+
|
|
1190
|
+
### Owned-menu observation
|
|
1191
|
+
|
|
1192
|
+
An authorized Pi owned-menu invocation returned successfully and the fixture observed a visible one-item managed `ContextMenuStrip` with consistent ownership across four samples. The Windows GUI menu-mode flag was false at each observation, so the native-menu criterion is **inconclusive**, not a failure or pass. Input tick and aggregate event counts remained unchanged. The runner retained its owned processes on this unconfirmed result. After confirming the invoke had returned, the identified runner was stopped; an independent process check found the observer, fixtures, worker and observed helpers exited, and inspected keys/buttons released. DSH was not run. This managed-menu fixture cannot establish native menu-mode acceptance. Raw result: `/tmp/pi-cu-drop-evidence/menu-pi.jsonl`.
|
|
1193
|
+
|
|
1194
|
+
Source analysis found a possible timing mechanism but did not establish that it caused this result. Pi's `NativeButton` and the pinned reference both post `BM_CLICK` and then synchronously send `WM_NULL`; Pi ignores the return value of that follow-up call. Microsoft documents that [sent messages are dispatched before posted messages](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getmessage), so the `WM_NULL` response does not guarantee the earlier posted click handler completed before foreground restoration was evaluated. The observed `foreground: unchanged` followed by the target coming forward is consistent with that ordering, but no in-handler timing was captured. Synchronously sending `BM_CLICK` instead would change the reference path and could block on modal UI. Do not treat either a repair or the source difference as proven until the relevant behavior can be established; planned tests are deferred at the user's request.
|
|
1195
|
+
|
|
1196
|
+
A subsequent native Win32-menu preparation run on 2026-10-31 stopped during Pi's prior-window activation: Windows returned `activated: false` with foreground refusal. Before any menu action, the aggregate observer recorded unmarked mouse and injected key activity of unknown source. The runner classified the case blocked and reported cleanup; an independent OS check found both owned fixture processes and the observer gone and inspected keys/buttons released. DSH was not run, and no native-menu behavior is claimed. Raw result: `/tmp/pi-cu-drop-evidence/native-menu-pi.jsonl`.
|
|
1197
|
+
|
|
1198
|
+
### Paired window management
|
|
1199
|
+
|
|
1200
|
+
On 2026-10-30 the user confirmed Windows was unlocked and idle. The reviewed `test:reference:management` runner used separate uniquely named owned fixtures for Pi and the pinned DSH reference, serialized under the WSL live-test lock. Both completed all eight checks: launch, fixture survival after controller disposal, wrong-owner refusal, movement, activation, close veto, close and stale identity. Foreground, HWND/PID, bounds and process creation identity were observed independently of each tool result. Each activation matched the fixture HWND/PID; fixture events confirmed veto and subsequent close. Both reports recorded controller/fixture cleanup confirmed, and a separate OS process check found no owned test runner or fixture afterward. No keyboard, mouse or clipboard input was dispatched. Raw fixture-only reports and staged source hashes are in `/tmp/pi-cu-followup-evidence/management-{pi,reference}.json` and `window-management-provenance.json`.
|
|
1201
|
+
|
|
1202
|
+
This was one paired run of the named cases. A later extended run on fresh fixtures passed all 11 checks on both engines, including a distinct same-process distractor, observed restoration to that owned foreground window after focusing the target control, and refusal of a stale HWND after a same-title replacement. The fixture focus event and OS HWND/PID observations independently verified that scoped restoration; it does not erase the earlier separate restoration discrepancy. Both fixture/controller cleanups were confirmed. User interference, menus/dialogs and broader foreground restoration remain untested here; this is not complete #30 acceptance or a real-agent recovery result. Extended raw reports and source hashes are in `/tmp/pi-cu-acceptance-evidence/window-extended-{pi,reference}.json` and `staging-provenance.json`.
|
|
1203
|
+
|
|
1204
|
+
### Paired native element scroll
|
|
1205
|
+
|
|
1206
|
+
The existing separately gated runner now verifies matched background distance on fresh owned controls fixtures: `deltaY: 240` moves **both DSH 0→30 and Pi 0→30**, with Windows configured for three wheel-scroll lines. DSH reports `background:WM_VSCROLL`, Pi `native_scroll`; foreground HWND/PID and last-input tick remain unchanged, and controller/fixture cleanup is confirmed. This replaces the earlier Pi 0→10 mismatch for that case. The runner's public API permits fallback, but neither observed action used it. Raw outcomes and source hashes are in `/tmp/pi-cu-quiet-scroll-live/native-paired.log` and `native-paired.json/accessibility-comparison.json`; no personal window content was retained.
|
|
1207
|
+
|
|
1208
|
+
Quiet element scrolling now reuses the existing independent stop event, private input-preparation acknowledgment and cleanup promise. A portable public-worker regression first failed because element scroll bypassed preparation; it now passes acknowledgment, late acknowledgment, stop/race, owner-crash and unconfirmed-cleanup checks alongside the existing pointer case. The private background discriminator is appended only after public argument validation. Physical-control presentation is not started by quiet dispatch, and uncertain failure cannot trigger a fallback/replay.
|
|
1209
|
+
|
|
1210
|
+
`npm run test:native:nullable-uia -- --quiet-scroll` extends the existing owned provider fixture. With current wheel-lines three, the normal `deltaY: 240` call issued six ScrollPattern steps and left presentation invisible. The fixture then held the first call of another scroll. Caller cancellation returned while an independent competing worker still received `COMPUTER_USE_BUSY`. After test-only provider release, exactly the one already-dispatched effect settled, **zero subsequent scroll calls** occurred, and settlement permitted ownership release/new work. The final-candidate log is `/tmp/pi-cu-quiet-scroll-live/provider-integrated.log`. This proves prevention of later dispatch and ownership retention through the held call; it does not claim reversal or synchronous cancellation of a remote app effect. Missing cleanup acknowledgment retains the existing fail-closed lease.
|
|
1211
|
+
|
|
1212
|
+
Independent review accepted repair `b7b3675`, merged as `be7d25d`. The reviewer reran `npm run check`: 124 passed, one skipped (`/tmp/pi-cu-quiet-scroll-live/check-merger.log`). Candidate build and package/documentation checks passed with 84 entries; the paired native artifact's controls hash matches the final source. No additional live run was needed for review.
|
|
1213
|
+
|
|
1214
|
+
Reference source semantics are preserved: Windows wheel-lines or page setting, midpoint-to-even rounding, vertical before horizontal, 100-step line-mode cap and uncapped page count. Cancellation checks occur before each dispatch and after provider return, rather than pretending a step cap bounds a blocking provider. Other wheel settings/page mode, native-message timeout edge cases, inaccessible/reused targets and broader provider acceptance remain #28 work. The scoped checks do not close #28 or the physical/manual stop requirements of #31.
|
|
1215
|
+
|
|
1216
|
+
A separate fixture-only locked-clipboard probe confirmed OS lock ownership and available → busy → available using a second process, with unchanged clipboard sequence and confirmed fixture exit. It read and replaced no clipboard content, dispatched no input and did not call either engine. It establishes the fixture prerequisite only; locked-clipboard tool behavior remains untested. The five-second fixture watchdog depends on its message loop remaining responsive. Raw output and fixture hashes are in `/tmp/pi-cu-acceptance-evidence/clipboard-lock.jsonl` and `staging-provenance.json`.
|
|
1217
|
+
|
|
1218
|
+
Run `npm run test:native:process-containment` with Windows Node to check the separate test-only process containment prerequisite. It requires Windows and the .NET Framework 64-bit C# compiler at `%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\csc.exe`. The check uses disposable processes and files; it does not access the desktop or clipboard or dispatch input. A passing result does not establish locked-clipboard behavior for either engine.
|
|
1219
|
+
|
|
1220
|
+
**Still open:** diagnosis/regression of DSH indexed preservation and newer-copy differences; Pi/DSH behavior with locked clipboard, broader clipboard formats, full TSF/IME state and control-character isolation; cross-application drag/drop, user interference, menus/dialogs and broader foreground restoration; real Esc/custom shortcut; mixed DPI/layouts and other manual release gates. #26/#27/#30/#31 remain open. These results do not complete #35/#36 real-agent recovery or #37 mechanism diagnosis.
|
|
1221
|
+
|
|
1222
|
+
## Pi chords and editor focus acceptance
|
|
1223
|
+
|
|
1224
|
+
On 2026-11-05, the existing native text runner's opt-in `--chords` case exercised the registered Pi tools through the actual Windows worker from WSL. It used only a disposable native RichEdit and separate native Edit fields; no model, clipboard, personal document or browser was involved. The fixture independently reported complete seeded text, selection/caret, native foreground/focus, held-key count and keyboard layout after input.
|
|
1225
|
+
|
|
1226
|
+
- From a verified unselected caret, Ctrl+A selected all eight characters, then exact typing replaced them with `ABCDE`. Home, Shift+Right and Backspace selected/deleted the first character; End and typing produced `BCDE!`. Ctrl+Shift+Home selected all five characters, then Home/Right established caret 1 without a selection.
|
|
1227
|
+
- Explicit focus to the secondary field followed by preserve-mode input produced `secondary P` without changing the primary. Main-mode input chose the primary RichEdit, confirmed its exact focus handle before dispatch and produced `B MCDE!` at its retained caret. The secondary stayed unchanged.
|
|
1228
|
+
- Read-only text, disabled focus and deliberately wrong PID were refused. Both restricted values remained unchanged. Each input call required an action-matched cleanup acknowledgment and independent released-key observation. Settlement reported exclusive control false and zero held keys, with both edited values preserved; the fixture and worker retired normally.
|
|
1229
|
+
- The existing [human handback/continuation receipt](#wsl-pi-human-handback-and-continuation) already proves real human `abc` editing and fresh-target continuation to exact `xabcx`; no duplicate human test was requested. Reuse the [#30 app/foreground outcomes](#workspace-decision-acceptance) and earlier [Unicode cases](#unicode-mechanism-investigation).
|
|
1230
|
+
|
|
1231
|
+
Earlier failures remain failures: the first assertions incorrectly assumed Right collapses a selection to its end; the fixture instead advanced to caret 1. Plain WinForms TextBox Ctrl+A attempts received the modifier/key messages but did not change selection; initial focus sometimes selected all before the chord, giving a misleading apparent pass. The final RichEdit case explicitly clears that selection before testing the supported shortcut. This does not claim a plain-TextBox shortcut repair. A separate held left Windows key, which this suite never sends, was cleared by the user only after owned test processes were retired; those interrupted attempts are not accepted results.
|
|
1232
|
+
|
|
1233
|
+
The main-focus investigation also observed safe `TARGET_FOREGROUND_CHANGED`/`TARGET_FOCUS_CHANGED` refusals during a focus transition. The repair confirms a requested field before physical text, rather than immediately capturing possibly previous focus; remembered recovery cannot overwrite an explicit request. The clean no-probe regression and a fresh run after the reviewed remembered-focus guard passed. One intervening attempt failed at its first find with `spawn UNKNOWN`, before input; the passive regression and fresh physical run then passed without a process-start retry added to production. No chord timing or 50 ms text pacing changed. The new confirmation timeout and cancellation paths are source-reviewed, not separately forced live failures; existing cancellation/identity safeguards remain. Keyboard layout was `4040404`; complete TSF/IME state is unknown, and no universal IME support is asserted.
|
|
1234
|
+
|
|
1235
|
+
Receipts: `/tmp/pi26-chords-{reset,refusal,focus-ack,command,multiline,multiline2,rich,final,accepted,reviewed}.log`; each failed or successful run retains its actual verdict. Temporary key/message probes were removed. Reproduce with `npm run build`, then Windows Node `tests/native-text.mjs --chords` with `PI_CU_DEDICATED_INPUT_DESKTOP=1`, while holding the shared live-test lock. Default `test:native:text` remains passive and clipboard-free. This completes #26's scoped chord, editor-focus and reused human-handback clauses; it does not declare the release ready.
|
|
1236
|
+
|
|
1237
|
+
Final #26 checks: configured `npm run check` passed 178 tests with one skipped (179 total); build and the existing passive text regression passed. The 90-entry package and all documentation links passed validation. The initial check stopped at an import-order lint error before tests; it was corrected before the passing check.
|
|
1238
|
+
|
|
1239
|
+
## Pi targeting and accessibility reconciliation
|
|
1240
|
+
|
|
1241
|
+
The #28 reconciliation on 2026-11-05 reuses retained Pi receipts, not DSH outcomes or new blanket test claims. The authoritative cleaned baseline is `/tmp/pi-cu-accessibility-final-baseline/accessibility-comparison.json` (`cleanupConfirmed: true`). Earlier `evidence/` and `target-bound/` directories include failed assertions or incomplete cleanup and are not substituted for that final baseline.
|
|
1242
|
+
|
|
1243
|
+
| #28 clause | Retained evidence and disposition |
|
|
1244
|
+
| --- | --- |
|
|
1245
|
+
| Discovery, ambiguous selectors, snapshot/tree, find/info | Final baseline Pi cases `native.discovery`, `native.ambiguous`, `native.snapshot`, `native.tree`, `native.find-info` passed. [Lifetime enumeration](#window-lifetime-reference-acceptance) additionally exercises proof loss inside the real enumeration callback. |
|
|
1246
|
+
| Native focus/invoke/value, restricted and unsupported controls | Baseline Pi `native.focus`, `native.invoke`, `native.set-value`, `native.read-only`, `native.disabled`, `native.unsupported` and final preservation passed. The historical `native.focus-restoration` failure stays failed; [#30 workspace/foreground](#workspace-decision-acceptance) owns the subsequent supported behavior, with [#26 editor-focus](#pi-chords-and-editor-focus-acceptance) checked separately. |
|
|
1247
|
+
| Native Chromium discovery/find/info/focus/value/invoke | `/tmp/pi-cu-native-chromium-live/paired/accessibility-comparison.json`: all four Pi cases passed with independent page effects and cleanup true; [scope](#native-chromium-uia-action-acceptance). No browser-protocol input or universal provider claim. |
|
|
1248
|
+
| Sparse, budget, unknown and failing providers | Final baseline includes the stable small fixture plus node/depth/time-budget and unknown-type cases. `/tmp/pi-cu-provider-retirement-final/accessibility-comparison.json`: Pi provider fault/hang cases passed, with cleanup true. [Actual provider-unavailable](#passive-provider-unavailable-probe) supplies the explicit partial/providerError path; it is not replaced by a successful tree from a normalized exception. |
|
|
1249
|
+
| Element scrolling | `/tmp/pi-cu-quiet-scroll-live/native-paired.json/accessibility-comparison.json`: Pi native scroll passed with cleanup true. [Scroll evidence](#paired-native-element-scroll) adds custom-provider effects, cancellation, no later dispatch and fresh-operation recovery. Other wheel settings/page mode and native-message timeout edges remain unexercised configurations; no user global wheel setting was changed. |
|
|
1250
|
+
| Wrong/stale/unseen targets and lost lifetime proof | Baseline Pi wrong-owner/unseen/stale cases passed. [Lifetime receipts](#window-lifetime-reference-acceptance) cover destruction, marker removal, conflicting selectors, reader/worker restart, authority mismatch, actual expiry and provider-time proof loss. Different replacement handles are not proof of numeric handle reuse. Immediate post-close `targetState: absent` remains source-reviewed, not separately observed live; actual posted close plus independently observed disappearance passed. |
|
|
1251
|
+
| Global discovery, launch and Pi host integration | [#30 registered-tool workspace sequence](#default-app-and-workspace-acceptance) passed actual private-association Explorer launch, fresh window observation, activation lifetime-witness propagation and element-only intended-root actions. [Ordinary Pi workspace actors](#workspace-decision-acceptance) used real global listing, filtered to owned windows before model delivery. `launch_app` deliberately reports dispatch rather than treating a returned process or new window as a verified target; fresh discovery establishes identity. Both host entry paths share the Windows worker/reference implementation; [runtime checks](runtime.md#verification) retain their recorded native/WSL scopes, not every provider case on both hosts. |
|
|
1252
|
+
|
|
1253
|
+
Two environment prerequisites remain **unavailable, not passed**: genuine full-HWND/same-PID replacement after the bounded 18,244-window probe, and verified UIPI denial after the bounded owned-token/desktop probes. Their [original receipts](#window-lifetime-reference-acceptance) preserve exact conditions and cleanup. No larger collision search, elevation, ACL change or synthetic-denial substitution is queued. On 2026-11-05, after the safety purpose and bounded probe results were explained, the user explicitly accepted these two cases as first-release test limitations and agreed to close #28. They remain unverified; this disposition removes their release-test gate, not the identity/access safeguards. #28 is complete for its reconciled scope. No additional collision search, privileged setup or Windows test is required by this disposition.
|
|
1254
|
+
|
|
1255
|
+
## Native document workflow
|
|
1256
|
+
|
|
1257
|
+
#35 preparation on 2026-11-05 extends the existing workspace actor, native window-management runner and fixture with `--scenario document`; no runtime code, new tool or framework was added. The outcome-only task asks for one task document in the existing owned app, an initial multilingual save, an append/save, and preserved original work. Physical typing/pointer/clipboard and fallbacks are disabled; UIA value/invoke actions use observed owned controls.
|
|
1258
|
+
|
|
1259
|
+
The model-free preflight passed through registered Pi tools and the real Windows worker from WSL: exactly one new tab in the same root, initial save `Pi document 中文 café 😀`, final editor/file `Pi document 中文 café 😀 — appended`, original editor/file both `original work 1`, selected task, independently observed visible/nonminimized foreground window, and fixture/worker cleanup. Its state is read on the fixture UI thread and published atomically; file bytes and ordered save journal are separate observations. Receipt: `/tmp/pi35-document-preflight.log`, `/tmp/pi-workspace-model-uPb2ty/reset-1-mEOBG8/owner.json`. Windows dependencies resolved from this exact checkout; build passed. Portable red/green checks reject overwritten originals, editor-only success, missing intermediate save, hidden/background results and unsafe input escalation. Both review axes are clear after correcting atomic publication and visibility/foreground evidence. Configured checks passed 181 tests with one skipped; build and the 90-entry package/document links passed.
|
|
1260
|
+
|
|
1261
|
+
Safe plan: `npm run test:pi:workspace -- --scenario document --plan`. Serialized model-free setup/outcome check: `flock -n /tmp/pi-cu-live-tests.lock npm run test:pi:workspace -- --scenario document --preflight`. Model acceptance uses `--run --runs 3` only with an explicit episode allowance; the user approved up to three on 2026-11-05, stopping at the first failure. Three approved fresh real-Pi resets on `9571295` subsequently passed this creation/preservation/save scenario. All effective assistant rows were OpenAI `gpt-6.1-sol`, low reasoning; the source/compiled manifests matched across resets. Each trace mutated only New task tab → Task editor → Save task → Task editor → Save task; no mutation targeted the original editor. Independent state, exact original/final files and ordered saves passed, as did selected/visible/nonminimized/foreground checks, unhalted guards, nonaborted settlement, Pi/fixture exit 0 and fixture cleanup. Independent spec review accepted this first #35 clause. Reports/traces are `/tmp/pi-workspace-model-JOh9Ow/reset-{1-3}-*/{report.json,tools.jsonl,trace.jsonl}`; aggregate: `/tmp/pi35-document-acceptance.json`. All three approved episodes are used. This completes creation/preservation/save, not full #35: native controlled recovery and human-handback outcomes remain; earlier append/save successes retain their original scope.
|
|
1262
|
+
|
|
1263
|
+
### Native replacement and partial-observation recovery preparation
|
|
1264
|
+
|
|
1265
|
+
The existing document scenario now has `--scenario document-recovery`, with the same outcome-only task. Its private actor wrapper caps only the first native tree/snapshot request at one node; the real worker produces the partial observation, and the actual cap/result metadata are audited. It does not fabricate a successful result or tell the model a recovery procedure. On the first save the owned app replaces and disposes its task editor, carrying forward the saved value; the replacement HWND is created while the old control is live, so their distinct numeric identities can be independently checked. The original document stays untouched.
|
|
1266
|
+
|
|
1267
|
+
The model-free preflight passed on 2026-11-05: actual `nodeCount: 1`, `truncated: true`, reason `maxNodes`; after an independently witnessed replacement, old-ID inspection returned `WINDOWS_ERROR: STALE_ELEMENT: control no longer exists; observe again`. Fresh lookup/mutation/save produced the exact final task file/editor, preserved the original file/editor, retained visible foreground and confirmed cleanup. Receipt: `/tmp/pi35-recovery-preflight-final.log`, `/tmp/pi-workspace-model-thoKhX/reset-1-goT0NY/owner.json`. The initial preflight failed before startup on a fixture-only C# local-name collision; `/tmp/pi-workspace-model-8FNRLt/reset-1-R4LhlT/fixture.stderr` preserves that setup failure. No application fix or paid episode was used.
|
|
1268
|
+
|
|
1269
|
+
Acceptance additionally requires the actual partial receipt and successful final mutation through a freshly observed replacement-editor ID, alongside every base document/preservation/save check. Re-observation may proactively recover without attempting the stale ID; claim stale-error recovery only when that error appears in a model trace. Both review axes cleared the preparation after requiring a witnessed replacement before the stale probe and checking its precise diagnostic. Configured checks passed 183 tests with one skipped; package/document-link validation passed (90 entries). Plan and serialized preflight use the document commands above with `--scenario document-recovery`. The user approved three recovery episodes, which ran on `a119e4b` and all completed the actual workflow correctly. Effective assistant metadata was OpenAI `gpt-6.1-sol`, low reasoning; source/compiled manifests matched. Each received actual one-node truncation, observed a replacement editor ID after its initial write/save, then successfully mutated that new ID. Independent files/editor state, initial/final save chronology, untouched originals, selected visible foreground task, unhalted guards, nonaborted settlement, Pi/fixture exit 0 and cleanup passed. No trace encountered a stale-element error: accept partial-observation and replacement recovery, not stale-error recovery.
|
|
1270
|
+
|
|
1271
|
+
The original series exited nonzero at reset 3 because its compact post-save tree omitted optional `nativeWindowHandle`. The old oracle required that field despite the new opaque ID and correct independent effects. The original `report.json` stays `pass: false`; it is not overwritten. A collector-only red/green repair requires an observed initial-editor ID, successful observed Save, then a different freshly observed editor ID before final mutation. Explicit HWND metadata, when present, must match its role; later contradictions invalidate the verdict. No identity is inferred from numeric AutomationId. Both review axes cleared the correction; independent spec review accepted the retained evidence. Re-evaluation of all three unchanged audits passed with the final conflict checks; no new model, Windows action or production change was needed. Configured checks passed 183 tests with one skipped.
|
|
1272
|
+
|
|
1273
|
+
Original reports/audits: `/tmp/pi-workspace-model-qn8son/reset-{1-3}-*/{report.json,tools.jsonl,trace.jsonl}`. Separate accepted-disposition/source-hash receipt: `/tmp/pi35-recovery-oracle-review.json`; red/green logs: `/tmp/pi35-{compact,conflict}-oracle-{red,green}.log`. All three approved recovery episodes are used. Cancellation/human-handback remains a separate #35 clause; #31's mechanism evidence is reused rather than repeating physical stop-key tests.
|
|
1274
|
+
|
|
1275
|
+
### Native cancellation and handback continuation
|
|
1276
|
+
|
|
1277
|
+
The remaining #35 outcome uses the existing native workspace app and actor with `--scenario document-handback`. Setup creates and saves one task document through registered Pi tools, cancels a pending passive wait, requires a same-stopped-operation edit to be refused, settles the operation and checks control status. It then disposes the original worker and independently confirms its PID/creation/executable identity is absent or replaced before allowing a labelled application-side stand-in edit. A fresh real-Pi operation must read that unsaved edit and append/save without creating another document or changing the original.
|
|
1278
|
+
|
|
1279
|
+
This is composed acceptance: #31 already supplies [actual human editing/explicit continuation](#wsl-pi-human-handback-and-continuation) and [physical stop/control proof](#control-interruption-acceptance). Here cancellation is scripted registered-tool setup, `HUMAN` is explicitly a fixture stand-in, and the model exercises native continuation. It does not claim an interrupted model episode, a new real-human edit, one continuous model–human–model session or new physical-control reacquisition. The preflight only proves a pending caller was cancelled and safely retired; it does not independently time entry into the worker's wait.
|
|
1280
|
+
|
|
1281
|
+
The 2026-11-05 model-free preflight passed cancellation (`HANDOFF_WAIT_CANCEL`), stopped-operation refusal, settlement/release, independently pinned worker retirement, initial disk text unchanged during the stand-in edit, and fresh read/append/save to exact `Pi document 中文 café 😀 HUMAN — appended`. The original editor/file remained `original work 1`; task selection, visibility, foreground and cleanup passed. Receipt: `/tmp/pi35-handback-preflight.log`, `/tmp/pi-workspace-model-PwUWWa/reset-1-S5n5tK/owner.json`. Both review axes cleared the setup after changing process-retirement comparisons to validated identity fields, independent of JSON key order. The shared basic-document preflight passed after observation-helper reuse; replacement-recovery regression is recorded alongside it in `/tmp/pi35-handback-{document,recovery}-regression.log`.
|
|
1282
|
+
|
|
1283
|
+
The acceptance oracle rejects missing cancellation/release/retirement, saved or lost stand-in edits, mutation before reading the edited value, wrong final files and original-document changes. Plan: `npm run test:pi:workspace -- --scenario document-handback --plan`. Model-free Windows check: the same command with `--preflight` under the shared live-test lock. Paid continuation episodes use `--run --runs 3` only with an explicit allowance. The user approved three, and all three fresh resets on `071a8b5` passed. Every model first read the unsaved `HUMAN` value and then preserved it in the final mutation/save through that same observed editor ID. The only mutations were Task editor and Save task: no new tab or original-document edit. Exact saved files, original preservation, selected visible foreground task, unhalted guards, nonaborted settlement, Pi/fixture exit 0 and cleanup passed. All effective metadata was OpenAI `gpt-6.1-sol`, low reasoning, with identical source/compiled manifests. Independent spec review accepted the three traces and scoped #35 closure through the composed receipts.
|
|
1284
|
+
|
|
1285
|
+
Reports/audits: `/tmp/pi-workspace-model-ybf8hP/reset-{1-3}-*/{report.json,tools.jsonl,trace.jsonl}`; aggregate/source-hash verification: `/tmp/pi35-handback-acceptance.json`. All three approved continuation episodes are used. Configured checks passed 185 tests with one skipped; build, package/document links and both affected document preflights passed. This completes #35's native creation/preservation/recovery/continuation scope, composed with #31's accepted actual human/control evidence, without a new real-human or physical-control claim. No production tool or runtime behavior changed; release acceptance remains with the other owners.
|
|
1286
|
+
|
|
1287
|
+
## Automated border lifecycle
|
|
1288
|
+
|
|
1289
|
+
On 2026-11-05 the user requested automated preparation first and identified the current Windows session as local. The passive inventory (`test:indicators -- --layout-only`) reported DISPLAY1 at `(0,0,2560,1080)` and DISPLAY2 at `(2560,-61,1920,1080)`, both scale 1. No overlay was shown, control was unarmed, and no display setting was changed and no desktop pixel was read. Receipt: `/tmp/pi-display-inventory.log`.
|
|
1290
|
+
|
|
1291
|
+
The existing indicator runner's bounded `--lifecycle-only` case passed with disposable settings and no dispatched keyboard/mouse input. A deliberately invalid target acquired the normal required control lease and was refused before input. The same listener/operation retained visible, error-free frames across a read/gap, disabled optional visuals, remote-visibility true→false, an idle interval longer than the saved 200 ms preference, and an invalid settings update. Both frames stayed visible when optional bars/tag were disabled. Settlement hid them and released exclusive control; a new operation used a distinct cancel event and showed the frames again; explicit stop hid them and refused another same-operation action. Windows reported affinity application success, which is not third-party recorder acceptance. `/tmp/pi-border-lifecycle.log` retains all eight actual status samples.
|
|
1292
|
+
|
|
1293
|
+
This is new presentation evidence, composed with [#31 actual human/control acceptance](#control-interruption-acceptance); no new physical stop or human-input proof is claimed. Own capture pixel exclusion, higher/mixed DPI, dynamic display changes and actual recording remain separate. Safe plans run without compiled code or Windows: `npm run test:indicators -- --layout-only --plan` and `--lifecycle-only --plan`. Live modes retain the shared desktop lock. The affected default indicator protocol was checked with its optional desktop-preview capture explicitly disabled; receipt `/tmp/pi-indicators-protocol-regression.log`.
|
|
1294
|
+
|
|
1295
|
+
The initial capture/DPI draft was withheld because the default screenshot path permits full-desktop/occluded-region fallback. The user selected optional window-only capture on 2026-11-06; its implementation/evidence is recorded below. The earlier `/tmp/pi-display-capture-draft.patch` and `/tmp/pi-display-capture-draft-test.ts` are superseded by the current runner and [display/border baseline](#display-and-border-baseline). They are not runnable acceptance instructions or passing evidence. No private desktop pixels were acquired for that draft.
|
|
1296
|
+
|
|
1297
|
+
Both review axes cleared the shipped indicator-only changes. Configured checks passed 186 tests with one skipped; build and package/document-link validation passed (90 entries). Receipts: `/tmp/pi-display-lifecycle-check.log` and `/tmp/pi-display-lifecycle-package.log`. No production runtime or capture behavior changed.
|
|
1298
|
+
|
|
1299
|
+
### Optional window-only capture
|
|
1300
|
+
|
|
1301
|
+
The user approved the native screenshot opt-in `windowOnly: true` on 2026-11-06. The existing capture module bypasses all screen-copy paths in this mode, using PrintWindow or lifetime-validated HWND-bound WGC. Desktop scope/browser-tab combinations and invalid option types are rejected. Hidden/minimized or unavailable surfaces return failure without a fallback image. The default, snapshot and OCR contracts remain unchanged; see [supported capture behavior](windows.md).
|
|
1302
|
+
|
|
1303
|
+
The new `test:native:capture -- --window-only` case first failed with `INVALID_ARGUMENTS` before implementation (`/tmp/pi-window-only-red.log`), then passed through the registered Pi screenshot tool. Actual PNG pixels were green `(20,150,80)` for both normal and magenta-covered owned targets via PrintWindow, and black `(0,0,0)` via WGC when PrintWindow treated the blank render as unavailable. A strict capture retained its observed window reference. The independently restored fixture confirmed visible/non-minimized preconditions before separate minimized and hidden-only refusals, both without an image. An initial green sequence hid an already-minimized target; review required and the final run supplied the independent hidden-only case. Final receipt: `/tmp/pi-window-only-final.log`.
|
|
1304
|
+
|
|
1305
|
+
The affected existing `--lifetime-only` mode also passed green/covered/black pixels, bound WGC, image dimensions/mapping and wrong-owner refusal (`/tmp/pi-window-only-default-regression.log`). This regression deliberately excludes the default runner's desktop-fallback cases to preserve current-session scope. No physical input, global display changes or desktop captures were requested. Windows Node resolved the runtime dependency from this exact WSL checkout before execution. The first Node script-shortcut attempt did not launch the test; direct Windows Node ran the configured runner. An initial sandboxed portable launch failed at the child-process level and was stopped; the configured checks outside that restriction passed 186 tests with one skipped (`/tmp/pi-window-only-check.log`). These results establish the new safe capture option, not overlay exclusion or actual mixed-DPI/recording acceptance.
|
|
1306
|
+
|
|
1307
|
+
Both review axes cleared the change after the hidden-only test correction. Build and package/document-link checks passed (90 entries); package receipt `/tmp/pi-window-only-package-final.log`. The initial package subprocess failed under sandbox restrictions; the same configured check passed outside that restriction. No new model episodes or stop-key tests were used.
|
|
1308
|
+
|
|
1309
|
+
### Display and border baseline
|
|
1310
|
+
|
|
1311
|
+
On 2026-11-06 the user authorized preparing and running the remaining display/border checks, with monitor scaling unchanged until preparation completed. The existing capture runner now provides backend-free `--display --plan` and `--control-capture --plan` plus corresponding Windows-only live modes. The fixture opts into PMV2 only for these modes, reports actual window/monitor DPI and physical DWM geometry, and independently paints red/blue marker points. Startup/replies and owned fixture shutdown are bounded; worker control is disposed before fixture teardown. Only disposable settings and owned windows are used; the commands do not inject keyboard/mouse input or change display settings. PNGs stay in memory; receipts retain metadata and owned point RGB values.
|
|
1312
|
+
|
|
1313
|
+
Both live modes passed four samples: two current monitors, each at original width and maxWidth 80. The passive case independently matched frame bounds/origins, both image scales, rounded heights and all mapped red `(230,30,40)` / blue `(30,60,230)` point pixels. Window awareness was 2 and actual window DPI 96 on each monitor; monitor bounds were `(2560,-61,1920,1080)` and `(0,0,2560,1080)`. Foreground and frame geometry remained unchanged. Receipt: `/tmp/pi-display-final.log`.
|
|
1314
|
+
|
|
1315
|
+
The control case placed an ordinary borderless owned window at each monitor's top-left, including the negative Y origin. An invalid-target click acquired the existing control lease and was refused before input. Three guarded edge pixels independently showed the blue overlay before and after each screenshot; all corresponding PNG pixels were the fixture's green `(20,150,80)`. All four captures used strict PrintWindow. The same helper/operation stayed armed and exclusive; each call independently advanced its suspension count (1,2,3,4), returned unsuspended with a visible border, and settlement hid it and released control. The private remote-visibility setting was true so GDI could witness those owned live-border pixels. Receipt: `/tmp/pi-border-capture-final.log`. This proves sampled strict PrintWindow exclusion and lifecycle, composed with prior suspension protocol evidence; it is not new default screen-copy, OCR, WGC overlay-exclusion, remote-session or third-party recorder acceptance.
|
|
1316
|
+
|
|
1317
|
+
Preparation failures remain recorded. The new backend-free plan test initially failed (`/tmp/pi-display-plan-red.log`). The first mapping run stopped on a global input-tick change despite passing geometry/pixels (`/tmp/pi-display-baseline.log`); input activity is now diagnostic rather than attributed to the tool, while geometry/pixels and foreground assertions remain binding. The first border run lacked a visible-pixel witness (`/tmp/pi-border-capture-baseline.log`); diagnostics showed the fixture's own TopMost flag masked the border after switching monitors (`/tmp/pi-border-capture-diagnostic.log`). Removing that fixture-only flag fixed the test. Review also required a fresh per-call suspension baseline, now checked with stable helper/operation identity. No production behavior changed and no model episodes or physical stop-key tests were used. Higher/mixed DPI, topology changes and actual recording remain pending; 100% passes are not substitutes.
|
|
1318
|
+
|
|
1319
|
+
Both review axes cleared the code after those corrections. Configured checks passed 187 tests with one skipped (`/tmp/pi-display-check-final.log`); build and package/document-link validation passed (90 entries, `/tmp/pi-display-package.log`). A lint import-order failure before the final checks is retained in `/tmp/pi-display-check.log`. The affected `--window-only` mode passed with the shared bounded startup/reply/clean-exit handling (`/tmp/pi-display-window-regression.log`). Windows runtime dependencies resolved from this exact WSL checkout; production code is unchanged from `20b8060`. Subsequent human-configured scaling results are recorded below.
|
|
1320
|
+
|
|
1321
|
+
### Mixed-DPI stages
|
|
1322
|
+
|
|
1323
|
+
On 2026-11-06 the user confirmed the 1920×1080 monitor was set to 150%, with the 2560×1080 monitor left at 100%. Both unchanged runners from `03907ee` exited 0 after a fresh build and Windows dependency-resolution check from this checkout. Each supplied four passing samples, covering both monitors at native and maxWidth-80 image sizes.
|
|
1324
|
+
|
|
1325
|
+
| Configuration | Measured monitor/window DPI | Mapping | Strict PrintWindow border exclusion/control | Receipts |
|
|
1326
|
+
| --- | --- | --- | --- | --- |
|
|
1327
|
+
| 150% secondary / 100% primary | 144 / 96; window awareness 2 | Passed independent frame/origin/scales and painted points across both monitors | Passed owned blue-pixel witnesses, green capture pixels, stable helper/operation, per-call suspension counts 1–4 and settlement release | `/tmp/pi-display-150.log`, `/tmp/pi-border-capture-150.log` |
|
|
1328
|
+
| 175% secondary / 100% primary | 168 / 96; window awareness 2 | Passed all four native/reduced frame/origin/scales and painted-point samples | Passed on a fresh idle run: live-border witnesses, green capture pixels, stable helper/operation, suspension counts 1–4 and settlement release; earlier held-input refusals retained | `/tmp/pi-display-175.log`, `/tmp/pi-border-capture-175-idle.log`; earlier refusals: `/tmp/pi-border-capture-175.log`, `/tmp/pi-border-capture-175-fresh.log` |
|
|
1329
|
+
|
|
1330
|
+
The secondary retained physical bounds `(2560,-61,1920,1080)` and its working-area height changed to 1008; the primary remained `(0,0,2560,1080)`, working-area height 1032. The border case included the actual negative Y origin. This adds real mixed-DPI/window-transition evidence, not a resized-image substitute. No source/test changes, physical input dispatch, paid model episodes or global setting commands were used. The earlier 100% baseline and its failures remain intact. Both 175%/100% checks now passed, with restoration to the original 100%/100% subsequently confirmed below. The initial 200% setup request was superseded by the environment constraint below. Actual display topology/primary changes and broader capture/recording coverage remain separate.
|
|
1331
|
+
|
|
1332
|
+
On 2026-11-06 the user reported that 175% is the highest per-monitor preset available. Reaching 200% requires custom scaling, sign-out and applying the setting to both monitors. That setup is outside the current scoped session; 200% remains unavailable/untested here, not passed or inferred from 175%. The user subsequently confirmed the secondary at 175%, with the primary at 100%; original scaling was subsequently restored. No sign-out, custom scaling or live test was performed for this constraint update; it does not close #6/#20 or waive release reconciliation of missing coverage.
|
|
1333
|
+
|
|
1334
|
+
For the 175% stage, both unchanged runners used the same checkout/runtime dependencies as the accepted 150% stage. Mapping exited 0 with secondary bounds `(2560,-61,1920,1080)`, working-area height 996 and actual 168 DPI; the primary retained 96 DPI and its original bounds/work area. The border runner exited 1 on both its initial and one fresh attempt because acquisition returned `USER_INPUT_ACTIVE: release held input before control begins`, before the expected invalid-target refusal. Teardown completed without an additional error and no desktop input was dispatched in those attempts. The user then confirmed briefly using input. One fresh idle border/control run exited 0 at measured 168/96 DPI with four strict PrintWindow samples, live blue-pixel witnesses before/after capture, green target pixels, stable helper/operation, suspension counts 1–4 and settlement release (`/tmp/pi-border-capture-175-idle.log`). No guard, source or test was changed; this result supersedes the blocked status without erasing the earlier refusals. The user subsequently confirmed restoration, independently checked below.
|
|
1335
|
+
|
|
1336
|
+
The user confirmed restoration on 2026-11-06. The configured passive inventory `test:indicators -- --layout-only` exited 0 and reported both scales 1 with original bounds: DISPLAY2 `(2560,-61,1920,1080)` and DISPLAY1 `(0,0,2560,1080)`. Control was unarmed and presentation invisible; no overlay, pixels or physical input were dispatched. Receipt: `/tmp/pi-display-restored.log`. This completes setup restoration for the grouped 100%/150%/175% checks. Changed display topology/size, other capture/recording paths and disposition of unavailable 200% remain separate; #6/#20 are not closed by restoration.
|
|
1337
|
+
|
|
1338
|
+
### Changed monitor arrangement
|
|
1339
|
+
|
|
1340
|
+
On 2026-11-06 the user moved the 1920×1080 secondary display to the left of the unchanged primary, keeping both scales at 100%. Passive inventory independently measured DISPLAY2 `(-1920,-47,1920,1080)` and DISPLAY1 `(0,0,2560,1080)`, both scale 1, with control unarmed and presentation hidden (`/tmp/pi-layout-changed-inventory.log`). This differs from the original secondary position `(2560,-61)` and exercises simultaneous negative X/Y coordinates.
|
|
1341
|
+
|
|
1342
|
+
Both unchanged runners from `03907ee` exited 0, with four samples each: both monitors, native and maxWidth-80 images. Mapping matched independent PMV2/DWM bounds, origins, both image scales, rounded height and painted point pixels at actual 96 DPI. Secondary screenshot bounds were `(-1113,393,306,193)`; primary bounds were `(1127,440,306,193)`. Receipt: `/tmp/pi-display-layout-left.log`.
|
|
1343
|
+
|
|
1344
|
+
The border case used owned regions `(-1920,-47,640,480)` and `(0,0,640,480)`. All four strict PrintWindow captures excluded independently witnessed blue border pixels and retained the green target pixels. Helper/operation identity, exclusive control and visible restored border stayed valid; suspension counts advanced 1–4 and settlement released control. Receipt: `/tmp/pi-border-layout-left.log`. No physical input, paid model call, source/test change or global setting command was used. Only owned samples/metadata were retained; Windows dependency resolution passed from this checkout.
|
|
1345
|
+
|
|
1346
|
+
This establishes the tested changed arrangement with fresh worker/helper instances, not hot-plug/live-held reconfiguration, changed display resolution/primary or every capture/recording path. The 200% limitation remains untested. The user confirmed restoration to the right of the primary; passive verification is recorded below. The earlier scaling restoration receipt remains valid for its own stage.
|
|
1347
|
+
|
|
1348
|
+
After the user reported restoration, passive inventory exited 0 with DISPLAY2 `(2560,0,1920,1080)` and DISPLAY1 `(0,0,2560,1080)`, both scale 1, unarmed control and invisible presentation (`/tmp/pi-layout-restored-inventory.log`). Side, scales, dimensions and primary selection returned to their intended configuration; the secondary is now top-aligned at Y=0 rather than its original Y=-61. That difference was disclosed and exact-coordinate restoration is not claimed. No mapping or border tests were repeated. The user was asked whether to accept unavailable 200% custom scaling and untested resolution/primary-display variants as first-release #6 test limitations or keep the issue open; the user subsequently accepted the practical scaling closeout below. #20 recording/capture-path scope remains separate.
|
|
1349
|
+
|
|
1350
|
+
### Recording visibility preparation
|
|
1351
|
+
|
|
1352
|
+
The 2026-11-06 #20 closeout adds `test:indicators -- --recording-preview` to the existing indicator runner. Its backend-free plan declares two phases, remote visibility true then false, no exclusive control, no physical input and no pixel capture. Each phase renews the existing two-second preview eight times, about once per second; a preceding expiry gap separates old settings from the new phase. Disposable settings enable frames/bars, disable the pointer tag and label the phase. This is a preview, not an actual-control or human-stop test; #31's accepted control proof remains reused.
|
|
1353
|
+
|
|
1354
|
+
The live preflight exited 0 with helper PID 23004, eight samples per phase, four local visible windows on two monitors and successful affinity-application metadata for both settings. Every sample was unarmed, nonexclusive and not held; final health confirmed hidden/unarmed/nonexclusive state and disposal completed. No desktop pixels, recording files, input or personal settings were read/changed. Receipt: `/tmp/pi-recording-preview-preflight.log`. This establishes helper preparation only; it is not a recording verdict. The user selected Windows Snipping Tool; the actual region-recording run and human observations are accepted below.
|
|
1355
|
+
|
|
1356
|
+
For the human check, the user records a screen region containing an outer monitor edge before signalling readiness. The agent runs the preview and announces completion; the user stops and inspects the recording locally. Expected steady phases: the border remains locally visible in both, while the recording includes the border in the visible phase and omits it in the hidden phase. Record the actual recorder/method and result, including deviations; do not request credentials, video upload or access to private desktop recordings. An app-window recording that naturally excludes separate overlay windows cannot by itself establish the visible-phase behavior. Windows affinity metadata alone cannot replace this observation; [supported API scope](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowdisplayaffinity) is not a promise for every recorder or remote session.
|
|
1357
|
+
|
|
1358
|
+
The new plan contract first failed before implementation (`/tmp/pi-recording-plan-red.log`), then configured checks passed 187 tests with one skipped (`/tmp/pi-recording-preview-check.log`); build/package/document-link checks passed (90 entries, `/tmp/pi-recording-preview-package.log`). Both review axes cleared the change, with the phase expiry wait moved before the settings update as suggested. No production code changed. Stale indicator-checklist and #31-in-progress prose was replaced with the current scoped receipts; The later explicit #6 response is recorded below; #20's later recorder verdict is recorded below.
|
|
1359
|
+
|
|
1360
|
+
### Screenshot mapping closeout
|
|
1361
|
+
|
|
1362
|
+
On 2026-11-06 the user said there was no need to pursue 200% and accepted practical scaling support after the measured 100%/150%/175% and changed-arrangement checks. #6 is completed for that first-release scope. Unavailable 200% custom scaling and other unexercised resolution/primary-display/live-reconfiguration variants remain unverified; none is a passing test or a universal-support claim. No coordinate, target-identity or capture safeguards changed. Earlier refusal/failure receipts and the restored-layout vertical difference remain recorded. #20 owns the remaining recording acceptance; #21 retains final release reconciliation.
|
|
1363
|
+
|
|
1364
|
+
The user selected Windows Snipping Tool for #20. Its screen-region recording workflow is documented by [Microsoft](https://www.microsoft.com/en-us/windows/learning-center/how-to-use-snipping-tool-on-windows-screenshots-shortcuts-and-screen-recordings): open video capture with Win+Shift+R, select a region and start. For this check the region must touch an outer monitor edge; keep recording through both labelled preview phases and inspect locally after the completion signal. Snipping Tool version/actual capture behavior is not inferred merely from its availability; the later human result is recorded below. No recording or private desktop content is requested in chat.
|
|
1365
|
+
|
|
1366
|
+
### Snipping Tool recording acceptance
|
|
1367
|
+
|
|
1368
|
+
On 2026-11-06, after the user confirmed region recording was running, the unchanged `cc9c826` preview ran to exit 0. Helper PID 25676 supplied eight samples per phase with four visible local windows and successful affinity metadata. The helper stayed unarmed/nonexclusive/not held; final health verified hidden overlays before disposal. The runner sent no physical input and acquired no desktop pixels. Receipt: `/tmp/pi-snipping-recording-check.log`.
|
|
1369
|
+
|
|
1370
|
+
The user inspected the Windows Snipping Tool region recording locally and explicitly confirmed all three observations matched: local border visible in both steady phases; recorded border present during recording-visible; recorded border absent during recording-hidden. The brief expiry gap is excluded from the steady-phase comparison. No video, private screen content or credentials were uploaded/read by the agent; app version was not collected. This is a human-confirmed local Snipping Tool region-recording result, not an agent-inspected clip or universal recorder/RDP certification.
|
|
1371
|
+
|
|
1372
|
+
#20 is complete for the composed first-release scope: accepted appearance/hit samples and #31 human/control proof; automated retention/settings/release/reacquisition; strict PrintWindow pixel exclusion with active control at 100%/150%/175% and changed negative-origin layout; generic capture-suspension protocol evidence; and the human recorder result above. The preview does not claim new physical-control, Esc or handback proof. Per-route default screen-copy/WGC/OCR overlay pixels and other capture/remote/display variants remain unverified, not inferred passes. Windows affinity remains API-dependent; coordinate, target, stop and capture safeguards are unchanged. #21 reconciles those declared limits with the deferred clean-install gate; no release is declared.
|