Skip to content
Merged
Changes from 1 commit
Commits
Show all changes
272 commits
Select commit Hold shift + click to select a range
c938026
fix(studio): enforce P0 start guard in native controller boundary
masarray Sep 10, 2026
7d28eb2
fix(studio): include guarded public device controller
masarray Sep 10, 2026
cf27119
fix(studio): register guarded P0 device controller
masarray Sep 10, 2026
f80850b
test(studio): add firmware bundle and start-policy self checks
masarray Sep 10, 2026
5320657
test(studio): gate firmware contract native policy and high-DPI launch
masarray Sep 10, 2026
fe88723
docs(studio): focus operator docs on P0 4I+4V public release
masarray Sep 10, 2026
656696a
ci(release): isolate package acceptance on fresh Windows runner
masarray Sep 10, 2026
231044f
ci(release): package P0 with public Qt 6.10.3
masarray Sep 10, 2026
6610eaa
ci(studio): cancel superseded PR validation runs
masarray Sep 10, 2026
3fcc83a
ci(release): cancel superseded P0 packaging runs
masarray Sep 10, 2026
30a8e37
fix(studio): allow Qt QML wrapper for P0 device controller
masarray Sep 10, 2026
25a23d1
fix(firmware): make P0 ESP32-P4 pre-v3 build reproducible
masarray Sep 10, 2026
96e9909
fix(firmware): enforce ESP32-P4 pre-v3 release policy
masarray Sep 10, 2026
218e442
feat(firmware): track release silicon revision policy
masarray Sep 10, 2026
b7f8049
fix(firmware): verify ESP32-P4 silicon revision before flash
masarray Sep 10, 2026
ef29ff8
test(studio): include P0 silicon policy in firmware contract
masarray Sep 10, 2026
b52a186
fix(ci): write merged ESP32-P4 image from build cwd
masarray Sep 10, 2026
201c5d8
fix(ci): wait for Windows GUI process exit codes
masarray Sep 10, 2026
f369464
fix(studio): make espflash 4.5 recovery invocation compatible
masarray Sep 10, 2026
369a0fc
feat(studio): redesign firmware recovery as guided operator flow
masarray Sep 10, 2026
ddaa166
feat(studio): make firmware recovery the offline setup default
masarray Sep 10, 2026
7893ac0
feat(studio): surface firmware setup in the primary offline workflow
masarray Sep 10, 2026
4009658
fix(studio): use existing firmware setup icon asset
masarray Sep 10, 2026
549245e
test(studio): validate espflash recovery CLI contract in release CI
masarray Sep 10, 2026
8ec29f0
fix(studio): expose robust P4 recovery probe state
masarray Sep 10, 2026
66b4b54
fix(studio): recognize real espflash P4 output and guide boot mode
masarray Sep 10, 2026
e7ad9c8
ux(studio): guide ESP32-P4 download-mode recovery
masarray Sep 10, 2026
835ba52
test(studio): regress real espflash ESP32-P4 probe format
masarray Sep 10, 2026
bd082ba
feat(studio): auto-check single recovery COM port
masarray Sep 10, 2026
0c0673d
feat(studio): make 4I4V startup zero-configuration
masarray Sep 10, 2026
4960b42
feat(firmware): expose semantic version to Studio
masarray Sep 10, 2026
68ead28
fix(studio): serialize startup discovery and quiet default views
masarray Sep 10, 2026
17a6a94
perf(studio): coalesce live setpoint edits
masarray Sep 10, 2026
c7721a3
docs(studio): track zero-configuration UX progress
masarray Sep 10, 2026
f163c1a
feat(studio): add native smart session controller
masarray Sep 10, 2026
5ce3d87
feat(studio): implement native smart session orchestration
masarray Sep 10, 2026
cff5fbc
build(studio): register smart session controller
masarray Sep 10, 2026
cb9e56c
feat(studio): expose native smart session to QML
masarray Sep 10, 2026
fba46c7
refactor(studio): drive operator UI from native smart session
masarray Sep 10, 2026
aed2c85
docs(studio): mark native smart-session checkpoint
masarray Sep 10, 2026
24db256
fix(studio): include move utility for smart session
masarray Sep 10, 2026
a2f93c0
fix(studio): require session-owned profile synchronization
masarray Sep 10, 2026
dfdbc39
fix(studio): do not trust stale armed profile across sessions
masarray Sep 10, 2026
e108ce2
feat(firmware): publish semantic version and capabilities
masarray Sep 10, 2026
330e829
feat(studio): add native firmware update coordinator
masarray Sep 10, 2026
f1eafa5
feat(studio): orchestrate one-click firmware update
masarray Sep 10, 2026
85372db
feat(studio): add one-click firmware update UX
masarray Sep 10, 2026
453d200
fix(studio): make smart firmware update state deterministic
masarray Sep 10, 2026
f6b3dd3
docs(studio): sync smart UX progress after firmware intelligence
masarray Sep 10, 2026
57c640d
fix(studio): enforce semantic firmware identity in native safety gate
masarray Sep 10, 2026
701f740
docs(studio): record semantic firmware safety gate
masarray Sep 10, 2026
48a1a33
refactor(studio): make live control hooks overridable
masarray Sep 10, 2026
80cc6fd
feat(studio): coalesce live setpoint writes in native controller
masarray Sep 10, 2026
31eed82
docs(studio): advance Smart UX progress checkpoint
masarray Sep 10, 2026
f781521
refactor(studio): inject shared firmware service into smart session
masarray Sep 10, 2026
7a842d1
refactor(studio): share one firmware service across smart and advance…
masarray Sep 10, 2026
bc7a43f
refactor(studio): register one shared firmware service
masarray Sep 10, 2026
de3c47c
refactor(studio): use shared firmware service in smart workflow
masarray Sep 10, 2026
b161ce6
refactor(studio): reuse shared firmware service in Advanced
masarray Sep 10, 2026
3fec2a1
fix(studio): bound post-flash reconnect attempts
masarray Sep 10, 2026
d611dca
fix(studio): make firmware reconnect bounded and deterministic
masarray Sep 10, 2026
59672fa
feat(studio): expose firmware flash progress
masarray Sep 10, 2026
f50665e
feat(studio): parse espflash percentage with safe fallback
masarray Sep 10, 2026
cef8188
feat(studio): show real firmware flash progress
masarray Sep 10, 2026
72b92b4
test(studio): expose flash progress parser contract
masarray Sep 10, 2026
dd4ed24
test(studio): make espflash progress parser deterministic
masarray Sep 10, 2026
19dba56
test(studio): lock firmware progress parsing in package contract
masarray Sep 10, 2026
3e2e20a
docs(studio): record Smart UX checkpoint D
masarray Sep 10, 2026
ea6c51f
polish(studio): simplify advanced configuration hierarchy
masarray Sep 10, 2026
fb002e3
polish(studio): make smart workflow operator-first
masarray Sep 10, 2026
548e755
polish(studio): reduce telemetry visual noise
masarray Sep 10, 2026
fd4faba
polish(studio): strengthen numeric value hierarchy
masarray Sep 10, 2026
6b2e293
polish(studio): make injection matrix easier to scan
masarray Sep 10, 2026
3f56e2b
docs(studio): record checkpoint E smart UX polish
masarray Sep 10, 2026
7f080d7
fix(studio): stop active output on graceful app exit
masarray Sep 10, 2026
667772a
docs(studio): record checkpoint F operator polish
masarray Sep 10, 2026
723cc93
refactor(studio): expose quiet serial command for session lease
masarray Sep 10, 2026
54b279c
feat(studio): maintain quiet firmware session lease
masarray Sep 10, 2026
fcadf78
feat(firmware): stop Studio-owned output when session lease expires
masarray Sep 10, 2026
10a0949
fix(studio): refresh session lease immediately before Start
masarray Sep 10, 2026
e2222f5
fix(firmware): activate lease only for fresh Studio sessions
masarray Sep 10, 2026
6ba9536
fix(firmware): enforce control lease independently of console input
masarray Sep 10, 2026
0ac6e85
fix(firmware): make session lease fail closed at timer boundary
masarray Sep 10, 2026
fa937b0
docs(studio): record checkpoint G session lease
masarray Sep 10, 2026
be417eb
perf(studio): make firmware process lifecycle asynchronous and bounded
masarray Sep 11, 2026
6b66f55
perf(studio): remove blocking waits from firmware flashing
masarray Sep 11, 2026
de7cf0e
feat(studio): model blank ESP32-P4 onboarding in smart session
masarray Sep 11, 2026
5b161e2
feat(studio): detect unconfigured ESP32-P4 and offer firmware install
masarray Sep 11, 2026
bcb10c7
feat(studio): add novice blank-board firmware onboarding popup
masarray Sep 11, 2026
a546fe3
chore: carry production AGENTS contract into P0 branch
masarray Sep 11, 2026
09e6a9b
fix(studio): expose structured firmware operation failures
masarray Sep 11, 2026
36e7c40
fix(studio): keep flash/reset failure semantics deterministic
masarray Sep 11, 2026
6bec34a
fix(studio): correct firmware manager failure path and hash branch
masarray Sep 11, 2026
d57850c
fix(studio): separate terminal firmware failure from reset completion
masarray Sep 11, 2026
0a652db
test(studio): expose ESP32-P4 revision policy predicate
masarray Sep 11, 2026
e6f90bd
test(studio): lock pre-v3 ESP32-P4 firmware target policy
masarray Sep 11, 2026
2cb0ab5
test(studio): cover blank-board revision and progress safety contract
masarray Sep 11, 2026
7c2baca
test(studio): reject wrong-chip firmware manifests
masarray Sep 11, 2026
91017c7
docs(studio): record Checkpoint H blank-board onboarding
masarray Sep 11, 2026
70ecfbe
fix(esp32p4): declare esp_app_format dependency for semantic firmware…
masarray Sep 11, 2026
7ed1e68
fix(studio): keep Start control visible during firmware gating
masarray Sep 11, 2026
56f8d3d
fix(studio): keep legacy firmware run gate fail-closed
masarray Sep 11, 2026
7c89e8a
feat(studio): add operator menus and persistent smart workflow
masarray Sep 11, 2026
abe814b
feat(studio): add OBS-style dock title interactions
masarray Sep 11, 2026
e7ef9c2
feat(studio): unify operator state and simplify main chrome
masarray Sep 11, 2026
312053e
feat(studio): restore last engineering stream selection
masarray Sep 11, 2026
25eb3e6
fix(studio): make Smart Session sole startup discovery owner
masarray Sep 11, 2026
27decc5
fix(studio): preserve safe shutdown and centralize shell ownership
masarray Sep 11, 2026
97fed1c
refactor(studio): route engineering file open through one authority
masarray Sep 11, 2026
ab8ae0b
fix(studio): bound smart discovery and allow unique-port recovery
masarray Sep 11, 2026
7a55e9f
fix(studio): recover legacy and blank boards from unique serial ports
masarray Sep 11, 2026
2a249aa
test(studio): lock unique-port firmware recovery selection
masarray Sep 11, 2026
aef011a
fix(studio): harden firmware process lifecycle
masarray Sep 11, 2026
12dbf8d
fix(studio): bound firmware operations and shutdown cleanly
masarray Sep 11, 2026
a69cc03
fix(studio): make application shutdown deterministic
masarray Sep 11, 2026
940f56b
fix(studio): make firmware failure terminal and retryable
masarray Sep 11, 2026
20702a9
fix(studio): latch firmware failures instead of looping
masarray Sep 11, 2026
8ee7fb8
test(studio): lock primary-window shutdown contract
masarray Sep 11, 2026
3122ff9
test(studio): verify primary-window process shutdown
masarray Sep 11, 2026
ed20efc
test(studio): verify packaged Windows process shutdown
masarray Sep 11, 2026
2c88795
fix(studio): bind process lifetime to primary close event
masarray Sep 11, 2026
39075eb
fix(studio): own shutdown from native primary close event
masarray Sep 11, 2026
4314551
fix(studio): terminate from QQuickWindow closing signal
masarray Sep 11, 2026
106c0f8
fix(studio): make primary close lifecycle deterministic
masarray Sep 11, 2026
ead8c08
test(studio): deliver lifecycle close event synchronously
masarray Sep 11, 2026
67d4d22
fix(studio): terminate directly on primary close event
masarray Sep 11, 2026
4016d06
fix(ci): make Windows lifecycle regression deterministic
masarray Sep 11, 2026
93a8e72
fix(studio): repair lifecycle regression build gate
masarray Sep 11, 2026
73d10f3
docs(studio): define production device supervisor architecture
masarray Sep 14, 2026
158b162
docs(studio): audit P0.5 device supervisor migration
masarray Sep 14, 2026
1e02ded
feat(studio): make device identity a typed contract
masarray Sep 14, 2026
704d327
feat(studio): parse semantic device identity once
masarray Sep 14, 2026
f522e48
refactor(studio): gate control from typed identity
masarray Sep 14, 2026
4c99c5d
refactor(studio): consume typed firmware identity
masarray Sep 14, 2026
e699a6b
feat(firmware): announce typed boot identity
masarray Sep 14, 2026
180063a
build(firmware): declare boot identity RNG dependency
masarray Sep 14, 2026
fc54809
test(studio): lock typed identity S1 contract
masarray Sep 14, 2026
6af4989
fix(studio): parse identity inside ESP-IDF log framing
masarray Sep 14, 2026
dd3514e
test(studio): exercise framed S1 identity and capability gate
masarray Sep 14, 2026
3257c1f
feat(studio): add bounded semantic identification state
masarray Sep 14, 2026
6044451
feat(studio): bound semantic IDENTIFY handshake
masarray Sep 14, 2026
1a5faa3
refactor(studio): make firmware recovery explicit after identity timeout
masarray Sep 14, 2026
4659af6
feat(studio): stop automatic ROM classification in normal startup
masarray Sep 14, 2026
29906cb
test(studio): lock bounded S2 identity retry policy
masarray Sep 14, 2026
95145f6
fix(studio): bound S3 profile synchronization state
masarray Sep 14, 2026
cbf6ef4
fix(studio): implement bounded generation-aware S3 profile sync
masarray Sep 14, 2026
c45bba2
fix(studio): include profile transaction value type
masarray Sep 14, 2026
d4b9df4
test(studio): lock bounded S3 profile sync policy
masarray Sep 14, 2026
c7ec558
fix(studio): surface actionable S3 profile sync failure
masarray Sep 14, 2026
8daf7ad
fix(studio): allow supervisor to expire stale profile deployment
masarray Sep 14, 2026
7e78106
fix(studio): expire silent profile transaction before bounded retry
masarray Sep 14, 2026
9b8ec1a
refactor(studio): add long-lived DeviceIoWorker transport owner
masarray Sep 14, 2026
a0a3406
refactor(studio): implement threaded serial IO worker
masarray Sep 14, 2026
3c39d86
refactor(studio): turn DeviceController into worker-backed facade
masarray Sep 14, 2026
80c4163
refactor(studio): move serial ownership behind DeviceIoWorker facade
masarray Sep 14, 2026
d04a5bb
fix(studio): keep S2 retry policy authoritative in facade
masarray Sep 14, 2026
43aafbb
fix(studio): expose worker retry constants for regression lock
masarray Sep 14, 2026
5d5028a
refactor(studio): move heartbeat ownership into DeviceIoWorker
masarray Sep 14, 2026
3f4b5a5
build(studio): compile DeviceIoWorker transport boundary
masarray Sep 14, 2026
37eb8a9
fix(studio): wait for worker port release before firmware probe
masarray Sep 14, 2026
7f917b7
test(studio): lock S4 worker affinity and bounded transport policy
masarray Sep 14, 2026
77d75ba
fix(studio): make profile command batches exclusive in IO worker
masarray Sep 14, 2026
926c7ef
fix(studio): enforce exclusive profile queue gate in IO worker
masarray Sep 14, 2026
56c4d7d
refactor(studio): expose exclusive worker command batches
masarray Sep 14, 2026
bc0acdc
fix(studio): preserve facade call while auto-classifying profile batch
masarray Sep 14, 2026
f2fdc51
fix(studio): keep facade batch API stable after worker exclusivity
masarray Sep 14, 2026
d268031
chore(studio): make DeviceIoWorker move dependency explicit
masarray Sep 14, 2026
987ef8a
S5: add generation-aware firmware process worker boundary
masarray Sep 14, 2026
8469a42
S5: implement bounded firmware process worker
masarray Sep 14, 2026
acfab9d
S5: compile firmware worker boundary
masarray Sep 14, 2026
22edcdb
S5: make FirmwareManager a generation-aware worker facade
masarray Sep 14, 2026
4531f3f
S5: move espflash process execution behind FirmwareWorker
masarray Sep 14, 2026
b2da411
S5: attach session generation to serial worker boundary
masarray Sep 14, 2026
911c3b6
S5: generation-tag all serial worker events
masarray Sep 14, 2026
1b0b3e0
S5: add generation-aware DeviceController facade
masarray Sep 14, 2026
eb1f235
S5: filter serial callbacks by supervisor generation
masarray Sep 14, 2026
dcddcd6
S5: add supervisor session generation and explicit PortOwner
masarray Sep 14, 2026
d40b275
S5: enforce generation-aware PortOwner handoff
masarray Sep 14, 2026
52492fb
S5: lock generation ownership and firmware worker policy in CI
masarray Sep 14, 2026
3babcb1
S5: make FirmwareManager header dependencies explicit
masarray Sep 14, 2026
dfe1fd1
S5: drain firmware process output before terminal result
masarray Sep 14, 2026
17e51ab
S5: fail closed until firmware worker affinity is ready
masarray Sep 14, 2026
4bdc442
S5.1: bound firmware stop and port-release handoff
masarray Sep 14, 2026
b4d9e12
S5.1: make firmware mutation supervisor-only
masarray Sep 14, 2026
8f8f7ac
S5.1: remove direct QML firmware ownership bypass
masarray Sep 14, 2026
af7efdb
S6: add bounded control health and USB loss detection
masarray Sep 14, 2026
2f7f26f
S6: bind recovery to stable device identity
masarray Sep 14, 2026
f2db0fb
S6: add process-level Studio ownership guard
masarray Sep 14, 2026
12d1dd1
S6: include move support in single-instance guard
masarray Sep 14, 2026
1ed6136
S6: enforce single-instance ownership before device services
masarray Sep 14, 2026
4d15843
S6: register single-instance guard source
masarray Sep 14, 2026
4378aec
S6: expose known-device recovery gate
masarray Sep 14, 2026
62a9c5a
S6: suppress install offer during known-device recovery
masarray Sep 14, 2026
0b8083b
S7: centralize operator intent authority in session supervisor
masarray Sep 14, 2026
7222968
S7: route device writes through supervisor intents
masarray Sep 14, 2026
b597a4a
S7: route workflow operator actions through session supervisor
masarray Sep 14, 2026
cebdf17
S7: route manual device recovery through supervisor
masarray Sep 14, 2026
d813e26
S7: expose typed PTP and smpSynch presentation state
masarray Sep 14, 2026
690cf2b
S7: parse timing state once in DeviceController
masarray Sep 14, 2026
33177b5
S7: render typed timing state and submit supervisor intents
masarray Sep 14, 2026
86a5a41
S7: pass session authority into advanced panels
masarray Sep 14, 2026
75e05eb
S7: route firmware panel port refresh through supervisor
masarray Sep 14, 2026
147df77
S7: make Main submit device intents through supervisor
masarray Sep 14, 2026
607f6e7
S7: gate engineering editor from supervisor state
masarray Sep 14, 2026
35af574
S7: cover channel enable intent in supervisor API
masarray Sep 14, 2026
6439c93
S7: route channel enable through supervisor
masarray Sep 14, 2026
1819fce
S7: wire signal matrices to supervisor session
masarray Sep 14, 2026
b4448de
S7: lock QML presentation-only authority in CI
masarray Sep 14, 2026
f6ac7e9
S7: regression-lock fail-closed supervisor intents
masarray Sep 14, 2026
b777bf3
S7: make device mutation surface C++ supervisor-only
masarray Sep 14, 2026
fe7260a
S8: add deterministic harness seam and explicit recovery intent state
masarray Sep 14, 2026
d0b9abd
S8: expose friend-only deterministic device state seam
masarray Sep 14, 2026
b71f699
S8: expose friend-only control-health harness seam
masarray Sep 14, 2026
7825307
S8: fail closed auto identity timeout and wrong-device recovery
masarray Sep 14, 2026
51ec4f4
S8: declare deterministic session harness
masarray Sep 14, 2026
6f6686f
S8: add deterministic supervisor event-sequence harness
masarray Sep 14, 2026
1be4855
S7/S8: close derived QML mutation surface
masarray Sep 14, 2026
4bf9a64
S8: keep fixture construction on public APIs only
masarray Sep 14, 2026
c82c935
S8: build deterministic session harness as separate CI executable
masarray Sep 14, 2026
d4d329e
S8: add headless harness entry point
masarray Sep 14, 2026
17219f2
S8: wire headless harness entry point
masarray Sep 14, 2026
723ce12
S8: gate deterministic session harness in Studio CI
masarray Sep 14, 2026
deae020
S8: preserve explicit recovery intent across IDENTIFY transaction
masarray Sep 14, 2026
4525174
S8: test manual recovery across IDENTIFY transition
masarray Sep 14, 2026
3113577
S8B: expose serial transport-loss policy
masarray Sep 14, 2026
ca98dd8
S8B: keep serial policy patch minimal
masarray Sep 14, 2026
0ed56e8
S8B: use shared serial transport-loss classification
masarray Sep 14, 2026
2a7751a
S8B: add Windows ownership integration harness
masarray Sep 14, 2026
cf2b329
S8B: build Windows ownership harness
masarray Sep 14, 2026
1e71a9c
S8B: add native Windows ownership integration gate
masarray Sep 14, 2026
7c96a60
S8B: add packaged single-instance ownership probe
masarray Sep 14, 2026
942a08c
S8B: gate staged portable and installed Windows ownership
masarray Sep 14, 2026
1177245
S8B: keep ownership harness free of worker automoc
masarray Sep 14, 2026
01e0bef
S8B: stabilize packaged process exit-code capture
masarray Sep 14, 2026
538b3b4
S8B: fix Windows harness exit-code capture
masarray Sep 14, 2026
558a1e3
S8B: stabilize release Windows process exit capture
masarray Sep 14, 2026
db38553
S8B: use tracked .NET processes for packaged ownership
masarray Sep 14, 2026
ba15573
S8B: use direct Windows harness exit codes
masarray Sep 14, 2026
d600b0b
S8B: use direct native harness exit codes in release gate
masarray Sep 14, 2026
840c576
RC2: add machine-readable physical acceptance evidence gate
masarray Sep 14, 2026
3402628
RC2: wire physical acceptance evidence target
masarray Sep 14, 2026
cd676ca
RC2: add physical evidence template
masarray Sep 14, 2026
c4aed8c
RC2: document full functional and 4000 fps acceptance gate
masarray Sep 14, 2026
ed46f3b
RC2: add Windows physical evidence policy CI gate
masarray Sep 14, 2026
da832c1
Release Freeze: pin P0 RC baseline and exception ledger
masarray Sep 14, 2026
c6a91fe
Release Freeze: define P0 blocker-only policy
masarray Sep 14, 2026
730c543
Release Freeze: enforce blocker-only changes above frozen RC
masarray Sep 14, 2026
7028c2d
Release Freeze: pin PR merge artifact provenance
masarray Sep 14, 2026
acd8152
fix(esp32p4): eliminate START timing telemetry blocker
masarray Sep 14, 2026
d9b5b68
Merge prep: sync AGENTS.md with current main contract
masarray Sep 15, 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
Prev Previous commit
Next Next commit
S8B: use tracked .NET processes for packaged ownership
  • Loading branch information
masarray committed Sep 14, 2026
commit db38553252e973a02a271a96dc69ecd8937f6f35
33 changes: 18 additions & 15 deletions apps/arstack_studio/packaging/verify-single-instance.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,35 @@ $exe = (Resolve-Path $Executable).Path
$lockPath = Join-Path ([IO.Path]::GetTempPath()) 'arstack-studio-single-instance.lock'
Remove-Item $lockPath -Force -ErrorAction SilentlyContinue

function Start-TrackedProcess([string]$FilePath, [string]$Arguments = '') {
$startInfo = New-Object System.Diagnostics.ProcessStartInfo
$startInfo.FileName = $FilePath
$startInfo.Arguments = $Arguments
$startInfo.UseShellExecute = $false

$process = New-Object System.Diagnostics.Process
$process.StartInfo = $startInfo
if (-not $process.Start()) {
throw "Failed to start $FilePath"
}
return $process
}

function Wait-ForExitBounded([System.Diagnostics.Process]$Process, [int]$TimeoutMs, [string]$Label) {
if (-not $Process.WaitForExit($TimeoutMs)) {
try { $Process.Kill() } catch {}
try { $Process.WaitForExit(2000) | Out-Null } catch {}
throw "$Label timed out after $TimeoutMs ms."
}

# PowerShell/.NET may leave ExitCode unmaterialized after the timed overload,
# especially for quickly exiting GUI-subsystem processes. Complete the wait
# and refresh the process snapshot before callers inspect ExitCode.
$Process.WaitForExit()
$Process.Refresh()
}

$first = $null
try {
$first = Start-Process -FilePath $exe -PassThru
$first = Start-TrackedProcess $exe
$deadline = [DateTime]::UtcNow.AddMilliseconds($ReadyTimeoutMs)
while (-not (Test-Path $lockPath) -and [DateTime]::UtcNow -lt $deadline) {
if ($first.HasExited) {
$first.Refresh()
throw "Primary Studio instance exited before acquiring its process lock (exit=$($first.ExitCode))."
}
Start-Sleep -Milliseconds 100
Expand All @@ -39,7 +47,7 @@ try {
throw 'Primary Studio instance did not publish the single-instance lock in time.'
}

$second = Start-Process -FilePath $exe -PassThru
$second = Start-TrackedProcess $exe
Wait-ForExitBounded $second $ExitTimeoutMs 'Second Studio instance'
if ($second.ExitCode -ne 23) {
throw "Second Studio instance was not blocked by ownership lock; exit=$($second.ExitCode), expected=23."
Expand All @@ -51,7 +59,7 @@ try {
Wait-ForExitBounded $first $ExitTimeoutMs 'Primary Studio hard-stop'
$first = $null

$third = Start-Process -FilePath $exe -ArgumentList @('--check-app-lifecycle') -PassThru
$third = Start-TrackedProcess $exe '--check-app-lifecycle'
Wait-ForExitBounded $third $ExitTimeoutMs 'Post-crash Studio lifecycle'
if ($third.ExitCode -ne 0) {
throw "Studio did not reclaim the stale ownership lock after hard-stop; exit=$($third.ExitCode)."
Expand All @@ -61,12 +69,7 @@ try {
} finally {
if ($null -ne $first -and -not $first.HasExited) {
try { $first.Kill() } catch {}
try {
if ($first.WaitForExit(2000)) {
$first.WaitForExit()
$first.Refresh()
}
} catch {}
try { $first.WaitForExit(2000) | Out-Null } catch {}
}
Remove-Item $lockPath -Force -ErrorAction SilentlyContinue
}
Loading