Repository navigation
v0.6.2
Closes the remaining items of #93 (C5, C6, C8, C10, C11): a failure now says
which failure it is, a death names its cause, the sweep's hides are accounted for
and undone, launched children cannot hold the step's pipes, and a failed session
leaves the frames at the moment it failed.
Added
- Failure signatures.
WintegrateErrorkeeps the facts passed at raise time
and buildssignaturefrom the class'sSIGNATURE_KEYSallow-list --
FocusStealDetectedError[foreground_image=explorer.exe],
WindowDiscoveryTimeoutError[process_names=notepad.exe]-- so two failures with
the same count stop reading as the same problem. No hwnd, pid or timestamp may
be a key: one per-run integer makes every signature unique. The foreground is
sampled during the focus retry loop, not at raise time, and carried on
TextMismatchErrortoo, the raise a mid-typing steal most often reaches.
step_failed,session_error, the job summary andREAD_THIS_FIRST.mdprint
it. ConsoleHostEndedError. When the console this process shares is destroyed
duringSession.__enter__, what reaches the traceback is aKeyboardInterrupt
at whatever line was executing.__enter__now re-labels it, on evidence only:
the console probes that answered at preflight answer nothing now. The message
names the phase it was in, how long ago it entered it, the processes the sweep
ended and the console peers that die with it. Still aKeyboardInterrupt, so a
pytest run aborts once. A real Ctrl-C with the console intact is untouched. The
verdict is journaled (console_host_ended) before it is raised.step_failednow carries the same window census delta asstep_ok: the
windows that came and went during the failing step were computed and thrown
away on the only path that matters.frames/at the failure. A failed session now pulls the recording's frames
at the moments the timeline names intoframes/, each named by video time and
event (t041830ms_step-failed_submit.png), withframes/index.jsonmapping
files to events. The budget is small (8) and the priority explicit: the window
around the laststep_failedfirst, the tail of the recording second, the rest
after -- and marks that do not fit are dropped whole and listed as dropped,
because a silently truncated set reads as the whole story.READ_THIS_FIRST.md
says the directory is there.extract_frames,plan_marksandvideo_ms_for
are public, for pulling frames from any recording with its anchor.expect_artifact(path, timeout), replacing asleepafter launching
something that writes a file: waits for the file to exist, be non-empty and
stop growing, and on the deadline raisesArtifactMissingErrornaming what the
directory actually held -- the.tmpthat was left behind, or nothing.
Changed
- The sweep's hides are recorded, verified and undone.
sanitize_ci_runner_environment()
used to run threeShowWindow(SW_HIDE)calls that recorded nothing, verified nothing
and restored nothing -- on a library whose charter names focus stealing as the
enemy. Each window hidden is now anInterventionResult(what was intended, what
a re-measurement found 0.3 s later, whether they agree) onKillPlan.interventions,
journalled ashide_resultand written intokill_plan.json; the foreground is
measured before and after the pass.Session.__exit__shows again what this
session hid and that is still hidden and still exists -- nothing else -- and
records that too (restore_result). The rule (hide_reason) and the restore
selection (restore_targets) are pure functions with offline tests. - Launched children no longer inherit this process's stdio.
Window.launch_and_discover
gave every child the step's stdout/stderr handles; an orphan holding those pipes is
what kept a CI stepin_progressafter the process that started it had died. Inside
aSessiona child's output goes tolaunched_NN.out/.errin the artifact
directory and a discovery timeout quotes it -- a child that printed an error and
exited is the usual reason no window appeared. Outside a session, DEVNULL. stdin is
DEVNULL either way.READ_THIS_FIRST.mdexplains both when the files are present.
Full changelog: https://github.com/mangokingTW/wintegrate/blob/main/CHANGELOG.md