uriloop 0.3.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.
Files changed (62) hide show
  1. uriloop-0.3.1/LICENSE +11 -0
  2. uriloop-0.3.1/PKG-INFO +307 -0
  3. uriloop-0.3.1/README.md +282 -0
  4. uriloop-0.3.1/pyproject.toml +42 -0
  5. uriloop-0.3.1/setup.cfg +4 -0
  6. uriloop-0.3.1/src/uriloop/__init__.py +2 -0
  7. uriloop-0.3.1/src/uriloop/__main__.py +5 -0
  8. uriloop-0.3.1/src/uriloop/ai/__init__.py +0 -0
  9. uriloop-0.3.1/src/uriloop/ai/decision.py +305 -0
  10. uriloop-0.3.1/src/uriloop/ai/generator.py +153 -0
  11. uriloop-0.3.1/src/uriloop/ai/http.py +35 -0
  12. uriloop-0.3.1/src/uriloop/ai/router.py +129 -0
  13. uriloop-0.3.1/src/uriloop/ai/vision.py +181 -0
  14. uriloop-0.3.1/src/uriloop/analysis/__init__.py +0 -0
  15. uriloop-0.3.1/src/uriloop/analysis/dom_probe.js +108 -0
  16. uriloop-0.3.1/src/uriloop/analysis/file_transfer.js +53 -0
  17. uriloop-0.3.1/src/uriloop/analysis/layers.py +211 -0
  18. uriloop-0.3.1/src/uriloop/cli.py +247 -0
  19. uriloop-0.3.1/src/uriloop/composites.py +150 -0
  20. uriloop-0.3.1/src/uriloop/doctor.py +111 -0
  21. uriloop-0.3.1/src/uriloop/drivers/__init__.py +0 -0
  22. uriloop-0.3.1/src/uriloop/drivers/cdp.py +234 -0
  23. uriloop-0.3.1/src/uriloop/drivers/vnc.py +227 -0
  24. uriloop-0.3.1/src/uriloop/eventstore.py +236 -0
  25. uriloop-0.3.1/src/uriloop/files.py +76 -0
  26. uriloop-0.3.1/src/uriloop/loop.py +188 -0
  27. uriloop-0.3.1/src/uriloop/mcp/__init__.py +0 -0
  28. uriloop-0.3.1/src/uriloop/mcp/server.py +191 -0
  29. uriloop-0.3.1/src/uriloop/nl.py +127 -0
  30. uriloop-0.3.1/src/uriloop/privacy.py +55 -0
  31. uriloop-0.3.1/src/uriloop/projector.py +147 -0
  32. uriloop-0.3.1/src/uriloop/registry.py +93 -0
  33. uriloop-0.3.1/src/uriloop/runtime.py +675 -0
  34. uriloop-0.3.1/src/uriloop/scenarios.py +240 -0
  35. uriloop-0.3.1/src/uriloop/shell.py +102 -0
  36. uriloop-0.3.1/src/uriloop/suites.py +96 -0
  37. uriloop-0.3.1/src/uriloop/tabs.py +102 -0
  38. uriloop-0.3.1/src/uriloop/targeting.py +67 -0
  39. uriloop-0.3.1/src/uriloop/todo.py +104 -0
  40. uriloop-0.3.1/src/uriloop/uri.py +124 -0
  41. uriloop-0.3.1/src/uriloop.egg-info/PKG-INFO +307 -0
  42. uriloop-0.3.1/src/uriloop.egg-info/SOURCES.txt +60 -0
  43. uriloop-0.3.1/src/uriloop.egg-info/dependency_links.txt +1 -0
  44. uriloop-0.3.1/src/uriloop.egg-info/entry_points.txt +3 -0
  45. uriloop-0.3.1/src/uriloop.egg-info/requires.txt +20 -0
  46. uriloop-0.3.1/src/uriloop.egg-info/top_level.txt +1 -0
  47. uriloop-0.3.1/tests/test_ai.py +222 -0
  48. uriloop-0.3.1/tests/test_boundary.py +76 -0
  49. uriloop-0.3.1/tests/test_concurrency.py +35 -0
  50. uriloop-0.3.1/tests/test_core.py +205 -0
  51. uriloop-0.3.1/tests/test_e2e_browser.py +479 -0
  52. uriloop-0.3.1/tests/test_eventstore_boundaries.py +39 -0
  53. uriloop-0.3.1/tests/test_execution.py +144 -0
  54. uriloop-0.3.1/tests/test_files.py +101 -0
  55. uriloop-0.3.1/tests/test_layers.py +68 -0
  56. uriloop-0.3.1/tests/test_mcp.py +54 -0
  57. uriloop-0.3.1/tests/test_pg_mirror.py +84 -0
  58. uriloop-0.3.1/tests/test_privacy.py +107 -0
  59. uriloop-0.3.1/tests/test_shell.py +99 -0
  60. uriloop-0.3.1/tests/test_suites.py +74 -0
  61. uriloop-0.3.1/tests/test_tabs.py +133 -0
  62. uriloop-0.3.1/tests/test_vnc.py +126 -0
uriloop-0.3.1/LICENSE ADDED
@@ -0,0 +1,11 @@
1
+ Copyright 2026 uriloop contributors
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this project except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
uriloop-0.3.1/PKG-INFO ADDED
@@ -0,0 +1,307 @@
1
+ Metadata-Version: 2.4
2
+ Name: uriloop
3
+ Version: 0.3.1
4
+ Summary: Wspólna płaszczyzna URI/URN do autonomicznego sterowania przeglądarką (CDP) i pulpitem (noVNC) z pętlą zwrotną CQRS+ES i serwerami MCP
5
+ License-Expression: Apache-2.0
6
+ Requires-Python: >=3.11
7
+ Description-Content-Type: text/markdown
8
+ License-File: LICENSE
9
+ Requires-Dist: websockets>=12
10
+ Requires-Dist: jsonschema>=4.18
11
+ Requires-Dist: pillow>=10
12
+ Provides-Extra: pg
13
+ Requires-Dist: psycopg[binary]>=3.1; extra == "pg"
14
+ Provides-Extra: vnc
15
+ Requires-Dist: pycryptodome>=3.19; extra == "vnc"
16
+ Provides-Extra: onnx
17
+ Requires-Dist: onnxruntime>=1.18; extra == "onnx"
18
+ Requires-Dist: numpy>=1.26; extra == "onnx"
19
+ Provides-Extra: yolo
20
+ Requires-Dist: ultralytics>=8.3; extra == "yolo"
21
+ Provides-Extra: test
22
+ Requires-Dist: pyyaml>=6; extra == "test"
23
+ Requires-Dist: onnx>=1.15; extra == "test"
24
+ Dynamic: license-file
25
+
26
+ # uriloop
27
+
28
+
29
+ ## AI Cost Tracking
30
+
31
+ ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.3.1-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
32
+ ![AI Cost](https://img.shields.io/badge/AI%20Cost-$0.48-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-5.7h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
33
+
34
+ - 🤖 **LLM usage:** $0.4811 (11 commits)
35
+ - 👤 **Human dev:** ~$573 (5.7h @ $100/h, 30min dedup)
36
+
37
+ Generated on 2026-10-30 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
38
+
39
+ ---
40
+
41
+
42
+
43
+ Wspólna płaszczyzna **URI/URN** do autonomicznego sterowania **przeglądarką (CDP)** i **pulpitem (noVNC/VNC)**
44
+ przez **MCP**, z warstwową analizą ekranu, pętlą zwrotną nad `TODO.md` i wzorcem **CQRS + Event Sourcing**
45
+ (`logs.jsonl` → `chat.jsonl`, PostgreSQL).
46
+
47
+ Zgodność z wytycznymi wellmanifest: `nl-uri-dsl-llm` (NUL-001…009, 015), `logs` (hash-chain JSONL, runbooki),
48
+ `poa` (typowane procesy, kwity, fail-closed), `ssot` (`ssot.json`), `reuse` (rejestr deklaratywny, fasady), `dsl` (`dsl-manifest.json`).
49
+
50
+ ## AI: decyzje, generowanie procesów, wizja
51
+
52
+ | Rola | Model (domyślnie) | Co robi |
53
+ |---|---|---|
54
+ | Decyzje | **Liquid d1** `d1:3b` przez Ollama `/v1/systemone` | wybiera Action URI z katalogu (2..255 kandydatów, także elementy ekranu po URN), ocenia ryzyko 1..3 i zgodę na wykonanie; widzi zrzut ekranu |
55
+ | Generator | `qwen3:8b` (GPU 8 GB) · `qwen3.8:27b-q4_K_M` (≥ 20 GB) · DeepSeek `deepseek-v4-flash/pro` · proxy subllm | tworzy proces złożony `proc://uriloop/<nazwa>` z kroków rejestru, z pętlą poprawek po walidacji |
56
+ | Wizja | YOLO (`ultralytics` lub `onnxruntime`) | detekcje z URN i akcjami kliknięcia na pulpicie i stronie |
57
+
58
+ ```bash
59
+ make ollama-pull # natywnie: modele dobrane do VRAM (np. d1:3b + qwen3:8b)
60
+ make models # telemetria GPU i wybrane profile
61
+ make decide Q='kliknij Powitanie' X=1 # decyzja d1 (+ wykonanie, jeśli polityka pozwala)
62
+ make generate G='wyszukaj uriloop, a następnie otwórz drugą stronę' R=1
63
+ make generate G='…' P=deepseek # z DEEPSEEK_API_KEY
64
+ make detect SRC=desktop # YOLO
65
+ ```
66
+
67
+ W pętli: zadanie bez kroków → NL → decyzja d1 → (gdy wieloetapowe lub niepewne) generator → `proc://` → weryfikacja.
68
+ Zablokowane przez politykę (`URILOOP_AUTONOMY`, negacja „nie klikaj…”) dostaje `[?]` i czeka na człowieka.
69
+ Szczegóły: [docs/AI.md](docs/AI.md).
70
+
71
+ ## Szybki start
72
+
73
+ **Granica wdrożenia:** Ollama (d1, qwen), YOLO i ciężkie pakiety (onnxruntime, ultralytics/torch) działają
74
+ **natywnie na hoście** — z bezpośrednim dostępem do GPU i bez wielogigabajtowych obrazów. Docker uruchamia tylko
75
+ lekką infrastrukturę: Postgres, Chrome (CDP), pulpit (VNC/noVNC), stronę demo i projektor CQRS.
76
+
77
+ ```bash
78
+ make host-setup # .venv + uriloop[pg,vnc,onnx] + sprawdzenie Ollamy + `ollama pull` modeli dobranych do VRAM
79
+ # INSTALL_OLLAMA=1 make host-setup — instalacja Ollamy oficjalnym skryptem
80
+ # WITH_YOLO=1 make host-setup — ultralytics (torch zainstaluj wcześniej z właściwym CUDA)
81
+ source .venv/bin/activate # udostępnia uriloop w bieżącej powłoce, także po pracy w conda (base)
82
+ export URILOOP_ROOT="$PWD/workspace"
83
+ make up # docker: postgres, chrome (CDP 127.0.0.1:9222), desktop (VNC :5901, noVNC :6901), demo (:8088), projektor
84
+ make doctor # host: Ollama, modele, GPU, pakiety · docker: CDP, VNC, Postgres
85
+ make run-dry # plan: TODO.md → Action URI (bez wykonania)
86
+ make run # pętla autonomiczna na hoście; obserwuj workspace/TODO.md i workspace/chat.jsonl
87
+ make tail # zdarzenia
88
+ make verify # łańcuch hashy
89
+ make db-shell # select * from chat_view; select * from elements_view;
90
+ ```
91
+
92
+ Ollama działa jak zwykle na hoście (`ollama serve` lub usługa systemowa) pod `http://127.0.0.1:11434`.
93
+ Usługi docker są wystawione tylko na `127.0.0.1`. Opcjonalny kontener `agent` (`make agent-docker A='todo'`)
94
+ nie zawiera AI; jeśli ma korzystać z Ollamy hosta, ustaw `URILOOP_AI_IN_DOCKER=on` i uruchom Ollamę z `OLLAMA_HOST=0.0.0.0`.
95
+
96
+ Katalog `workspace/` jest współdzielony: projektor w kontenerze działa z UID/GID użytkownika (eksportuje je `make`),
97
+ więc pliki projekcji pozostają zapisywalne dla procesów hosta. Na macOS (Docker Desktop) blokady plików między
98
+ hostem a kontenerem bywają zawodne — tam uruchom projektor natywnie (`make follow`) zamiast usługi `projector`.
99
+
100
+ Podgląd pulpitu: `http://localhost:6901/vnc.html?password=vncpassword`.
101
+
102
+ ## Interaktywny shell i przykłady
103
+
104
+ `make shell` uruchamia terminal ze stałym `Runtime` oraz bramą narzędzi MCP. Analiza i kliknięcie po URN zachowują wspólną sesję. `make mcp` nadal udostępnia serwer stdio dla zewnętrznego klienta MCP.
105
+
106
+ ```text
107
+ uriloop> help
108
+ uriloop> tools
109
+ uriloop> scenarios
110
+ uriloop> scenario-plan demo-complex
111
+ uriloop> scenario demo-complex http://127.0.0.1:18089/
112
+ uriloop> do browser://page/analyze
113
+ uriloop> call chat_message_post {"text":"Sprawdzenie zakończone"}
114
+ uriloop> quit
115
+ ```
116
+
117
+ Dostępne przykłady: `demo-search`, `demo-data`, `demo-complex`, `demo-form`, `demo-table`, `demo-files`, `demo-tabs`, `demo-auth`. Wykonują analizę przed kliknięciem, wybierają bieżący URN, sprawdzają wyniki pośrednie i zapisują raport jako artefakt. Błąd zatrzymuje scenariusz; nie ma automatycznych ponowień efektów. URL wskazuje serwer demo widoczny dla sterowanej przeglądarki. Można też użyć `make scenarios` oraz `make scenario NAME=demo-complex URL=http://127.0.0.1:18089/`.
118
+
119
+ Terminal przyjmuje Action URI, `nl TEKST`, `plan CEL` i `call NAZWA JSON`. `plan` zapisuje plan do osobnego późniejszego wykonania przez `proc://uriloop/run?name=...`. `help`, `tools` i `quit` sterują terminalem; działania systemu przechodzą przez rejestr i MCP. Shell obsługuje lokalny katalog uriloop; nie jest klientem dowolnego zewnętrznego serwera MCP.
120
+
121
+ ## Seria scenariuszy i CI
122
+
123
+ `make suite` wykonuje wszystkie osiem gotowych scenariuszy, każdy w oddzielnej sesji i katalogu. Całość wymaga grantów i fikcyjnych danych do logowania:
124
+
125
+ ```bash
126
+ URILOOP_GRANTS=browser.upload,browser.tabs.close,browser.secrets \
127
+ URILOOP_SECRET_DEMO_PASSWORD=uriloop-demo-only \
128
+ URILOOP_SECRET_DEMO_BAD_PASSWORD=wrong-demo-password \
129
+ make suite URL=http://127.0.0.1:18089/
130
+ ```
131
+
132
+ W shellu uruchomionym z tymi ustawieniami odpowiednikiem jest `suite http://127.0.0.1:18089/`. Akcja `scenario://suite/run` zapisuje raport JSON, JUnit XML, kwity i logi; błąd dowolnego scenariusza daje exit 1. Można wybrać podzbiór parametrem `names` i limit czasu jednego przypadku parametrem `timeout`.
133
+
134
+ `make suite-local OUT=/tmp/nowe-wyniki CHROME_BIN=/sciezka/do/chrome` uruchamia własne Chromium i serwer demo na wolnych portach. Wymaga pustego katalogu wyników. Workflow GitHub Actions sprawdza Python 3.11 i 3.13 i zachowuje raporty nawet po niepowodzeniu. Szczegóły: [docs/CI.md](docs/CI.md).
135
+
136
+ Rzeczywisty VNC i PostgreSQL są sprawdzane osobnym jobem `real-infrastructure`: tekst jest wpisywany do aplikacji xterm i weryfikowany w pliku, a lustro bazy porównywane z logiem także po awarii połączenia i replay. Lokalne uruchomienie opisuje [docs/CI.md](docs/CI.md). Synchronizacja bazy ma teraz Action URI `log://mirror/sync`.
137
+
138
+ Nowe strony demo: formularz kontaktu (`forms.html`) i lista zamówień (`table.html`). Scenariusze otwierają je względem bazowego URL demo. Dane pozostają w pamięci strony do jej przeładowania.
139
+
140
+ ```text
141
+ uriloop> scenario demo-form http://demo/
142
+ uriloop> scenario demo-table http://demo/
143
+ ```
144
+
145
+ `demo-form` sprawdza pola wymagane, niepoprawny e-mail, zastąpienie tekstu i checkbox. `demo-table` sprawdza filtr, sortowanie, anulowanie i potwierdzenie modala oraz odmowę kliknięcia zasłoniętej kontrolki. Polecenie `browser://page/type` przyjmuje `clear=true`, aby zastąpić zawartość wskazanego pola; wymaga wtedy URN lub selektora.
146
+
147
+ Scenariusz plikowy wymaga grantu operatora:
148
+
149
+ ```bash
150
+ URILOOP_GRANTS=browser.upload ./uriloop shell
151
+ # W terminalu uriloop:
152
+ # scenario demo-files http://demo/
153
+ ```
154
+
155
+ `demo-files` pobiera raport UTF-8, sprawdza nazwę, MIME, bajty i SHA-256, wykrywa HTTP 404, załącza niewłaściwy typ, czyści wybór i zapisuje poprawny załącznik dokładnie raz w atrapie. Plik jest odczytywany w formularzu lokalnie; atrapa nie wysyła go do serwera. Runner `make suite-local` sam przyznaje potrzebne granty i ustawia jawne dane fikcyjnego konta dla własnego Chromium i lokalnych stron demo.
156
+
157
+ `browser://file/fetch?urn=…` pobiera zawartość linku przez Fetch w przeglądarce do artefaktu w katalogu roboczym. Obsługuje HTTP(S) tej samej domeny, bez przekierowań, maksymalnie 5 MiB i z ograniczonym czasem. Kwit zwraca metadane pliku i artefakt; błąd, timeout lub niekompletny transfer nie tworzy artefaktu plikowego. To ścieżka pobierania przez Fetch; natywny menedżer pobierania i dialog zapisu wymagają osobnych testów.
158
+
159
+ `browser://page/attach?urn=…&artifact=artifacts/…&name=raport.txt&mime=text/plain` wybiera jeden artefakt we wskazanym polu plikowym. `clear=true` czyści wybór. Wymaga grantu `browser.upload`, aktualnego celu i zgodnego hasha pliku; nie odczytuje dowolnych ścieżek hosta. Transfer bajtów przez CDP działa także wtedy, gdy Chromium jest w innym kontenerze. Używa `File`/`DataTransfer`; formularze wymagające zaufanych zdarzeń systemowych lub natywnego dialogu nie są jeszcze obsługiwane.
160
+
161
+ Scenariusz kart otwiera dwie kopie tej samej strony i sprawdza oddzielny stan notatek, odrzucenie URN z innej karty oraz zachowanie po zamknięciu wybranej karty:
162
+
163
+ ```bash
164
+ URILOOP_GRANTS=browser.tabs.close ./uriloop shell
165
+ # W terminalu uriloop:
166
+ # scenario demo-tabs http://demo/
167
+ ```
168
+
169
+ `browser://tabs/list` zwraca URN, URL, tytuł i informację o karcie wybranej w Runtime. `browser://tabs/open` przyjmuje albo `url`, albo URN linku z analizy; otwiera i wybiera nową kartę. `browser://tabs/switch?urn=…` wybiera wskazaną kartę. `browser://tabs/close?urn=…` wymaga grantu `browser.tabs.close`. Po zamknięciu wybranej karty trzeba jawnie wskazać kolejną przez `switch`; zwykła akcja strony nie wybiera automatycznie sąsiedniej karty. Zamknięcie karty w tle zachowuje wybraną kartę i jej indeks.
170
+
171
+ URN elementów i formularzy uwzględnia kartę, także przy identycznym URL. Przełączenie czyści indeks, poprzedni obraz i obserwację; nowa sesja CDP ma osobną historię żądań. `open` otwiera adres linku bez wykonywania jego handlera JavaScript. Okna popup, iframe, pobieranie danych między formularzami i odzyskiwanie niezapisanej pracy wymagają dalszych scenariuszy.
172
+
173
+ Logowanie demonstracyjne:
174
+
175
+ ```bash
176
+ URILOOP_GRANTS=browser.secrets \
177
+ URILOOP_SECRET_DEMO_PASSWORD=uriloop-demo-only \
178
+ URILOOP_SECRET_DEMO_BAD_PASSWORD=wrong-demo-password \
179
+ ./uriloop shell
180
+ # W terminalu uriloop:
181
+ # scenario demo-auth http://demo/
182
+ ```
183
+
184
+ To jawne dane fikcyjnego konta. `demo-auth` sprawdza niepoprawne dane, zalogowanie, odświeżenie, odmowę dostępu, wygaśnięcie i wylogowanie. Kody 200/401/403 są komunikatami lokalnej symulacji w `sessionStorage`; nie są odpowiedziami serwera uwierzytelniania. Backend, ciasteczka, SSO i MFA wymagają kolejnych testów.
185
+
186
+ `browser://page/secret?urn=…&env=URILOOP_SECRET_PASSWORD` odczytuje wartość z otoczenia procesu operatora i wpisuje ją wyłącznie do wskazanego pola hasła. Wymaga grantu `browser.secrets`, świeżego URN, poprawnego fokusu i nazwy zmiennej zaczynającej się od `URILOOP_SECRET_`. Nie zatwierdza formularza. W URI, kwicie i błędzie sterownika pozostaje referencja, bez wartości ani jej długości. Zwykłe `browser://page/type` odrzuca pole hasła; tekst tej komendy jest maskowany w publicznym URI także przy błędzie kontraktu. URI z maską jest dowodem audytu, a nie sposobem odtworzenia wpisanej treści.
187
+
188
+ Sekrety przekazuj przez referencję środowiskową, również w procesach złożonych. Nie umieszczaj ich w NL, TODO, kodzie procesu, `eval` ani innych parametrach URI. Ochrona dotyczy tej ścieżki wprowadzania i standardowych pól hasła; nie zapewnia maskowania dowolnych danych widocznych na ekranie ani treści, którą strona sama ujawni poza polem hasła.
189
+
190
+ ## Dostęp do polecenia uriloop
191
+
192
+ Instalacja znajduje się w `.venv`. Skrypt `make host-setup` aktywuje ją tylko wewnątrz swojego procesu. W nowym terminalu aktywuj środowisko przez `source .venv/bin/activate`, aby używać polecenia `uriloop`. W katalogu projektu można od razu używać `./uriloop` albo `.venv/bin/uriloop` bez aktywacji. Launcher `./uriloop` wybiera Python projektu i domyślnie zapisuje zdarzenia do `workspace/`; respektuje jawne `URILOOP_ROOT` i `--root`.
193
+
194
+ ```bash
195
+ ./uriloop --help
196
+ ./uriloop nl 'wpisz „uriloop” ' --dry
197
+ ./uriloop shell
198
+ # Alternatywnie, w bieżącym terminalu:
199
+ source .venv/bin/activate
200
+ export URILOOP_ROOT="$PWD/workspace"
201
+ uriloop --help
202
+ ```
203
+
204
+ `nl 'wpisz …'` wpisuje do pola, które ma fokus. Do przykładu z wyszukiwaniem i weryfikacją wyniku użyj w shellu `scenario demo-search http://demo/`. Samo uruchomienie CLI nie wymaga `goal -a`.
205
+
206
+ ## Goal: dostarczenie zmian do prywatnego repozytorium
207
+
208
+ Do commitu i push bez wydania pakietu użyj:
209
+
210
+ ```bash
211
+ make deliver
212
+ # To samo bez Make:
213
+ goal -a --no-publish push --no-version-sync --no-tag --no-changelog
214
+ # Podgląd bez wykonywania zmian:
215
+ goal -a --no-publish --dry-run push --no-version-sync --no-tag --no-changelog
216
+ ```
217
+
218
+ W Goal 2.2.4 samo `-a` włącza również `--force-publish`. Przy czystym drzewie i braku bazowej wersji z tagów, rejestru lub historii Goal proponuje `normal-bump`, po czym odmawia publikacji: `clean --force-publish requires an already synchronized, pre-bumped release version`. To konflikt w przebiegu wydania Goal; ponowienie tego samego polecenia nie przygotuje wydania. Linie `VERSION ... -> ...` w tym komunikacie opisują plan, a nie wykonany zapis.
219
+
220
+ Samo `--no-publish` pomija publikację pakietu; pozostałe flagi w `make deliver` wyłączają także synchronizację wersji, tagowanie i generowanie changeloga. Podgląd Goal 2.2.4 może nadal wyświetlić hipotetyczne podbicie wersji mimo tych flag; wykonanie korzysta ze ścieżki commitu bez wydania. Goal nadal może przygotować środowisko oraz zmienić pliki konfiguracyjne, utworzyć commit i wykonać push bieżącej gałęzi. Do uruchomienia aplikacji wystarczy `./uriloop shell`, a do lokalnej kontroli `make test` i `make verify`.
221
+
222
+ Ostrzeżenie `AI badge generation failed` pochodzi z dodatkowego mechanizmu szacowania kosztów i jest oddzielne od błędu wydania. Nie wymaga dodawania klucza OpenRouter do uruchamiania CLI ani deterministycznych scenariuszy. Wydanie do rejestru pakietów jest osobnym procesem: wymaga świadomego wyboru wersji, jej synchronizacji i konfiguracji docelowego rejestru.
223
+
224
+ ## Pojedyncze polecenia
225
+
226
+ ```bash
227
+ uriloop do 'browser://page/navigate?url=http://demo/'
228
+ uriloop do 'browser://page/analyze?format=webp' # zwraca URN elementów + gotowe akcje
229
+ uriloop do 'browser://page/click?urn=urn:uriloop:el:3f9c0a1b2c4d'
230
+ uriloop nl 'wpisz „uriloop” ' # NL → browser://page/type?text=uriloop
231
+ uriloop do 'desktop://keyboard/key?key=ctrl+l'
232
+ uriloop do 'desktop://screen/analyze?grid=12'
233
+ uriloop snapshot # NUL-009: stan rozmowy, procesów, zadań
234
+ ```
235
+
236
+ ## MCP
237
+
238
+ Narzędzia są generowane z `registry/processes.json` (nazwa = URI: `browser://page/click` → `browser_page_click`),
239
+ plus `uri_execute` (dowolne URI) i `nl_execute` (polecenie w języku naturalnym). Zrzuty wracają jako treść `image`.
240
+ Zasoby: `TODO.md`, `chat.jsonl`, `state.json`, `logs.jsonl`, `uriloop://registry/gbnf`.
241
+
242
+ ```bash
243
+ make mcp-browser # profil CDP (natywnie, stdio)
244
+ make mcp-desktop # profil noVNC (natywnie, stdio)
245
+ ```
246
+
247
+ Konfiguracja klienta: `.mcp.json` uruchamia serwery z `.venv` na hoście (ustaw `URILOOP_HOME` na katalog projektu).
248
+
249
+ ## TODO.md — kolejka zadań
250
+
251
+ ```markdown
252
+ - [ ] Wyszukaj frazę formularzem
253
+ - `browser://page/type?selector=%23q&text=uriloop&submit=true`
254
+ - expect: url~search.html?q=uriloop
255
+ - expect: text~Fraza: uriloop
256
+ - [ ] przejdź do http://demo/page2.html ← bez kroków: NL → URI
257
+ - expect: text~Nawigacja zakończona sukcesem
258
+ ```
259
+
260
+ Statusy `[~]` w toku, `[x]` wykonane, `[!]` nieudane ustawia projektor ze zdarzeń; dopisuje też `<!-- urn:uriloop:task:… -->`.
261
+
262
+ ## Pliki robocze (`workspace/`)
263
+
264
+ | Plik | Rola |
265
+ |---|---|
266
+ | `logs.jsonl` | Event store: append-only, `prev`/`hash` SHA-256, jedyne źródło prawdy |
267
+ | `chat.jsonl` | Projekcja rozmowy: wiadomości + zwięzłe powiadomienia procesów z URI/URN |
268
+ | `state.json` | Projekcja zasobów po URN (elementy, żądania, artefakty, procesy, zadania) |
269
+ | `TODO.md` | Zadania (pisze człowiek) + statusy (pisze projektor) |
270
+ | `artifacts/` | PNG/WebP, Set-of-Mark, JSON warstw — adresowane treścią |
271
+
272
+ ## Struktura
273
+
274
+ ```
275
+ registry/processes.json SSOT akcji (URI, schematy, aliasy NL, efekty)
276
+ src/uriloop/uri.py Action URI / URN, stable_urn
277
+ src/uriloop/runtime.py szyna komend + handlery (CQRS write)
278
+ src/uriloop/eventstore.py logs.jsonl + lustro PostgreSQL + artefakty
279
+ src/uriloop/projector.py projekcje (CQRS read), follow/rebuild
280
+ src/uriloop/loop.py pętla autonomiczna z expect i ponowieniami
281
+ src/uriloop/analysis/ warstwy L0–L4, sonda DOM, Set-of-Mark
282
+ src/uriloop/drivers/ cdp.py, vnc.py (RFB 3.8, TCP lub WebSocket noVNC)
283
+ src/uriloop/mcp/server.py serwer MCP stdio
284
+ src/uriloop/ai/ router (NUL-022), decision (d1/System One), generator (qwen/DeepSeek), vision (YOLO)
285
+ src/uriloop/composites.py procesy złożone proc://uriloop/<nazwa>, katalog DockURI
286
+ registry/models.json SSOT modeli i profili
287
+ db/init.sql tabela events (append-only) + widoki read-modeli
288
+ ```
289
+
290
+ Szczegóły: [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md), zasady dla agentów: [AGENTS.md](AGENTS.md), runbooki: [errors/](errors/README.md).
291
+
292
+ ## Testy
293
+
294
+ `make test` — 110 testów, w tym kontrola granicy wdrożenia (brak Ollamy/GPU/torch w compose i obrazie, MCP natywnie, `doctor`), warstwa AI na atrapie Ollama/DeepSeek (router GPU 8 GB, kontrakt d1, polityki, pętla poprawek generatora, YOLO ONNX) i E2E zadania złożonego (d1 → generator → proc:// → weryfikacja na żywym Chromium). Pozostałe: URI/rejestr/NL, event store i projekcje, schematy, klient RFB vs atrapa serwera (TCP i WebSocket),
295
+ warstwy analizy, kontrakt MCP oraz E2E z prawdziwym Chromium (pętla nad TODO.md, MCP po stdio), uruchamiane gdy przeglądarka jest dostępna.
296
+
297
+ ## Ograniczenia i dalsze kroki
298
+
299
+ - Analiza pulpitu jest pikselowa (siatka, zmiany); rozpoznawanie tekstu/ikon (OCR, VLM na Set-of-Mark) to następny krok.
300
+ - Klient VNC obsługuje kodowania Raw/CopyRect; dla wolnych łączy warto dodać Tight/ZRLE.
301
+ - Klienci d1, qwen i DeepSeek są przetestowani na atrapach zgodnych z opublikowanymi kontraktami API, nie na prawdziwych modelach.
302
+ - Format katalogu DockURI jest własnym profilem — repozytorium dockuri/dockuri było niedostępne.
303
+
304
+
305
+ ## License
306
+
307
+ Licensed under Apache-2.0.
@@ -0,0 +1,282 @@
1
+ # uriloop
2
+
3
+
4
+ ## AI Cost Tracking
5
+
6
+ ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.3.1-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
7
+ ![AI Cost](https://img.shields.io/badge/AI%20Cost-$0.48-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-5.7h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
8
+
9
+ - 🤖 **LLM usage:** $0.4811 (11 commits)
10
+ - 👤 **Human dev:** ~$573 (5.7h @ $100/h, 30min dedup)
11
+
12
+ Generated on 2026-10-30 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
13
+
14
+ ---
15
+
16
+
17
+
18
+ Wspólna płaszczyzna **URI/URN** do autonomicznego sterowania **przeglądarką (CDP)** i **pulpitem (noVNC/VNC)**
19
+ przez **MCP**, z warstwową analizą ekranu, pętlą zwrotną nad `TODO.md` i wzorcem **CQRS + Event Sourcing**
20
+ (`logs.jsonl` → `chat.jsonl`, PostgreSQL).
21
+
22
+ Zgodność z wytycznymi wellmanifest: `nl-uri-dsl-llm` (NUL-001…009, 015), `logs` (hash-chain JSONL, runbooki),
23
+ `poa` (typowane procesy, kwity, fail-closed), `ssot` (`ssot.json`), `reuse` (rejestr deklaratywny, fasady), `dsl` (`dsl-manifest.json`).
24
+
25
+ ## AI: decyzje, generowanie procesów, wizja
26
+
27
+ | Rola | Model (domyślnie) | Co robi |
28
+ |---|---|---|
29
+ | Decyzje | **Liquid d1** `d1:3b` przez Ollama `/v1/systemone` | wybiera Action URI z katalogu (2..255 kandydatów, także elementy ekranu po URN), ocenia ryzyko 1..3 i zgodę na wykonanie; widzi zrzut ekranu |
30
+ | Generator | `qwen3:8b` (GPU 8 GB) · `qwen3.8:27b-q4_K_M` (≥ 20 GB) · DeepSeek `deepseek-v4-flash/pro` · proxy subllm | tworzy proces złożony `proc://uriloop/<nazwa>` z kroków rejestru, z pętlą poprawek po walidacji |
31
+ | Wizja | YOLO (`ultralytics` lub `onnxruntime`) | detekcje z URN i akcjami kliknięcia na pulpicie i stronie |
32
+
33
+ ```bash
34
+ make ollama-pull # natywnie: modele dobrane do VRAM (np. d1:3b + qwen3:8b)
35
+ make models # telemetria GPU i wybrane profile
36
+ make decide Q='kliknij Powitanie' X=1 # decyzja d1 (+ wykonanie, jeśli polityka pozwala)
37
+ make generate G='wyszukaj uriloop, a następnie otwórz drugą stronę' R=1
38
+ make generate G='…' P=deepseek # z DEEPSEEK_API_KEY
39
+ make detect SRC=desktop # YOLO
40
+ ```
41
+
42
+ W pętli: zadanie bez kroków → NL → decyzja d1 → (gdy wieloetapowe lub niepewne) generator → `proc://` → weryfikacja.
43
+ Zablokowane przez politykę (`URILOOP_AUTONOMY`, negacja „nie klikaj…”) dostaje `[?]` i czeka na człowieka.
44
+ Szczegóły: [docs/AI.md](docs/AI.md).
45
+
46
+ ## Szybki start
47
+
48
+ **Granica wdrożenia:** Ollama (d1, qwen), YOLO i ciężkie pakiety (onnxruntime, ultralytics/torch) działają
49
+ **natywnie na hoście** — z bezpośrednim dostępem do GPU i bez wielogigabajtowych obrazów. Docker uruchamia tylko
50
+ lekką infrastrukturę: Postgres, Chrome (CDP), pulpit (VNC/noVNC), stronę demo i projektor CQRS.
51
+
52
+ ```bash
53
+ make host-setup # .venv + uriloop[pg,vnc,onnx] + sprawdzenie Ollamy + `ollama pull` modeli dobranych do VRAM
54
+ # INSTALL_OLLAMA=1 make host-setup — instalacja Ollamy oficjalnym skryptem
55
+ # WITH_YOLO=1 make host-setup — ultralytics (torch zainstaluj wcześniej z właściwym CUDA)
56
+ source .venv/bin/activate # udostępnia uriloop w bieżącej powłoce, także po pracy w conda (base)
57
+ export URILOOP_ROOT="$PWD/workspace"
58
+ make up # docker: postgres, chrome (CDP 127.0.0.1:9222), desktop (VNC :5901, noVNC :6901), demo (:8088), projektor
59
+ make doctor # host: Ollama, modele, GPU, pakiety · docker: CDP, VNC, Postgres
60
+ make run-dry # plan: TODO.md → Action URI (bez wykonania)
61
+ make run # pętla autonomiczna na hoście; obserwuj workspace/TODO.md i workspace/chat.jsonl
62
+ make tail # zdarzenia
63
+ make verify # łańcuch hashy
64
+ make db-shell # select * from chat_view; select * from elements_view;
65
+ ```
66
+
67
+ Ollama działa jak zwykle na hoście (`ollama serve` lub usługa systemowa) pod `http://127.0.0.1:11434`.
68
+ Usługi docker są wystawione tylko na `127.0.0.1`. Opcjonalny kontener `agent` (`make agent-docker A='todo'`)
69
+ nie zawiera AI; jeśli ma korzystać z Ollamy hosta, ustaw `URILOOP_AI_IN_DOCKER=on` i uruchom Ollamę z `OLLAMA_HOST=0.0.0.0`.
70
+
71
+ Katalog `workspace/` jest współdzielony: projektor w kontenerze działa z UID/GID użytkownika (eksportuje je `make`),
72
+ więc pliki projekcji pozostają zapisywalne dla procesów hosta. Na macOS (Docker Desktop) blokady plików między
73
+ hostem a kontenerem bywają zawodne — tam uruchom projektor natywnie (`make follow`) zamiast usługi `projector`.
74
+
75
+ Podgląd pulpitu: `http://localhost:6901/vnc.html?password=vncpassword`.
76
+
77
+ ## Interaktywny shell i przykłady
78
+
79
+ `make shell` uruchamia terminal ze stałym `Runtime` oraz bramą narzędzi MCP. Analiza i kliknięcie po URN zachowują wspólną sesję. `make mcp` nadal udostępnia serwer stdio dla zewnętrznego klienta MCP.
80
+
81
+ ```text
82
+ uriloop> help
83
+ uriloop> tools
84
+ uriloop> scenarios
85
+ uriloop> scenario-plan demo-complex
86
+ uriloop> scenario demo-complex http://127.0.0.1:18089/
87
+ uriloop> do browser://page/analyze
88
+ uriloop> call chat_message_post {"text":"Sprawdzenie zakończone"}
89
+ uriloop> quit
90
+ ```
91
+
92
+ Dostępne przykłady: `demo-search`, `demo-data`, `demo-complex`, `demo-form`, `demo-table`, `demo-files`, `demo-tabs`, `demo-auth`. Wykonują analizę przed kliknięciem, wybierają bieżący URN, sprawdzają wyniki pośrednie i zapisują raport jako artefakt. Błąd zatrzymuje scenariusz; nie ma automatycznych ponowień efektów. URL wskazuje serwer demo widoczny dla sterowanej przeglądarki. Można też użyć `make scenarios` oraz `make scenario NAME=demo-complex URL=http://127.0.0.1:18089/`.
93
+
94
+ Terminal przyjmuje Action URI, `nl TEKST`, `plan CEL` i `call NAZWA JSON`. `plan` zapisuje plan do osobnego późniejszego wykonania przez `proc://uriloop/run?name=...`. `help`, `tools` i `quit` sterują terminalem; działania systemu przechodzą przez rejestr i MCP. Shell obsługuje lokalny katalog uriloop; nie jest klientem dowolnego zewnętrznego serwera MCP.
95
+
96
+ ## Seria scenariuszy i CI
97
+
98
+ `make suite` wykonuje wszystkie osiem gotowych scenariuszy, każdy w oddzielnej sesji i katalogu. Całość wymaga grantów i fikcyjnych danych do logowania:
99
+
100
+ ```bash
101
+ URILOOP_GRANTS=browser.upload,browser.tabs.close,browser.secrets \
102
+ URILOOP_SECRET_DEMO_PASSWORD=uriloop-demo-only \
103
+ URILOOP_SECRET_DEMO_BAD_PASSWORD=wrong-demo-password \
104
+ make suite URL=http://127.0.0.1:18089/
105
+ ```
106
+
107
+ W shellu uruchomionym z tymi ustawieniami odpowiednikiem jest `suite http://127.0.0.1:18089/`. Akcja `scenario://suite/run` zapisuje raport JSON, JUnit XML, kwity i logi; błąd dowolnego scenariusza daje exit 1. Można wybrać podzbiór parametrem `names` i limit czasu jednego przypadku parametrem `timeout`.
108
+
109
+ `make suite-local OUT=/tmp/nowe-wyniki CHROME_BIN=/sciezka/do/chrome` uruchamia własne Chromium i serwer demo na wolnych portach. Wymaga pustego katalogu wyników. Workflow GitHub Actions sprawdza Python 3.11 i 3.13 i zachowuje raporty nawet po niepowodzeniu. Szczegóły: [docs/CI.md](docs/CI.md).
110
+
111
+ Rzeczywisty VNC i PostgreSQL są sprawdzane osobnym jobem `real-infrastructure`: tekst jest wpisywany do aplikacji xterm i weryfikowany w pliku, a lustro bazy porównywane z logiem także po awarii połączenia i replay. Lokalne uruchomienie opisuje [docs/CI.md](docs/CI.md). Synchronizacja bazy ma teraz Action URI `log://mirror/sync`.
112
+
113
+ Nowe strony demo: formularz kontaktu (`forms.html`) i lista zamówień (`table.html`). Scenariusze otwierają je względem bazowego URL demo. Dane pozostają w pamięci strony do jej przeładowania.
114
+
115
+ ```text
116
+ uriloop> scenario demo-form http://demo/
117
+ uriloop> scenario demo-table http://demo/
118
+ ```
119
+
120
+ `demo-form` sprawdza pola wymagane, niepoprawny e-mail, zastąpienie tekstu i checkbox. `demo-table` sprawdza filtr, sortowanie, anulowanie i potwierdzenie modala oraz odmowę kliknięcia zasłoniętej kontrolki. Polecenie `browser://page/type` przyjmuje `clear=true`, aby zastąpić zawartość wskazanego pola; wymaga wtedy URN lub selektora.
121
+
122
+ Scenariusz plikowy wymaga grantu operatora:
123
+
124
+ ```bash
125
+ URILOOP_GRANTS=browser.upload ./uriloop shell
126
+ # W terminalu uriloop:
127
+ # scenario demo-files http://demo/
128
+ ```
129
+
130
+ `demo-files` pobiera raport UTF-8, sprawdza nazwę, MIME, bajty i SHA-256, wykrywa HTTP 404, załącza niewłaściwy typ, czyści wybór i zapisuje poprawny załącznik dokładnie raz w atrapie. Plik jest odczytywany w formularzu lokalnie; atrapa nie wysyła go do serwera. Runner `make suite-local` sam przyznaje potrzebne granty i ustawia jawne dane fikcyjnego konta dla własnego Chromium i lokalnych stron demo.
131
+
132
+ `browser://file/fetch?urn=…` pobiera zawartość linku przez Fetch w przeglądarce do artefaktu w katalogu roboczym. Obsługuje HTTP(S) tej samej domeny, bez przekierowań, maksymalnie 5 MiB i z ograniczonym czasem. Kwit zwraca metadane pliku i artefakt; błąd, timeout lub niekompletny transfer nie tworzy artefaktu plikowego. To ścieżka pobierania przez Fetch; natywny menedżer pobierania i dialog zapisu wymagają osobnych testów.
133
+
134
+ `browser://page/attach?urn=…&artifact=artifacts/…&name=raport.txt&mime=text/plain` wybiera jeden artefakt we wskazanym polu plikowym. `clear=true` czyści wybór. Wymaga grantu `browser.upload`, aktualnego celu i zgodnego hasha pliku; nie odczytuje dowolnych ścieżek hosta. Transfer bajtów przez CDP działa także wtedy, gdy Chromium jest w innym kontenerze. Używa `File`/`DataTransfer`; formularze wymagające zaufanych zdarzeń systemowych lub natywnego dialogu nie są jeszcze obsługiwane.
135
+
136
+ Scenariusz kart otwiera dwie kopie tej samej strony i sprawdza oddzielny stan notatek, odrzucenie URN z innej karty oraz zachowanie po zamknięciu wybranej karty:
137
+
138
+ ```bash
139
+ URILOOP_GRANTS=browser.tabs.close ./uriloop shell
140
+ # W terminalu uriloop:
141
+ # scenario demo-tabs http://demo/
142
+ ```
143
+
144
+ `browser://tabs/list` zwraca URN, URL, tytuł i informację o karcie wybranej w Runtime. `browser://tabs/open` przyjmuje albo `url`, albo URN linku z analizy; otwiera i wybiera nową kartę. `browser://tabs/switch?urn=…` wybiera wskazaną kartę. `browser://tabs/close?urn=…` wymaga grantu `browser.tabs.close`. Po zamknięciu wybranej karty trzeba jawnie wskazać kolejną przez `switch`; zwykła akcja strony nie wybiera automatycznie sąsiedniej karty. Zamknięcie karty w tle zachowuje wybraną kartę i jej indeks.
145
+
146
+ URN elementów i formularzy uwzględnia kartę, także przy identycznym URL. Przełączenie czyści indeks, poprzedni obraz i obserwację; nowa sesja CDP ma osobną historię żądań. `open` otwiera adres linku bez wykonywania jego handlera JavaScript. Okna popup, iframe, pobieranie danych między formularzami i odzyskiwanie niezapisanej pracy wymagają dalszych scenariuszy.
147
+
148
+ Logowanie demonstracyjne:
149
+
150
+ ```bash
151
+ URILOOP_GRANTS=browser.secrets \
152
+ URILOOP_SECRET_DEMO_PASSWORD=uriloop-demo-only \
153
+ URILOOP_SECRET_DEMO_BAD_PASSWORD=wrong-demo-password \
154
+ ./uriloop shell
155
+ # W terminalu uriloop:
156
+ # scenario demo-auth http://demo/
157
+ ```
158
+
159
+ To jawne dane fikcyjnego konta. `demo-auth` sprawdza niepoprawne dane, zalogowanie, odświeżenie, odmowę dostępu, wygaśnięcie i wylogowanie. Kody 200/401/403 są komunikatami lokalnej symulacji w `sessionStorage`; nie są odpowiedziami serwera uwierzytelniania. Backend, ciasteczka, SSO i MFA wymagają kolejnych testów.
160
+
161
+ `browser://page/secret?urn=…&env=URILOOP_SECRET_PASSWORD` odczytuje wartość z otoczenia procesu operatora i wpisuje ją wyłącznie do wskazanego pola hasła. Wymaga grantu `browser.secrets`, świeżego URN, poprawnego fokusu i nazwy zmiennej zaczynającej się od `URILOOP_SECRET_`. Nie zatwierdza formularza. W URI, kwicie i błędzie sterownika pozostaje referencja, bez wartości ani jej długości. Zwykłe `browser://page/type` odrzuca pole hasła; tekst tej komendy jest maskowany w publicznym URI także przy błędzie kontraktu. URI z maską jest dowodem audytu, a nie sposobem odtworzenia wpisanej treści.
162
+
163
+ Sekrety przekazuj przez referencję środowiskową, również w procesach złożonych. Nie umieszczaj ich w NL, TODO, kodzie procesu, `eval` ani innych parametrach URI. Ochrona dotyczy tej ścieżki wprowadzania i standardowych pól hasła; nie zapewnia maskowania dowolnych danych widocznych na ekranie ani treści, którą strona sama ujawni poza polem hasła.
164
+
165
+ ## Dostęp do polecenia uriloop
166
+
167
+ Instalacja znajduje się w `.venv`. Skrypt `make host-setup` aktywuje ją tylko wewnątrz swojego procesu. W nowym terminalu aktywuj środowisko przez `source .venv/bin/activate`, aby używać polecenia `uriloop`. W katalogu projektu można od razu używać `./uriloop` albo `.venv/bin/uriloop` bez aktywacji. Launcher `./uriloop` wybiera Python projektu i domyślnie zapisuje zdarzenia do `workspace/`; respektuje jawne `URILOOP_ROOT` i `--root`.
168
+
169
+ ```bash
170
+ ./uriloop --help
171
+ ./uriloop nl 'wpisz „uriloop” ' --dry
172
+ ./uriloop shell
173
+ # Alternatywnie, w bieżącym terminalu:
174
+ source .venv/bin/activate
175
+ export URILOOP_ROOT="$PWD/workspace"
176
+ uriloop --help
177
+ ```
178
+
179
+ `nl 'wpisz …'` wpisuje do pola, które ma fokus. Do przykładu z wyszukiwaniem i weryfikacją wyniku użyj w shellu `scenario demo-search http://demo/`. Samo uruchomienie CLI nie wymaga `goal -a`.
180
+
181
+ ## Goal: dostarczenie zmian do prywatnego repozytorium
182
+
183
+ Do commitu i push bez wydania pakietu użyj:
184
+
185
+ ```bash
186
+ make deliver
187
+ # To samo bez Make:
188
+ goal -a --no-publish push --no-version-sync --no-tag --no-changelog
189
+ # Podgląd bez wykonywania zmian:
190
+ goal -a --no-publish --dry-run push --no-version-sync --no-tag --no-changelog
191
+ ```
192
+
193
+ W Goal 2.2.4 samo `-a` włącza również `--force-publish`. Przy czystym drzewie i braku bazowej wersji z tagów, rejestru lub historii Goal proponuje `normal-bump`, po czym odmawia publikacji: `clean --force-publish requires an already synchronized, pre-bumped release version`. To konflikt w przebiegu wydania Goal; ponowienie tego samego polecenia nie przygotuje wydania. Linie `VERSION ... -> ...` w tym komunikacie opisują plan, a nie wykonany zapis.
194
+
195
+ Samo `--no-publish` pomija publikację pakietu; pozostałe flagi w `make deliver` wyłączają także synchronizację wersji, tagowanie i generowanie changeloga. Podgląd Goal 2.2.4 może nadal wyświetlić hipotetyczne podbicie wersji mimo tych flag; wykonanie korzysta ze ścieżki commitu bez wydania. Goal nadal może przygotować środowisko oraz zmienić pliki konfiguracyjne, utworzyć commit i wykonać push bieżącej gałęzi. Do uruchomienia aplikacji wystarczy `./uriloop shell`, a do lokalnej kontroli `make test` i `make verify`.
196
+
197
+ Ostrzeżenie `AI badge generation failed` pochodzi z dodatkowego mechanizmu szacowania kosztów i jest oddzielne od błędu wydania. Nie wymaga dodawania klucza OpenRouter do uruchamiania CLI ani deterministycznych scenariuszy. Wydanie do rejestru pakietów jest osobnym procesem: wymaga świadomego wyboru wersji, jej synchronizacji i konfiguracji docelowego rejestru.
198
+
199
+ ## Pojedyncze polecenia
200
+
201
+ ```bash
202
+ uriloop do 'browser://page/navigate?url=http://demo/'
203
+ uriloop do 'browser://page/analyze?format=webp' # zwraca URN elementów + gotowe akcje
204
+ uriloop do 'browser://page/click?urn=urn:uriloop:el:3f9c0a1b2c4d'
205
+ uriloop nl 'wpisz „uriloop” ' # NL → browser://page/type?text=uriloop
206
+ uriloop do 'desktop://keyboard/key?key=ctrl+l'
207
+ uriloop do 'desktop://screen/analyze?grid=12'
208
+ uriloop snapshot # NUL-009: stan rozmowy, procesów, zadań
209
+ ```
210
+
211
+ ## MCP
212
+
213
+ Narzędzia są generowane z `registry/processes.json` (nazwa = URI: `browser://page/click` → `browser_page_click`),
214
+ plus `uri_execute` (dowolne URI) i `nl_execute` (polecenie w języku naturalnym). Zrzuty wracają jako treść `image`.
215
+ Zasoby: `TODO.md`, `chat.jsonl`, `state.json`, `logs.jsonl`, `uriloop://registry/gbnf`.
216
+
217
+ ```bash
218
+ make mcp-browser # profil CDP (natywnie, stdio)
219
+ make mcp-desktop # profil noVNC (natywnie, stdio)
220
+ ```
221
+
222
+ Konfiguracja klienta: `.mcp.json` uruchamia serwery z `.venv` na hoście (ustaw `URILOOP_HOME` na katalog projektu).
223
+
224
+ ## TODO.md — kolejka zadań
225
+
226
+ ```markdown
227
+ - [ ] Wyszukaj frazę formularzem
228
+ - `browser://page/type?selector=%23q&text=uriloop&submit=true`
229
+ - expect: url~search.html?q=uriloop
230
+ - expect: text~Fraza: uriloop
231
+ - [ ] przejdź do http://demo/page2.html ← bez kroków: NL → URI
232
+ - expect: text~Nawigacja zakończona sukcesem
233
+ ```
234
+
235
+ Statusy `[~]` w toku, `[x]` wykonane, `[!]` nieudane ustawia projektor ze zdarzeń; dopisuje też `<!-- urn:uriloop:task:… -->`.
236
+
237
+ ## Pliki robocze (`workspace/`)
238
+
239
+ | Plik | Rola |
240
+ |---|---|
241
+ | `logs.jsonl` | Event store: append-only, `prev`/`hash` SHA-256, jedyne źródło prawdy |
242
+ | `chat.jsonl` | Projekcja rozmowy: wiadomości + zwięzłe powiadomienia procesów z URI/URN |
243
+ | `state.json` | Projekcja zasobów po URN (elementy, żądania, artefakty, procesy, zadania) |
244
+ | `TODO.md` | Zadania (pisze człowiek) + statusy (pisze projektor) |
245
+ | `artifacts/` | PNG/WebP, Set-of-Mark, JSON warstw — adresowane treścią |
246
+
247
+ ## Struktura
248
+
249
+ ```
250
+ registry/processes.json SSOT akcji (URI, schematy, aliasy NL, efekty)
251
+ src/uriloop/uri.py Action URI / URN, stable_urn
252
+ src/uriloop/runtime.py szyna komend + handlery (CQRS write)
253
+ src/uriloop/eventstore.py logs.jsonl + lustro PostgreSQL + artefakty
254
+ src/uriloop/projector.py projekcje (CQRS read), follow/rebuild
255
+ src/uriloop/loop.py pętla autonomiczna z expect i ponowieniami
256
+ src/uriloop/analysis/ warstwy L0–L4, sonda DOM, Set-of-Mark
257
+ src/uriloop/drivers/ cdp.py, vnc.py (RFB 3.8, TCP lub WebSocket noVNC)
258
+ src/uriloop/mcp/server.py serwer MCP stdio
259
+ src/uriloop/ai/ router (NUL-022), decision (d1/System One), generator (qwen/DeepSeek), vision (YOLO)
260
+ src/uriloop/composites.py procesy złożone proc://uriloop/<nazwa>, katalog DockURI
261
+ registry/models.json SSOT modeli i profili
262
+ db/init.sql tabela events (append-only) + widoki read-modeli
263
+ ```
264
+
265
+ Szczegóły: [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md), zasady dla agentów: [AGENTS.md](AGENTS.md), runbooki: [errors/](errors/README.md).
266
+
267
+ ## Testy
268
+
269
+ `make test` — 110 testów, w tym kontrola granicy wdrożenia (brak Ollamy/GPU/torch w compose i obrazie, MCP natywnie, `doctor`), warstwa AI na atrapie Ollama/DeepSeek (router GPU 8 GB, kontrakt d1, polityki, pętla poprawek generatora, YOLO ONNX) i E2E zadania złożonego (d1 → generator → proc:// → weryfikacja na żywym Chromium). Pozostałe: URI/rejestr/NL, event store i projekcje, schematy, klient RFB vs atrapa serwera (TCP i WebSocket),
270
+ warstwy analizy, kontrakt MCP oraz E2E z prawdziwym Chromium (pętla nad TODO.md, MCP po stdio), uruchamiane gdy przeglądarka jest dostępna.
271
+
272
+ ## Ograniczenia i dalsze kroki
273
+
274
+ - Analiza pulpitu jest pikselowa (siatka, zmiany); rozpoznawanie tekstu/ikon (OCR, VLM na Set-of-Mark) to następny krok.
275
+ - Klient VNC obsługuje kodowania Raw/CopyRect; dla wolnych łączy warto dodać Tight/ZRLE.
276
+ - Klienci d1, qwen i DeepSeek są przetestowani na atrapach zgodnych z opublikowanymi kontraktami API, nie na prawdziwych modelach.
277
+ - Format katalogu DockURI jest własnym profilem — repozytorium dockuri/dockuri było niedostępne.
278
+
279
+
280
+ ## License
281
+
282
+ Licensed under Apache-2.0.
@@ -0,0 +1,42 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "uriloop"
7
+ version = "0.3.1"
8
+ description = "Wspólna płaszczyzna URI/URN do autonomicznego sterowania przeglądarką (CDP) i pulpitem (noVNC) z pętlą zwrotną CQRS+ES i serwerami MCP"
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ license = "Apache-2.0"
12
+ dependencies = ["websockets>=12", "jsonschema>=4.18", "pillow>=10"]
13
+
14
+ [project.optional-dependencies]
15
+ pg = ["psycopg[binary]>=3.1"]
16
+ vnc = ["pycryptodome>=3.19"]
17
+ onnx = ["onnxruntime>=1.18", "numpy>=1.26"]
18
+ yolo = ["ultralytics>=8.3"]
19
+ test = ["pyyaml>=6", "onnx>=1.15"]
20
+
21
+ [project.scripts]
22
+ uriloop = "uriloop.cli:main"
23
+ uriloop-mcp = "uriloop.mcp.server:main"
24
+
25
+ [tool.setuptools.packages.find]
26
+ where = ["src"]
27
+
28
+ [tool.setuptools.package-data]
29
+ uriloop = ["analysis/*.js"]
30
+
31
+ [tool.costs]
32
+ # AI Cost tracking configuration
33
+ badge = true
34
+ update_readme = true
35
+ readme_path = "README.md"
36
+ default_model = "openrouter/qwen/qwen3-coder-next"
37
+ analysis_mode = "byok"
38
+ full_history = true
39
+ max_commits = 500
40
+
41
+ # Cost thresholds for badge colors (USD)
42
+ badge_color_thresholds = { low = 1.0, medium = 5.0, high = 10.0, critical = 50.0 }
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+