From 9514faef4915aeb3d2145732b320b03bd6e1129e Mon Sep 17 00:00:00 2001 From: Tom Softreck Date: Sun, 1 Nov 2026 19:01:41 +0100 Subject: [PATCH] [ticket-019] fix(standards,release): exclude errors/README.md in logs check, guard optional cv2/numpy/typer test deps, and align 0.4.1 version SSOT --- README.md | 4 ++-- project/ticket-019/README.md | 9 +++++++++ project/ticket-019/intent.json | 19 +++++++++++++++++++ tests/live/test_live_io.py | 1 + tests/test_extensions.py | 5 ++++- tests/test_release_contracts.py | 14 +++++++++++++- tools/release.py | 2 +- tools/standards.py | 2 +- verification/summary.json | 2 +- 9 files changed, 51 insertions(+), 7 deletions(-) create mode 100644 project/ticket-019/README.md create mode 100644 project/ticket-019/intent.json diff --git a/README.md b/README.md index b41b5dc..257ac3b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Testwins 0.4.0 +# Testwins 0.4.1 **Jedna paczka do testów GUI, scenariuszy TestQL, shell/terminala, osobnych kontraktów API i ciągłej obserwacji.** To scalone wydanie wcześniejszych Testwins 0.2/0.3 oraz migracji `twin_ux` / Clonerd. @@ -45,7 +45,7 @@ Przykład live domyślnie obserwuje **3 trasy x 3 profile x Chromium**, nie trzy make bootstrap . .venv/bin/activate # Alternatywa bez bootstrap, po utworzeniu i aktywowaniu venv: -python -m pip install './dist/testwins-0.4.0-py3-none-any.whl[live,terminal]' +python -m pip install './dist/testwins-0.4.1-py3-none-any.whl[live,terminal]' python -m playwright install chromium testwins --version diff --git a/project/ticket-019/README.md b/project/ticket-019/README.md new file mode 100644 index 0000000..aa25662 --- /dev/null +++ b/project/ticket-019/README.md @@ -0,0 +1,9 @@ +# ticket-019 — Exclude errors/README.md in standards checker, guard optional cv2/numpy/typer test deps, and align version SSOT + +## Goal +Exclude `errors/README.md` when collecting error codes in `tools/standards.py` (`B09`), guard optional `cv2`/`numpy`/`typer` imports in `tests/test_extensions.py` and `tests/live/test_live_io.py` and exclude `.worktrees`/`.governance` in `tools/release.py` (`B02`), and align version `0.4.1` SSOT across `README.md`, `verification/summary.json`, and `tests/test_release_contracts.py` (`B03`). + +## Acceptance Criteria +1. `tools/standards.py` excludes `README.md` from `errors/*.md` error code discovery. +2. `tests/test_extensions.py` and `tests/live/test_live_io.py` skip cleanly via `pytest.importorskip` when `cv2`, `numpy`, or `typer` is not installed. +3. `VERSION`, `pyproject.toml`, `testwins.__version__`, `README.md`, and `verification/summary.json` all agree on `0.4.1`. diff --git a/project/ticket-019/intent.json b/project/ticket-019/intent.json new file mode 100644 index 0000000..4588dbd --- /dev/null +++ b/project/ticket-019/intent.json @@ -0,0 +1,19 @@ +{ + "schemaVersion": "1.0.0", + "ticketId": "ticket-019", + "title": "Exclude errors/README.md in standards checker, guard optional cv2/numpy/typer test deps, and align version SSOT", + "owner": "antigravity", + "workstream": "release-and-standards", + "status": "IN_PROGRESS", + "phase": "EDIT", + "allowedPaths": [ + "project/ticket-019/**", + "tools/standards.py", + "tools/release.py", + "README.md", + "verification/summary.json", + "tests/test_extensions.py", + "tests/live/test_live_io.py", + "tests/test_release_contracts.py" + ] +} diff --git a/tests/live/test_live_io.py b/tests/live/test_live_io.py index cebd749..62c2753 100644 --- a/tests/live/test_live_io.py +++ b/tests/live/test_live_io.py @@ -102,6 +102,7 @@ def test_wup_installer_no_overwrite(tmp_path): def test_wup_typer_adapter_has_watch_status_export_capacity(): + pytest.importorskip('typer') from typer.testing import CliRunner spec=importlib.util.spec_from_file_location('wup_gui',ROOT/'integrations/wup/overlay/wup/gui_testwins.py');m=importlib.util.module_from_spec(spec);spec.loader.exec_module(m) r=CliRunner().invoke(m.app,['--help']);assert r.exit_code==0 diff --git a/tests/test_extensions.py b/tests/test_extensions.py index 6a89280..d83ab31 100644 --- a/tests/test_extensions.py +++ b/tests/test_extensions.py @@ -139,6 +139,7 @@ def test_vision_invented_selector(): with pytest.raises(ValueError):validate_response({'findings':[f]},{'#real'},400,300) def test_opencv_actual(screenshot,tmp_path): + pytest.importorskip('cv2') assert len(contours(screenshot))>0 tpl=tmp_path/'template.png';Image.open(screenshot).crop((25,35,125,105)).save(tpl) result=match_template(screenshot,tpl);assert result['found'] and result['score']>.99 @@ -146,10 +147,12 @@ def test_opencv_actual(screenshot,tmp_path): data=analyze(screenshot,tmp_path/'cv.json');assert data['defects']==[] and data['authority']=='none' def test_uniform_rgb_template_rejected(screenshot,tmp_path): + pytest.importorskip('cv2') tpl=tmp_path/'constant.png';Image.new('RGB',(20,20),(255,0,0)).save(tpl) with pytest.raises(ValueError,match='texture'):match_template(screenshot,tpl) def test_template_larger(screenshot,tmp_path): + pytest.importorskip('cv2') tpl=tmp_path/'large.png';Image.new('RGB',(401,301),'white').save(tpl) assert not match_template(screenshot,tpl)['found'] @@ -160,7 +163,7 @@ def test_nms_class_aware(): def test_yolo_mock_adapter_tiles_and_offsets(tmp_path): """Fake detections exercise adapter coordinate logic; no weights/model inference are claimed.""" - import numpy as np + np=pytest.importorskip('numpy') p=tmp_path/'long.png';Image.new('RGB',(400,2000),'white').save(p) weights=tmp_path/'fake.pt';weights.write_bytes(b'NOT A MODEL') calls=[] diff --git a/tests/test_release_contracts.py b/tests/test_release_contracts.py index 3a18d8f..f3b99e8 100644 --- a/tests/test_release_contracts.py +++ b/tests/test_release_contracts.py @@ -160,7 +160,7 @@ async def send(self,*args):return {'metrics':[{'name':'Nodes','value':51}]} def test_report_single_failed_check_is_visible_in_manifest_junit(tmp_path): c=load();c.update(matrix='chromium',routes=[],journeys=[{'id':'flow','path':'/','steps':[step()]}]) c['devices']={'desktop':c['devices']['desktop']};c['capture']['repeats']=1 - r=report('failed');r.update(run_id='unit',schema='testwins.report/v1',created='2026-09-22',project='p',tool_version='0.4.0',config_hash='a'*64,matrix='chromium',environment={},occurrences=[]) + r=report('failed');r.update(run_id='unit',schema='testwins.report/v1',created='2026-09-22',project='p',tool_version='0.4.1',config_hash='a'*64,matrix='chromium',environment={},occurrences=[]) r['cells'][0].update(browser='chromium',device='desktop',version='stub',transport='cdp',errors=[],observed_scenes=1,expected_scenes=1) finalize(tmp_path,r,c) assert r['gate']['exit_code']==1 and r['cells'][0]['status']=='failed' @@ -274,3 +274,15 @@ def test_packaged_profiles_validate_and_preserve_all_personas(): assert len(large['journeys'])==len(small['journeys'])==6 assert {j['id'] for j in large['journeys']}=={j['id'] for j in small['journeys']} assert len(large['devices'])==2 and len(small['devices'])==1 + + +def test_version_ssot_consistent(): + import tomllib + import testwins + repo=Path(__file__).resolve().parents[1] + ver=(repo/'VERSION').read_text('utf-8').strip() + pyproj=tomllib.loads((repo/'pyproject.toml').read_text('utf-8'))['project']['version'] + summary=json.loads((repo/'verification/summary.json').read_text('utf-8'))['version'] + readme=(repo/'README.md').read_text('utf-8') + assert ver==pyproj==summary==testwins.__version__ + assert f'# Testwins {ver}' in readme diff --git a/tools/release.py b/tools/release.py index a5ef8ae..6b73263 100644 --- a/tools/release.py +++ b/tools/release.py @@ -30,7 +30,7 @@ def package(): dist=ROOT/'dist';archive=dist/f'testwins-{VERSION}-final.zip' artifacts=[dist/f'testwins-{VERSION}-py3-none-any.whl',dist/f'testwins-{VERSION}.tar.gz'] if not all(p.is_file() for p in artifacts):raise RuntimeError('Expected distributions not created') - excluded={'.git','.venv','.auth','.testwins','.pytest_cache','__pycache__','artifacts','baselines','build','dist', + excluded={'.git','.worktrees','.koru','.governance','.planfile','.subactor','.venv','.auth','.testwins','.pytest_cache','.ruff_cache','__pycache__','artifacts','baselines','build','dist', '.testwins-live-secret','.testwins-integration-backup'} selected=[] for p in sorted(ROOT.rglob('*')): diff --git a/tools/standards.py b/tools/standards.py index 74d1175..82391a8 100644 --- a/tools/standards.py +++ b/tools/standards.py @@ -22,7 +22,7 @@ def check(run: Path, upstream: Path, out: Path) -> dict: spec=importlib.util.spec_from_file_location('testwins_trusted_upstream_logs',checker) module=importlib.util.module_from_spec(spec);sys.modules[spec.name]=module;spec.loader.exec_module(module) bundle,contract_sha=module.load_contract(upstream) - codes={p.stem for p in (ROOT/'errors').glob('*.md')} + codes={p.stem for p in (ROOT/'errors').glob('*.md') if p.name!='README.md'} catalog=module.load_error_documents(ROOT,bundle,directory_relative='errors',declared=codes) previous='0'*64;prior={};count=0 from jsonschema import Draft202012Validator,FormatChecker diff --git a/verification/summary.json b/verification/summary.json index 166bc35..8eeaa07 100644 --- a/verification/summary.json +++ b/verification/summary.json @@ -1,6 +1,6 @@ { "schema": "testwins.release-verification/v1", - "version": "0.4.0", + "version": "0.4.1", "date": "2026-09-22", "unit_and_local": { "passed": 254,