Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
d937111
Add scoped attach-only runner grants and settled controller handoff
JasonVMo Nov 12, 2026
b203739
Add opt-in native descriptor-path runner handoff qualification
JasonVMo Nov 12, 2026
74d129e
Classify invalid runner handoff input before reserving authority
JasonVMo Nov 12, 2026
c2748ca
Record scoped runner handoff qualification and native permission limits
JasonVMo Nov 12, 2026
dc7a21f
Format handoff qualification ledger for repository checks
JasonVMo Nov 12, 2026
2be11d3
Record passing final handoff aggregate validation
JasonVMo Nov 12, 2026
731d246
Harden reusable runner grants, preempt recovery and worker credentials
JasonVMo Nov 12, 2026
3326e01
Record reviewed handoff fixes and passing qualification
JasonVMo Nov 12, 2026
9a077fc
docs: record Windows F11 handoff qualification
JasonVMo Nov 12, 2026
9e82307
test(desktop): cover Windows runner and agent interruption
JasonVMo Nov 12, 2026
088b8b6
test(desktop): address runner lifecycle review
JasonVMo Nov 12, 2026
71f2dca
docs: isolate project-local validation fixtures
JasonVMo Nov 12, 2026
8fa8995
docs: bound parallel validation scheduling when needed
JasonVMo Nov 12, 2026
17749fe
docs(desktop-test): record portable Windows buildci qualification
JasonVMo Nov 12, 2026
70740c7
Revert "docs: bound parallel validation scheduling when needed"
JasonVMo Nov 12, 2026
c6a063e
Revert "docs: isolate project-local validation fixtures"
JasonVMo Nov 12, 2026
d56f09c
docs(desktop-test): record default-environment acceptance
JasonVMo Nov 12, 2026
684d7cd
Fix built Windows fixture provisioning for hosted handoff checks
JasonVMo Nov 12, 2026
e7043b4
Record hosted fixture import failure and default-environment repair v…
JasonVMo Nov 12, 2026
524b9a4
Validate native runner response loss by its original transport cause
JasonVMo Nov 12, 2026
632eb6f
Record Windows native runner and physical console qualification
JasonVMo Nov 12, 2026
5dbadb5
docs(desktop): record default Windows aggregate acceptance
JasonVMo Nov 12, 2026
7c95c6b
docs(desktop): record rebased macOS handoff qualification
JasonVMo Nov 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/scoped-runner-handoff.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@fluentui-react-native/desktop-driver': patch
'@fluentui-react-native/desktop-test': patch
'@fluentui-react-native/desktop-driver-mcp': patch
---

Add attach-only scoped runner grants, drain-confirmed MCP relinquish and standalone WDIO handoff, with parent-owned worker-crash cleanup and private credential transport. Bound live/draining grant authority separately from settled cleanup history, preserve shared descriptor roots during preemption, and allow preempted MCP controllers to reopen with fresh authority. Deliver worker credentials individually and scrub them before user hooks/specs and their children run; Node bootstrap remains trusted. Storybook handoff and retained launched applications remain unsupported.
5 changes: 5 additions & 0 deletions .changeset/windows-fixture-esm-provisioning.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@fluentui-react-native/desktop-driver': patch
---

Make the test-only Win32 fixture provisioner loadable as built Node ESM so hosted Windows native MCP/WDIO consumer qualification can provision its fixture explicitly without a Jest loader.
5 changes: 5 additions & 0 deletions .changeset/windows-native-runner-coverage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@fluentui-react-native/desktop-test': patch
---

Add Windows native private-descriptor MCP/WDIO consumer coverage for handoff, operator preemption, worker crash and lost runner-grant response, with explicit fixture readiness, bounded cleanup, optional capture and required accessibility-input execution in hosted CI. Cover terminal agent-serve interruption, the historical borrowed-scope self-wait, repeated signals and fenced failed cleanup without treating semantic SIGINT as physical console input.
5 changes: 5 additions & 0 deletions .changeset/windows-runner-response-loss.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@fluentui-react-native/desktop-test': patch
---

Validate native runner response loss through the client's typed transport failure and original cause. Share the real-successful-response fault with the portable runner contract while retaining reservation fencing, confirmed drain and fresh-session checks.
67 changes: 67 additions & 0 deletions .github/actions/setup-desktop-driver/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ inputs:
description: Run the target-OS native package contract before provisioning.
required: false
default: 'false'
run-native-runner-contract:
description: Provision the plain Win32 fixture and verify the native MCP/WDIO consumer on Windows.
required: false
default: 'false'
macos-signing-identity:
description: Pre-provisioned macOS code-signing identity. Leave empty for an ad hoc CI signature.
required: false
Expand Down Expand Up @@ -197,3 +201,66 @@ runs:

"FURN_DESKTOP_DRIVER_BUILD_POLICY=never" |
Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8

- name: Provision Windows native runner fixture
if: inputs.run-native-runner-contract == 'true' && (inputs.platform == 'windows' || inputs.platform == 'win32')
shell: pwsh
working-directory: ${{ github.workspace }}
run: |
$ErrorActionPreference = 'Stop'
@'
import fs from 'node:fs';
import path from 'node:path';
import { pathToFileURL } from 'node:url';
const module = path.resolve('packages', 'agentic', 'desktop-driver', 'lib', 'native', 'windows', 'win32FixtureSupport.js');
const { fixtureExecutable } = await import(pathToFileURL(module).href);
const executable = await fixtureExecutable();
fs.appendFileSync(process.env.GITHUB_ENV, `FURN_NATIVE_HANDOFF_APP_PATH=${executable}\n`);
console.log('Provisioned the plain Win32 native runner fixture.');
'@ | node --input-type=module
if ($LASTEXITCODE -ne 0) {
throw "Native runner fixture provisioning exited with code $LASTEXITCODE."
}

- name: Verify Windows native MCP and WDIO consumer
if: inputs.run-native-runner-contract == 'true' && (inputs.platform == 'windows' || inputs.platform == 'win32')
shell: pwsh
working-directory: ${{ github.workspace }}
env:
FURN_NATIVE_DRIVER_TEST: '1'
run: |
$ErrorActionPreference = 'Stop'
$results = Join-Path $env:GITHUB_WORKSPACE 'artifacts\desktop\f11\native-runner-jest.json'
New-Item -ItemType Directory -Force -Path (Split-Path $results) | Out-Null
yarn workspace @fluentui-react-native/desktop-test test nativeRunner.contract --runInBand --json --outputFile $results
if ($LASTEXITCODE -ne 0) {
throw "Native MCP/WDIO consumer contract exited with code $LASTEXITCODE."
}
$report = Get-Content -Raw -Path $results | ConvertFrom-Json
$ownership = @($report.testResults.assertionResults | Where-Object { $_.title -notmatch '\bcapture\b' })
if ($ownership.Count -ne 4 -or @($ownership | Where-Object { $_.status -ne 'passed' }).Count -ne 0) {
throw 'Native handoff, operator preemption, worker crash and lost-response recovery must all execute and pass.'
}
$evidence = @(
Get-ChildItem -Path (Split-Path $results) -Directory -Filter 'native-*' |
ForEach-Object {
$record = Join-Path $_.FullName 'evidence.json'
if (Test-Path $record) {
Get-Content -Raw -Path $record | ConvertFrom-Json
}
}
)
foreach ($mode in @('handoff', 'operator-preempt', 'lost-response')) {
$caseEvidence = @($evidence | Where-Object { $_.mode -eq $mode })
if (
$caseEvidence.Count -ne 1 -or
-not $caseEvidence[0].passed -or
-not $caseEvidence[0].cleanupConfirmed -or
$caseEvidence[0].wdio.executed -ne 2 -or
$caseEvidence[0].wdio.passed -ne 2 -or
$caseEvidence[0].wdio.skipped -ne 0 -or
$caseEvidence[0].wdio.accessibilityClick -ne 'passed'
) {
throw "$mode must execute both inner WDIO ownership and accessibility-input specs; an inner skip is not qualification."
}
}
10 changes: 10 additions & 0 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,7 @@ jobs:
with:
platform: windows
run-native-contract: 'true'
run-native-runner-contract: 'true'
disabled-input-features: keyboard,physicalClick,wheel

- name: Prep Windows Storybook
Expand Down Expand Up @@ -456,6 +457,10 @@ jobs:
path: |
apps/storybook/artifacts/windows
apps/storybook/artifacts/desktop
artifacts/desktop/f11/native-runner-jest.json
artifacts/desktop/f11/native-*/evidence.json
artifacts/desktop/f11/native-*/*/run.json
artifacts/desktop/f11/native-*/*/events.jsonl
${{ steps.desktop-driver.outputs.doctor-path }}
${{ steps.desktop-driver.outputs.cache-root }}/v1/artifacts/**/build.log
${{ steps.desktop-driver.outputs.cache-root }}/v1/diagnostics/**
Expand Down Expand Up @@ -534,6 +539,7 @@ jobs:
uses: ./.github/actions/setup-desktop-driver
with:
platform: win32
run-native-runner-contract: 'true'
disabled-input-features: keyboard,physicalClick,wheel

- name: Smoke test Win32 Storybook
Expand All @@ -548,6 +554,10 @@ jobs:
path: |
apps/storybook/artifacts/win32
apps/storybook/artifacts/desktop
artifacts/desktop/f11/native-runner-jest.json
artifacts/desktop/f11/native-*/evidence.json
artifacts/desktop/f11/native-*/*/run.json
artifacts/desktop/f11/native-*/*/events.jsonl
${{ steps.desktop-driver.outputs.doctor-path }}
${{ steps.desktop-driver.outputs.cache-root }}/v1/artifacts/**/build.log
${{ steps.desktop-driver.outputs.cache-root }}/v1/diagnostics/**
Expand Down
4 changes: 4 additions & 0 deletions packages/agentic/desktop-driver-mcp/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ only maps them onto MCP.
same-incarnation/descriptor-principal rediscovery; never share or resume another
connection's session. Disposal awaits child revocation, keeping terminal-only
cleanup proof for lost responses and failed drains; unauthorized is not cleanup.
- Explicit relinquish fences admission and aborts current calls immediately,
before queued cleanup. Return success only after confirmed child/session
drain; retain the fence/proof after failure. Reopening uses a fresh child and
invalidates old session resources, never cross-connection resume.
- Tie every artifact link to its session. Artifact ids restart in each session.
- Progress ticks come from the adapter and never reach the service, so a waiting
model does not keep an idle session alive. Cancellation aborts the HTTP call,
Expand Down
7 changes: 7 additions & 0 deletions packages/agentic/desktop-driver-mcp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ and drains the child, including ambiguous acquisitions; old services without
delegation fail closed. See
[Connection and setup](references/connection.md).

`desktop_session` with `action: "relinquish"` cancels and drain-confirms the
controller before an operator's generic attach-only WDIO runner takes over.
After runner cleanup, open a fresh session; no old resources are resumed.
Operator preemption also allows a fresh child after authoritative rejection;
it does not require restarting the MCP connection.
See [session actions](references/tools.md#desktop_session).

## Use it

Register the server with an MCP client that launches it over stdio:
Expand Down
13 changes: 9 additions & 4 deletions packages/agentic/desktop-driver-mcp/references/connection.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ existing private child client, never another connection's child. This retains
known-session cleanup responsibility rather than resuming across connections.
A replacement service or an authoritative invalid/revoked
session invalidates old references; open a new session and observe again.
Authoritative child rejection also discards its cached binding. Once an
operator-preempting runner has drained, the same MCP connection can delegate a
fresh child from the still-live descriptor; it cannot reuse the revoked child
or any old references, cursors, proofs, or artifact links.
Nothing automatically replays the failed operation.

Operations, acquisition, close, and complete resource reads are serialized per
Expand All @@ -145,10 +149,11 @@ retry an incomplete cleanup while the process remains alive.
There is no resume across different MCP connections and no crash-safe native
recovery promise; see [current status](current-status.md).

The authority limits delegation to eight edges and 4096 grants per service
incarnation, including revoked roots/children. Exhaustion is explicit and
requires an operator-controlled drain and service replacement. Cleanup proof
is never silently evicted or reused.
The authority limits delegation to eight edges and 4096 live or not-yet-drained
grants. Successful subtree drains restore capacity without restarting.
Pending and failed cleanup proof is never evicted; terminal retry proof for
the last 4096 fully drained records remains available. Older settled records
expire and their credentials fail closed, without recovering driver authority.

## Embedding

Expand Down
Loading
Loading