quality-loop 0.3.0__tar.gz → 0.4.1__tar.gz
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.
- {quality_loop-0.3.0/quality_loop.egg-info → quality_loop-0.4.1}/PKG-INFO +3 -1
- {quality_loop-0.3.0 → quality_loop-0.4.1}/README.md +2 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop/__init__.py +1 -1
- quality_loop-0.4.1/quality_loop/awake.py +85 -0
- quality_loop-0.4.1/quality_loop/guest/__init__.py +580 -0
- quality_loop-0.4.1/quality_loop/guest/boot/__init__.py +7 -0
- quality_loop-0.4.1/quality_loop/guest/boot/launch.py +35 -0
- quality_loop-0.4.1/quality_loop/guest/boot/screen_agent.py +54 -0
- quality_loop-0.4.1/quality_loop/guest/screens.py +138 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop/runner.py +3 -3
- {quality_loop-0.3.0 → quality_loop-0.4.1/quality_loop.egg-info}/PKG-INFO +3 -1
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop.egg-info/SOURCES.txt +8 -0
- quality_loop-0.4.1/tests/test_awake.py +45 -0
- quality_loop-0.4.1/tests/test_guest.py +215 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/LICENSE +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/pyproject.toml +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop/OPERATOR.md +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop/__main__.py +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop/adapter.py +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop/audit.py +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop/cli.py +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop/compare.py +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop/config.py +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop/drive/__init__.py +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop/drive/_mac.py +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop/drive/_windows.py +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop/drive/keys.py +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop/drive/terminal.py +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop/install.py +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop/mcp.py +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop/operator.py +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop/pages.py +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop/processes.py +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop/progress.py +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop/report.py +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop/room.py +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop/scenario.py +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop/screens/__init__.py +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop/screens/_mac.py +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop/screens/_windows.py +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop/session.py +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop/skill/SKILL.md +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop/skill/references/filing.md +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop/skill/references/setup.md +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop/standin.py +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop/transcript.py +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop.egg-info/dependency_links.txt +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop.egg-info/entry_points.txt +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop.egg-info/requires.txt +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/quality_loop.egg-info/top_level.txt +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/setup.cfg +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/tests/test_core.py +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/tests/test_drive.py +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/tests/test_loop.py +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/tests/test_mcp.py +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/tests/test_operator.py +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/tests/test_scenario_report.py +0 -0
- {quality_loop-0.3.0 → quality_loop-0.4.1}/tests/test_screens.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: quality-loop
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.1
|
|
4
4
|
Summary: Measure what a product teaches - its skill, tools or manual - with isolated agent runs of real tasks, reported by an operator agent
|
|
5
5
|
Author: craftware
|
|
6
6
|
License-Expression: MIT
|
|
@@ -110,6 +110,8 @@ under a policy the person sets. See [Running the loop](https://github.com/crftwr
|
|
|
110
110
|
launch command and a redirected home up to evidence tools of its own.
|
|
111
111
|
- [Reports](https://github.com/crftwr/quality-loop/blob/main/docs/reports.md): problems, severities, kinds and ids, the
|
|
112
112
|
reproduction record, and `FINDINGS.md` / `findings.json`.
|
|
113
|
+
- [Running the app in a VM](https://github.com/crftwr/quality-loop/blob/main/docs/guests.md): one image per OS,
|
|
114
|
+
the guest over SSH, a clean machine every run, screens in the guest.
|
|
113
115
|
- [Isolation and permissions](https://github.com/crftwr/quality-loop/blob/main/docs/isolation.md): what keeps the room, the
|
|
114
116
|
operator and the conductor in bounds, why each rule exists, and the known limits.
|
|
115
117
|
- [Development](https://github.com/crftwr/quality-loop/blob/main/docs/development.md): tests, live tests, releasing.
|
|
@@ -79,6 +79,8 @@ under a policy the person sets. See [Running the loop](https://github.com/crftwr
|
|
|
79
79
|
launch command and a redirected home up to evidence tools of its own.
|
|
80
80
|
- [Reports](https://github.com/crftwr/quality-loop/blob/main/docs/reports.md): problems, severities, kinds and ids, the
|
|
81
81
|
reproduction record, and `FINDINGS.md` / `findings.json`.
|
|
82
|
+
- [Running the app in a VM](https://github.com/crftwr/quality-loop/blob/main/docs/guests.md): one image per OS,
|
|
83
|
+
the guest over SSH, a clean machine every run, screens in the guest.
|
|
82
84
|
- [Isolation and permissions](https://github.com/crftwr/quality-loop/blob/main/docs/isolation.md): what keeps the room, the
|
|
83
85
|
operator and the conductor in bounds, why each rule exists, and the known limits.
|
|
84
86
|
- [Development](https://github.com/crftwr/quality-loop/blob/main/docs/development.md): tests, live tests, releasing.
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""This machine kept from idle sleep while a run is going (issue #16).
|
|
2
|
+
|
|
3
|
+
A run is mostly waiting - on a session, on a VM - and a machine left alone
|
|
4
|
+
for it goes to sleep: a Mac on battery within minutes. Nothing fails; the
|
|
5
|
+
run just stops while it sleeps, and a VM guest stops with it. One run of
|
|
6
|
+
43 minutes had spent 40 of them asleep.
|
|
7
|
+
|
|
8
|
+
So the runner holds the platform's "the system is busy" assertion for the
|
|
9
|
+
length of the run, and lets go when it ends. The display may still sleep,
|
|
10
|
+
and closing a laptop's lid still sleeps it: those are the person's to choose.
|
|
11
|
+
|
|
12
|
+
- macOS: ``caffeinate -i -w <this pid>``, which also ends with this process
|
|
13
|
+
if it dies without letting go.
|
|
14
|
+
- Windows: ``SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED)``
|
|
15
|
+
from the runner's thread, cleared at the end (and by Windows when the
|
|
16
|
+
process exits).
|
|
17
|
+
- Elsewhere nothing is held.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
import contextlib
|
|
23
|
+
import os
|
|
24
|
+
import shutil
|
|
25
|
+
import subprocess
|
|
26
|
+
import sys
|
|
27
|
+
|
|
28
|
+
ES_CONTINUOUS = 0x80000000
|
|
29
|
+
ES_SYSTEM_REQUIRED = 0x00000001
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@contextlib.contextmanager
|
|
33
|
+
def held(say=print):
|
|
34
|
+
"""Idle sleep held off for the ``with`` block, where the platform allows."""
|
|
35
|
+
release = _hold()
|
|
36
|
+
if release is None:
|
|
37
|
+
yield False
|
|
38
|
+
return
|
|
39
|
+
say("awake: idle sleep is held off for the run (closing the lid still sleeps it)")
|
|
40
|
+
try:
|
|
41
|
+
yield True
|
|
42
|
+
finally:
|
|
43
|
+
release()
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _hold():
|
|
47
|
+
if sys.platform == "darwin":
|
|
48
|
+
return _hold_mac()
|
|
49
|
+
if os.name == "nt":
|
|
50
|
+
return _hold_windows()
|
|
51
|
+
return None
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _hold_mac():
|
|
55
|
+
caffeinate = shutil.which("caffeinate")
|
|
56
|
+
if caffeinate is None:
|
|
57
|
+
return None
|
|
58
|
+
try:
|
|
59
|
+
process = subprocess.Popen([caffeinate, "-i", "-w", str(os.getpid())],
|
|
60
|
+
stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL,
|
|
61
|
+
stderr=subprocess.DEVNULL)
|
|
62
|
+
except OSError:
|
|
63
|
+
return None
|
|
64
|
+
|
|
65
|
+
def release():
|
|
66
|
+
process.terminate()
|
|
67
|
+
try:
|
|
68
|
+
process.wait(5)
|
|
69
|
+
except subprocess.TimeoutExpired:
|
|
70
|
+
process.kill()
|
|
71
|
+
|
|
72
|
+
return release
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _hold_windows():
|
|
76
|
+
import ctypes
|
|
77
|
+
try:
|
|
78
|
+
kernel32 = ctypes.WinDLL("kernel32")
|
|
79
|
+
except OSError:
|
|
80
|
+
return None
|
|
81
|
+
kernel32.SetThreadExecutionState.restype = ctypes.c_uint
|
|
82
|
+
kernel32.SetThreadExecutionState.argtypes = [ctypes.c_uint]
|
|
83
|
+
if not kernel32.SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED):
|
|
84
|
+
return None
|
|
85
|
+
return lambda: kernel32.SetThreadExecutionState(ES_CONTINUOUS)
|