argus-testing 0.6.0__tar.gz → 0.7.0__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.

Potentially problematic release.


This version of argus-testing might be problematic. Click here for more details.

Files changed (159) hide show
  1. argus_testing-0.7.0/.dockerignore +19 -0
  2. {argus_testing-0.6.0 → argus_testing-0.7.0}/.github/workflows/ci.yml +9 -0
  3. {argus_testing-0.6.0 → argus_testing-0.7.0}/.github/workflows/release.yml +4 -0
  4. {argus_testing-0.6.0 → argus_testing-0.7.0}/.gitignore +5 -1
  5. {argus_testing-0.6.0 → argus_testing-0.7.0}/AGENTS.md +23 -1
  6. argus_testing-0.7.0/CHANGELOG.md +86 -0
  7. argus_testing-0.7.0/CONTRIBUTING.md +64 -0
  8. argus_testing-0.7.0/Dockerfile +11 -0
  9. {argus_testing-0.6.0 → argus_testing-0.7.0}/PKG-INFO +128 -15
  10. argus_testing-0.7.0/PRIVACY.md +72 -0
  11. {argus_testing-0.6.0 → argus_testing-0.7.0}/README.md +118 -12
  12. {argus_testing-0.6.0 → argus_testing-0.7.0}/argus/__init__.py +2 -0
  13. argus_testing-0.7.0/argus/_compat.py +102 -0
  14. argus_testing-0.7.0/argus/adapters/__init__.py +1 -0
  15. argus_testing-0.7.0/argus/adapters/assets/__init__.py +1 -0
  16. argus_testing-0.7.0/argus/adapters/assets/dashboard.css +1 -0
  17. argus_testing-0.7.0/argus/adapters/assets/dashboard.html +3 -0
  18. argus_testing-0.7.0/argus/adapters/assets/dashboard.js +29 -0
  19. argus_testing-0.7.0/argus/adapters/journal.py +33 -0
  20. argus_testing-0.7.0/argus/adapters/logging.py +26 -0
  21. argus_testing-0.7.0/argus/adapters/monitoring.py +257 -0
  22. argus_testing-0.7.0/argus/adapters/reporting/common.py +254 -0
  23. argus_testing-0.7.0/argus/adapters/reporting/html.py +345 -0
  24. argus_testing-0.7.0/argus/adapters/reporting/json.py +36 -0
  25. argus_testing-0.7.0/argus/adapters/reporting/junit.py +56 -0
  26. argus_testing-0.7.0/argus/adapters/reporting/sarif.py +62 -0
  27. argus_testing-0.7.0/argus/adapters/scripts/check_layout_js.js +31 -0
  28. argus_testing-0.7.0/argus/adapters/scripts/extract_elements_js.js +178 -0
  29. argus_testing-0.7.0/argus/adapters/scripts/extract_page_content_js.js +221 -0
  30. argus_testing-0.7.0/argus/adapters/scripts/extract_performance_js.js +27 -0
  31. argus_testing-0.7.0/argus/adapters/scripts/find_visible_element_js.js +91 -0
  32. argus_testing-0.7.0/argus/adapters/scripts/inspect_element_js.js +54 -0
  33. argus_testing-0.7.0/argus/application/actions.py +573 -0
  34. argus_testing-0.7.0/argus/application/capsules.py +162 -0
  35. argus_testing-0.7.0/argus/application/capture.py +124 -0
  36. argus_testing-0.7.0/argus/application/context.py +23 -0
  37. argus_testing-0.7.0/argus/application/coverage.py +289 -0
  38. argus_testing-0.7.0/argus/application/events.py +116 -0
  39. argus_testing-0.7.0/argus/application/evidence.py +162 -0
  40. argus_testing-0.7.0/argus/application/expectations.py +184 -0
  41. argus_testing-0.7.0/argus/application/findings.py +430 -0
  42. argus_testing-0.7.0/argus/application/finish.py +119 -0
  43. argus_testing-0.7.0/argus/application/inspection.py +226 -0
  44. argus_testing-0.7.0/argus/application/journeys.py +368 -0
  45. argus_testing-0.7.0/argus/application/lifecycle.py +258 -0
  46. argus_testing-0.7.0/argus/application/manager.py +242 -0
  47. argus_testing-0.7.0/argus/application/navigation.py +188 -0
  48. argus_testing-0.7.0/argus/application/network_storage.py +399 -0
  49. argus_testing-0.7.0/argus/application/observation.py +507 -0
  50. argus_testing-0.7.0/argus/application/operations.py +158 -0
  51. argus_testing-0.7.0/argus/application/probes.py +248 -0
  52. argus_testing-0.7.0/argus/application/regression.py +121 -0
  53. argus_testing-0.7.0/argus/application/screen.py +910 -0
  54. argus_testing-0.7.0/argus/application/screenshots.py +208 -0
  55. argus_testing-0.7.0/argus/application/session.py +120 -0
  56. argus_testing-0.7.0/argus/application/telemetry.py +36 -0
  57. argus_testing-0.7.0/argus/application/text.py +134 -0
  58. argus_testing-0.7.0/argus/application/verification.py +334 -0
  59. argus_testing-0.7.0/argus/application/verifiers.py +31 -0
  60. argus_testing-0.7.0/argus/bench/__init__.py +0 -0
  61. {argus_testing-0.6.0 → argus_testing-0.7.0}/argus/bench/__main__.py +23 -24
  62. {argus_testing-0.6.0 → argus_testing-0.7.0}/argus/bench/agent_runner.py +150 -59
  63. {argus_testing-0.6.0 → argus_testing-0.7.0}/argus/bench/runner.py +28 -23
  64. {argus_testing-0.6.0 → argus_testing-0.7.0}/argus/bench/scenarios_buggytasks.py +75 -43
  65. {argus_testing-0.6.0 → argus_testing-0.7.0}/argus/bench/scenarios_darkshop.py +81 -39
  66. argus_testing-0.7.0/argus/bootstrap.py +26 -0
  67. {argus_testing-0.6.0 → argus_testing-0.7.0}/argus/browser.py +368 -785
  68. argus_testing-0.7.0/argus/cleanup.py +153 -0
  69. {argus_testing-0.6.0 → argus_testing-0.7.0}/argus/cli.py +145 -81
  70. {argus_testing-0.6.0 → argus_testing-0.7.0}/argus/config.py +22 -8
  71. argus_testing-0.7.0/argus/detector.py +3 -0
  72. {argus_testing-0.6.0 → argus_testing-0.7.0}/argus/differ.py +1 -0
  73. argus_testing-0.7.0/argus/domain/__init__.py +1 -0
  74. argus_testing-0.7.0/argus/domain/contracts.py +60 -0
  75. {argus_testing-0.6.0/argus → argus_testing-0.7.0/argus/domain}/detector.py +51 -38
  76. {argus_testing-0.6.0/argus → argus_testing-0.7.0/argus/domain}/models.py +19 -2
  77. argus_testing-0.7.0/argus/domain/replay.py +44 -0
  78. argus_testing-0.7.0/argus/domain/verification.py +53 -0
  79. argus_testing-0.7.0/argus/entrypoints/__init__.py +0 -0
  80. argus_testing-0.7.0/argus/entrypoints/mcp/__init__.py +0 -0
  81. argus_testing-0.7.0/argus/entrypoints/mcp/catalog.py +215 -0
  82. argus_testing-0.7.0/argus/entrypoints/mcp/server.py +74 -0
  83. {argus_testing-0.6.0 → argus_testing-0.7.0}/argus/explorer.py +34 -42
  84. argus_testing-0.7.0/argus/mcp_server.py +122 -0
  85. argus_testing-0.7.0/argus/models.py +14 -0
  86. {argus_testing-0.6.0 → argus_testing-0.7.0}/argus/planner.py +13 -9
  87. argus_testing-0.7.0/argus/ports.py +41 -0
  88. argus_testing-0.7.0/argus/reporter.py +104 -0
  89. {argus_testing-0.6.0 → argus_testing-0.7.0}/argus/resolver.py +90 -30
  90. argus_testing-0.7.0/argus/runtime.py +64 -0
  91. argus_testing-0.7.0/argus/screen/__init__.py +0 -0
  92. {argus_testing-0.6.0 → argus_testing-0.7.0}/argus/screen/backend.py +136 -59
  93. {argus_testing-0.6.0 → argus_testing-0.7.0}/argus/screen/permissions.py +43 -34
  94. {argus_testing-0.6.0 → argus_testing-0.7.0}/argus/screen/safety.py +4 -3
  95. {argus_testing-0.6.0 → argus_testing-0.7.0}/argus/screen/validate.py +29 -22
  96. argus_testing-0.7.0/argus/security.py +82 -0
  97. argus_testing-0.7.0/argus/settings.py +81 -0
  98. argus_testing-0.7.0/argus/storage.py +104 -0
  99. argus_testing-0.7.0/docs/architecture.md +139 -0
  100. argus_testing-0.7.0/docs/decisions.md +83 -0
  101. argus_testing-0.7.0/docs/implementation-0.7.md +58 -0
  102. argus_testing-0.7.0/docs/interview-guide.md +71 -0
  103. {argus_testing-0.6.0 → argus_testing-0.7.0}/pyproject.toml +25 -2
  104. {argus_testing-0.6.0 → argus_testing-0.7.0}/server.json +2 -2
  105. argus_testing-0.7.0/tests/__init__.py +0 -0
  106. {argus_testing-0.6.0 → argus_testing-0.7.0}/tests/conftest.py +29 -0
  107. {argus_testing-0.6.0 → argus_testing-0.7.0}/tests/test_action_targeting.py +1 -0
  108. argus_testing-0.7.0/tests/test_architecture_runtime.py +308 -0
  109. {argus_testing-0.6.0 → argus_testing-0.7.0}/tests/test_bench_report.py +18 -11
  110. {argus_testing-0.6.0 → argus_testing-0.7.0}/tests/test_browser_shadow.py +31 -14
  111. {argus_testing-0.6.0 → argus_testing-0.7.0}/tests/test_cross_stack.py +9 -2
  112. {argus_testing-0.6.0 → argus_testing-0.7.0}/tests/test_detector_console.py +1 -0
  113. {argus_testing-0.6.0 → argus_testing-0.7.0}/tests/test_detector_network.py +9 -6
  114. {argus_testing-0.6.0 → argus_testing-0.7.0}/tests/test_expectation_oracle.py +38 -17
  115. {argus_testing-0.6.0 → argus_testing-0.7.0}/tests/test_final_hardening.py +338 -113
  116. {argus_testing-0.6.0 → argus_testing-0.7.0}/tests/test_journal_regression.py +27 -17
  117. {argus_testing-0.6.0 → argus_testing-0.7.0}/tests/test_mcp_contract.py +52 -13
  118. argus_testing-0.7.0/tests/test_monitoring.py +111 -0
  119. {argus_testing-0.6.0 → argus_testing-0.7.0}/tests/test_regression_cli.py +24 -3
  120. {argus_testing-0.6.0 → argus_testing-0.7.0}/tests/test_release_metadata.py +11 -1
  121. {argus_testing-0.6.0 → argus_testing-0.7.0}/tests/test_replay_minimize.py +32 -18
  122. {argus_testing-0.6.0 → argus_testing-0.7.0}/tests/test_replay_receipt.py +33 -16
  123. {argus_testing-0.6.0 → argus_testing-0.7.0}/tests/test_replay_trace.py +34 -4
  124. {argus_testing-0.6.0 → argus_testing-0.7.0}/tests/test_reporter_badge.py +16 -7
  125. {argus_testing-0.6.0 → argus_testing-0.7.0}/tests/test_reproduction_receipt.py +454 -266
  126. {argus_testing-0.6.0 → argus_testing-0.7.0}/tests/test_resolver.py +173 -71
  127. argus_testing-0.7.0/tests/test_runtime_limits.py +95 -0
  128. {argus_testing-0.6.0 → argus_testing-0.7.0}/tests/test_screen_permissions.py +6 -2
  129. {argus_testing-0.6.0 → argus_testing-0.7.0}/tests/test_screen_safety.py +4 -3
  130. {argus_testing-0.6.0 → argus_testing-0.7.0}/tests/test_session_lifecycle.py +98 -11
  131. {argus_testing-0.6.0 → argus_testing-0.7.0}/tests/test_state_capsules.py +15 -8
  132. argus_testing-0.7.0/tests/test_stdio_protocol.py +31 -0
  133. argus_testing-0.7.0/tests/test_storage_cleanup.py +165 -0
  134. {argus_testing-0.6.0 → argus_testing-0.7.0}/tests/test_substrate.py +5 -1
  135. {argus_testing-0.6.0 → argus_testing-0.7.0}/tests/test_visual_inspection.py +5 -1
  136. argus_testing-0.6.0/CHANGELOG.md +0 -44
  137. argus_testing-0.6.0/Dockerfile +0 -9
  138. argus_testing-0.6.0/PRIVACY.md +0 -33
  139. argus_testing-0.6.0/argus/mcp_server.py +0 -5631
  140. argus_testing-0.6.0/argus/reporter.py +0 -630
  141. {argus_testing-0.6.0 → argus_testing-0.7.0}/LICENSE +0 -0
  142. {argus_testing-0.6.0 → argus_testing-0.7.0}/SECURITY.md +0 -0
  143. {argus_testing-0.6.0/argus/bench → argus_testing-0.7.0/argus/adapters/reporting}/__init__.py +0 -0
  144. {argus_testing-0.6.0/argus/screen → argus_testing-0.7.0/argus/adapters/scripts}/__init__.py +0 -0
  145. {argus_testing-0.6.0/tests → argus_testing-0.7.0/argus/application}/__init__.py +0 -0
  146. {argus_testing-0.6.0 → argus_testing-0.7.0}/assets/argus-icon.svg +0 -0
  147. {argus_testing-0.6.0 → argus_testing-0.7.0}/bench-results/buggytasks.json +0 -0
  148. {argus_testing-0.6.0 → argus_testing-0.7.0}/bench-results/buggytasks.md +0 -0
  149. {argus_testing-0.6.0 → argus_testing-0.7.0}/bench-results/darkshop.json +0 -0
  150. {argus_testing-0.6.0 → argus_testing-0.7.0}/bench-results/darkshop.md +0 -0
  151. {argus_testing-0.6.0 → argus_testing-0.7.0}/bench-results/matrix.json +0 -0
  152. {argus_testing-0.6.0 → argus_testing-0.7.0}/bench-results/matrix.md +0 -0
  153. {argus_testing-0.6.0 → argus_testing-0.7.0}/bench-results/screen_validation.json +0 -0
  154. {argus_testing-0.6.0 → argus_testing-0.7.0}/examples/focus.yaml +0 -0
  155. {argus_testing-0.6.0 → argus_testing-0.7.0}/examples/mcp-config.json +0 -0
  156. {argus_testing-0.6.0 → argus_testing-0.7.0}/glama.json +0 -0
  157. {argus_testing-0.6.0 → argus_testing-0.7.0}/human-eye-fixture/app.py +0 -0
  158. {argus_testing-0.6.0 → argus_testing-0.7.0}/llms-install.md +0 -0
  159. {argus_testing-0.6.0 → argus_testing-0.7.0}/test-site/app.py +0 -0
@@ -0,0 +1,19 @@
1
+ .git
2
+ .github
3
+ .codex
4
+ .venv
5
+ **/__pycache__
6
+ *.py[cod]
7
+ .pytest_cache
8
+ .ruff_cache
9
+ .coverage
10
+ build
11
+ dist
12
+ *.egg-info
13
+ argus-reports
14
+ test-reports
15
+ screenshots
16
+ tests
17
+ test-site
18
+ docs
19
+ .DS_Store
@@ -29,7 +29,16 @@ jobs:
29
29
  cache: pip
30
30
  - name: Install package
31
31
  run: python -m pip install --upgrade pip && python -m pip install -e '.[dev]'
32
+ - name: Smoke-test package import
33
+ run: python -c "from argus.mcp_server import mcp; assert mcp is not None"
34
+ - name: Static checks
35
+ run: |
36
+ ruff check argus tests
37
+ ruff format --check argus tests
38
+ mypy
32
39
  - name: Install Chromium
33
40
  run: python -m playwright install --with-deps chromium
34
41
  - name: Run tests
42
+ env:
43
+ ARGUS_REQUIRE_BROWSER: "1"
35
44
  run: python -m pytest
@@ -21,6 +21,8 @@ jobs:
21
21
  cache: pip
22
22
  - name: Install build and test dependencies
23
23
  run: python -m pip install --upgrade pip && python -m pip install build twine -e '.[dev]'
24
+ - name: Smoke-test package import
25
+ run: python -c "from argus.mcp_server import mcp; assert mcp is not None"
24
26
  - name: Install Chromium
25
27
  run: python -m playwright install --with-deps chromium
26
28
  - name: Verify release metadata
@@ -40,6 +42,8 @@ jobs:
40
42
  assert server["packages"][0]["version"] == version
41
43
  PY
42
44
  - name: Run tests
45
+ env:
46
+ ARGUS_REQUIRE_BROWSER: "1"
43
47
  run: python -m pytest
44
48
  - name: Build distributions
45
49
  run: python -m build
@@ -15,4 +15,8 @@ argus-reports/
15
15
  .codex/
16
16
  test-reports/
17
17
  CLAUDE.md
18
- docs/
18
+ docs/*
19
+ !docs/architecture.md
20
+ !docs/decisions.md
21
+ !docs/interview-guide.md
22
+ !docs/implementation-0.7.md
@@ -53,7 +53,7 @@ the user's broader task. The short version:
53
53
  |------|---------|
54
54
  | `start_session(url, review_mode=..., goals=[...], constraints=[...], time_budget_minutes=...)` | Launch Playwright, establish the review contract, and return the one-time QA protocol plus initial observation. The budget is advisory; `0` means none. |
55
55
  | `observe()` | URL + interactive elements (description-keyed) + visible feedback + counts + ARIA + viewport state. Read this first, after every action. |
56
- | `coverage_update(goal, status, evidence)` | Update a supplied goal as `untested`, `in_progress`, `exercised`, or `blocked`. Concrete evidence is mandatory for `exercised` and `blocked`; Argus never guesses semantic completion. |
56
+ | `coverage_update(goal, status, evidence)` | Mark a goal `in_progress` before its journey to open a precise evidence window. `exercised` and `blocked` require an explanation and automatically link URLs, value-redacted actions, screenshots, checks, and findings; Argus never guesses semantic completion. |
57
57
  | `click_what(description)` | Click the element matching `description`. Returns the top candidates if ambiguous — rephrase rather than guess. |
58
58
  | `type_into(description, text)` / `select_into(description, value)` | Inputs and dropdowns by description. |
59
59
  | `test_action(target, expect=...)` | Click + before/after diff in one call. Pass `expect` to PREDICT the outcome ({"count":{"label":"tasks","delta":1}}, {"gains":"Buy milk"}, {"removes":...}, {"text_present":...}, {"toast":...}, {"url_changed":true}) and Argus reports MATCH / SURPRISE — a surprise is a bug lead. Also shows CROSS-STACK: which requests the click fired (methods/statuses) and a CHECK nudge when a message appeared without a matching write. |
@@ -88,6 +88,7 @@ the user's broader task. The short version:
88
88
  ```
89
89
  start_session(url, goals=[...], constraints=[...], time_budget_minutes=15)
90
90
  # initial result already MAPS the page
91
+ coverage_update(goal, "in_progress") # opens this goal's evidence window
91
92
  # USE IT — pick a real goal, walk it
92
93
  # end-to-end, carrying state across pages
93
94
  # HYPOTHESIZE — what could go wrong
@@ -155,6 +156,10 @@ Don't record speculation, polish nits, or static a11y / SEO that
155
156
  - `argus-mcp --list-tools` — selected tool profile and exported names.
156
157
  - `argus-mcp --tool-profile core|screen|full` — control discovery size.
157
158
  - `argus-mcp --unsafe` — turn on `eval_js` (off by default).
159
+ - `argus-mcp --monitor-port 8765` — enable the read-only loopback dashboard,
160
+ health/readiness endpoints, SSE events and metrics; use `0` for a free port.
161
+ - `argus-cleanup --keep-runs 20` — dry-run report retention; add `--apply`
162
+ to remove complete old run artifacts without touching journals or capsules.
158
163
  - `python -m argus.bench --target all` — reproduce the 34 / 34 matrix.
159
164
  - `python -m argus.screen.validate <app names...>` — read-only AX walk
160
165
  over running apps, JSON output.
@@ -171,6 +176,23 @@ Don't record speculation, polish nits, or static a11y / SEO that
171
176
  - Every `screen_click_what` / `screen_type_into` writes a
172
177
  before-and-after screenshot pair to the action trail.
173
178
 
179
+ ## Runtime boundaries (0.7)
180
+
181
+ All calls in one runtime are serialized. Defaults are a 5-second queue wait,
182
+ 120-second operation deadline and 10-second cleanup deadline per backend.
183
+ Cancellation/timeout closes the backend; do not blindly retry a write because
184
+ the application may already have processed it. Start a new session after a
185
+ failed lifecycle transition. Monitoring contains state/counts only, not inputs.
186
+
187
+ Input-dependent exported replay steps are marked `requires_input`. Never replay
188
+ redaction placeholders as real values. Capsules contain raw credentials and
189
+ must not be shared. Screenshots and explicit finding evidence can still contain
190
+ application data.
191
+
192
+ `argus-regression` exits 0 for no reproduced known findings (including no
193
+ journal), 1 for still-present findings, 2 for operational/storage failures and
194
+ 3 for inconclusive checks. An empty journal is not proof of app correctness.
195
+
174
196
  ## What changed in 0.5 (if you knew 0.4)
175
197
 
176
198
  - `get_page_state` → `observe` (no integer indices).
@@ -0,0 +1,86 @@
1
+ # Changelog
2
+
3
+ ## 0.7.0 - 2026-10-19
4
+
5
+ - Split MCP adaptation from focused application services, domain contracts and
6
+ adapters; add explicit runtime composition and injectable browser, journal,
7
+ verification and report extension points.
8
+ - Serialize all session operations; classify operational errors, validate
9
+ runtime/capture limits, and clean up on failed startup, cancellation, timeout
10
+ and shutdown. Do not automatically retry browser writes.
11
+ - Add optional loopback monitoring: dashboard, liveness/readiness, versioned
12
+ status, bounded SSE with reconnect gaps, and Prometheus metrics. Keep all
13
+ monitoring payloads free of tool arguments and page contents.
14
+ - Keep input values in a session-local vault and omit them from persisted
15
+ action steps/replay exports, including bulk form filling and paste paths.
16
+ - Share CLI/MCP regression through application services and a verifier registry;
17
+ use exit 3 for inconclusive checks and exit 2 for corrupted journals.
18
+ - Replace stale-file lock deletion with OS-backed file locking; coordinate
19
+ report generation and cleanup and split individual report exporters.
20
+ - Add real stdio MCP and HTTP-monitor integration tests, runtime fault tests,
21
+ architecture boundaries, Ruff checks and scoped core type checking in CI.
22
+ - Add architecture, decision, extension and interview documentation. Existing
23
+ public MCP tool names and profiles are retained.
24
+
25
+ ### Also included since 0.6
26
+
27
+ - Bound browser network, error, download, and dialog capture; avoid loading
28
+ binary or oversized response bodies and redact credentials at capture time.
29
+ - Give every run a unique artifact identity so screenshots and reports cannot
30
+ overwrite evidence from another session.
31
+ - Add atomic, schema-versioned journal and capsule persistence with visible
32
+ diagnostics instead of silent write failures.
33
+ - Add the dry-run-first `argus-cleanup` command for removing complete old report
34
+ runs without touching regression journals or state capsules.
35
+ - Serialize session lifecycle transitions and surface teardown, capture-limit,
36
+ and secondary-report warnings in the final session summary.
37
+ - Keep the MCP SDK on its supported 1.x API and fail fast on package-import
38
+ incompatibilities before browser installation in CI and release builds.
39
+ - Link each completed or blocked coverage goal to the URLs, value-redacted
40
+ actions, screenshots, persistence checks, bugs, and observations produced
41
+ during its testing window.
42
+ - Render structured goal evidence in HTML reports and preserve the same stable
43
+ shape in JSON reports.
44
+
45
+ ## 0.6.0 - 2026-07-21
46
+
47
+ - Move the full QA protocol from the global MCP instruction into the
48
+ one-time `start_session` response, with a regression budget for the default
49
+ tool context.
50
+ - Add natural-language testing goals, user constraints, and an advisory time
51
+ budget to `start_session`.
52
+ - Add `coverage_update` with evidence-required `exercised` and `blocked`
53
+ states; keep goal and discovered-page coverage visible during observations.
54
+ - Preserve completed, blocked, and unfinished coverage in HTML and JSON
55
+ reports and in the final session summary.
56
+
57
+ ## 0.5.0 - 2026-07-14
58
+
59
+ Argus 0.5 replaces the index-keyed MCP interface with a smaller,
60
+ description-keyed workflow and makes evidence preservation part of the
61
+ public contract.
62
+
63
+ - Add focused `core`, `screen`, and `full` MCP tool profiles.
64
+ - Replace integer-index actions with `observe`, `click_what`, `type_into`,
65
+ `select_into`, and description-keyed inspection tools.
66
+ - Add independently verified reproduction receipts for text and HTTP-status
67
+ findings, including cold replay for multi-step journeys.
68
+ - Preserve complete evidence in JSON, HTML, JUnit, and SARIF reports while
69
+ keeping HTML screenshot previews compact.
70
+ - Correlate console and network symptoms without duplicating root causes.
71
+ - Add native macOS screen-mode permission checks, action limits, abort control,
72
+ and before/after evidence capture.
73
+ - Improve visual inspection with element crops, screenshot diffs, bounded
74
+ layout checks, and finite CSS-transition waits.
75
+ - Add packaging, CI, PyPI Trusted Publishing, and official MCP Registry
76
+ metadata for repeatable releases.
77
+
78
+ ### Breaking changes from 0.4
79
+
80
+ - `get_page_state` is now `observe`.
81
+ - `click`, `type_text`, and `select_option` are replaced by description-keyed
82
+ actions.
83
+ - `verify_action` is now `verify_persistence`.
84
+ - `test_crud` is removed; compose journeys from the focused tools instead.
85
+ - Findings must be explicitly recorded with `record_bug` or
86
+ `record_observation`.
@@ -0,0 +1,64 @@
1
+ # Contributing
2
+
3
+ Use Python 3.10 or newer. CI runs 3.10 and 3.12. Browser checks are local and do
4
+ not call a model provider:
5
+
6
+ ```bash
7
+ python -m venv .venv
8
+ source .venv/bin/activate
9
+ pip install -e '.[dev]'
10
+ playwright install chromium
11
+ ruff check argus tests
12
+ ruff format --check argus tests
13
+ mypy
14
+ ARGUS_REQUIRE_BROWSER=1 pytest -q
15
+ ```
16
+
17
+ `mypy` covers the contracts, settings and runtime core listed in `pyproject.toml`;
18
+ the whole legacy codebase is not yet strictly typed. CI treats unavailable-browser
19
+ skips as failures. macOS AX permissions and real native-app behavior need a
20
+ separate macOS manual check; Linux CI does not claim to test that integration.
21
+
22
+ ## Where changes belong
23
+
24
+ - Tool arguments, MCP metadata and profile selection: `entrypoints/mcp/`.
25
+ - A new QA operation: the appropriate `application/` service and `OPERATIONS`
26
+ registry; add catalog metadata, README documentation and a protocol test.
27
+ - Pure rules and typed data: `domain/`; no browser, MCP or HTTP imports here.
28
+ - New verification: register an async strategy on `runtime.verifiers`. Return
29
+ an explicit receipt with `attempted` and a three-state `reproduced` result.
30
+ Automatic regression deliberately permits only read-only built-in checks.
31
+ - New report format: a pure renderer under `adapters/reporting/`, injected via
32
+ `Reporter(exporters=...)`. HTML remains the primary report.
33
+ - A different journal: implement `JournalPort` and wire it in `bootstrap.py`.
34
+ The repository owns merge atomicity; callers should not read-then-write.
35
+ - Browser actions: add a public adapter method. Application services must not
36
+ access `_page`, `_context`, `_locator` or other adapter private state.
37
+ - Monitor additions: `adapters/monitoring.py` and its packaged `assets/`.
38
+ Never add raw inputs, arbitrary URLs, page contents or credentials to events.
39
+
40
+ Each runtime is explicit. Use `create_runtime(Settings(...))` and
41
+ `runtime.execute(name, operation, ...)`; do not set global environment variables
42
+ to switch sessions. The context variable is only the invocation-local bridge
43
+ for existing service signatures. `mcp_server` compatibility imports are not the
44
+ application API for new code.
45
+
46
+ ## Verification and releases
47
+
48
+ Lifecycle tests use fake backends to deterministically force failures and
49
+ cancellation. Browser tests use temporary local fixtures. `test_stdio_protocol.py`
50
+ launches the real entry point and performs initialize/list/call/image/end over
51
+ MCP stdio. Monitoring tests use a real loopback socket and SSE disconnects.
52
+
53
+ For the scripted benchmark, start `test-site/app.py` and
54
+ `human-eye-fixture/app.py`, then run `python -m argus.bench --target all`. This is
55
+ a capability ceiling, not a real-agent success rate. Model-provider benchmarks
56
+ consume subscription/API usage and must be explicitly authorized.
57
+
58
+ For release, synchronize `pyproject.toml` and both version fields in
59
+ `server.json`, update `CHANGELOG.md`, build with `python -m build`, check with
60
+ `twine check`, and smoke-test the wheel outside the source directory. JS and
61
+ dashboard assets are package resources and must be present in the wheel.
62
+ Publish only after CI passes. The GitHub release workflow builds/tests again,
63
+ publishes to PyPI through Trusted Publishing, then publishes MCP Registry
64
+ metadata. Do not commit keys, capsules, generated reports or local test data.
@@ -0,0 +1,11 @@
1
+ FROM python:3.12-slim
2
+
3
+ WORKDIR /app
4
+
5
+ COPY . .
6
+
7
+ RUN pip install --no-cache-dir . \
8
+ && playwright install --with-deps chromium \
9
+ && rm -rf /var/lib/apt/lists/*
10
+
11
+ ENTRYPOINT ["argus-mcp"]
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: argus-testing
3
- Version: 0.6.0
3
+ Version: 0.7.0
4
4
  Summary: Autonomous QA MCP that tests apps like a real testing engineer and verifies every certified bug
5
5
  Project-URL: Homepage, https://yichenwu.dev/projects/argus
6
6
  Project-URL: Documentation, https://github.com/chriswu727/argus#readme
@@ -17,17 +17,24 @@ Classifier: Programming Language :: Python :: 3
17
17
  Classifier: Topic :: Software Development :: Testing
18
18
  Requires-Python: >=3.10
19
19
  Requires-Dist: click>=8.0.0
20
+ Requires-Dist: filelock<4,>=3.12
20
21
  Requires-Dist: jinja2>=3.0.0
21
22
  Requires-Dist: litellm>=1.40.0
22
- Requires-Dist: mcp[cli]>=1.0.0
23
+ Requires-Dist: mcp[cli]<2.0.0,>=1.0.0
23
24
  Requires-Dist: pillow>=10.0.0
24
25
  Requires-Dist: playwright>=1.40.0
25
26
  Requires-Dist: pydantic>=2.0.0
26
27
  Requires-Dist: pyyaml>=6.0
27
28
  Requires-Dist: rich>=13.0.0
29
+ Requires-Dist: starlette<2,>=0.27
30
+ Requires-Dist: typing-extensions>=4.9
31
+ Requires-Dist: uvicorn<1,>=0.31
28
32
  Provides-Extra: dev
33
+ Requires-Dist: httpx<1,>=0.27; extra == 'dev'
34
+ Requires-Dist: mypy<3,>=2.4; extra == 'dev'
29
35
  Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
30
36
  Requires-Dist: pytest>=8.0.0; extra == 'dev'
37
+ Requires-Dist: ruff<0.18,>=0.17; extra == 'dev'
31
38
  Requires-Dist: tomli>=2.0.0; (python_version < '3.11') and extra == 'dev'
32
39
  Provides-Extra: mac
33
40
  Requires-Dist: pyobjc-framework-applicationservices>=10.0; (sys_platform == 'darwin') and extra == 'mac'
@@ -81,12 +88,17 @@ flowchart LR
81
88
  C --> A
82
89
  B -->|bug| D["verify_persistence — reload from a clean state"]
83
90
  D -->|symptom repeats| E(["VERIFIED"])
84
- D -->|symptom gone| F(["dropped — no false positive"])
91
+ D -->|symptom gone or uncertain| F(["not certified"])
85
92
  E --> G[["report: HTML · JSON · JUnit · SARIF"]]
86
93
  ```
87
94
 
88
95
  The agent is the intelligence. Argus supplies concise QA guidance, a description-keyed tool surface (`click_what("Login button")`, not `click(7)`), a goal coverage ledger, and a **reproduction-receipt engine** that turns "the model thinks this is a bug" into "this bug is real, here's the proof."
89
96
 
97
+ A receipt confirms the specified observable symptom, not every possible root
98
+ cause. A clean load preserves authentication and browser storage by default;
99
+ replay can repeat real writes. Qualitative observations and inconclusive checks
100
+ remain distinct from verified findings.
101
+
90
102
  ---
91
103
 
92
104
  ## Quick start
@@ -140,7 +152,7 @@ Then just ask, in your agent session:
140
152
 
141
153
  That's it. The agent drives; Argus keeps it honest and writes the report.
142
154
 
143
- For a scoped review, the host can give `start_session` explicit `goals`, `constraints`, and an advisory `time_budget_minutes`. Argus returns the full testing protocol once, keeps outstanding goals and discovered pages visible in later observations, and requires concrete evidence before `coverage_update` can mark a goal `exercised` or `blocked`. The final HTML and JSON reports preserve both completed and unfinished coverage instead of implying that an incomplete pass was comprehensive.
155
+ For a scoped review, the host can give `start_session` explicit `goals`, `constraints`, and an advisory `time_budget_minutes`. Argus returns the full testing protocol once and keeps outstanding goals and discovered pages visible in later observations. Mark a goal `in_progress` before its journey; when `coverage_update` marks it `exercised` or `blocked`, Argus requires a concrete explanation and automatically links the URLs, value-redacted actions, screenshots, persistence checks, bugs, and observations produced in that testing window. The final HTML and JSON reports preserve both completed and unfinished coverage instead of implying that an incomplete pass was comprehensive.
144
156
 
145
157
  <details>
146
158
  <summary><b>pip installation</b></summary>
@@ -180,6 +192,95 @@ Same description-keyed tools, but the target is whatever app is foreground on ma
180
192
 
181
193
  </details>
182
194
 
195
+ ### Artifact and resource limits
196
+
197
+ Argus writes each run's screenshots into its own run directory so later tests
198
+ cannot overwrite earlier evidence. Long browser sessions also keep bounded
199
+ in-memory event logs and only read response bodies for inspectable API traffic;
200
+ binary and oversized bodies are skipped before they enter Python memory.
201
+
202
+ Report cleanup is explicit and dry-run by default. The newest 20 complete runs
203
+ are protected in this example; `.argus` journals and state capsules are never
204
+ deleted:
205
+
206
+ ```bash
207
+ argus-cleanup --output ./argus-reports --keep-runs 20
208
+ argus-cleanup --output ./argus-reports --keep-runs 20 --apply
209
+ ```
210
+
211
+ Use `--older-than-days` and `--max-size-mb` for stricter policies. Advanced
212
+ limits can be adjusted with `ARGUS_MAX_NETWORK_EVENTS`,
213
+ `ARGUS_MAX_ERROR_EVENTS`, `ARGUS_MAX_DOWNLOAD_EVENTS`,
214
+ `ARGUS_MAX_DIALOG_EVENTS`, `ARGUS_MAX_RESPONSE_BODY_BYTES`, and
215
+ `ARGUS_MAX_RESPONSE_READ_BYTES`. Responses without a declared length are skipped
216
+ by default; `ARGUS_CAPTURE_UNKNOWN_LENGTH_BODY=1` opts into reading them. When a
217
+ limit discards old evidence, Argus says so in tool output and the final session
218
+ summary.
219
+
220
+ ### Live monitoring (0.7)
221
+
222
+ Add a monitor port to the command your MCP client launches:
223
+
224
+ ```bash
225
+ argus-mcp --monitor-port 8765
226
+ # Or choose an available port automatically:
227
+ argus-mcp --monitor-port 0
228
+ ```
229
+
230
+ Open `http://127.0.0.1:8765` for session state, active operation and duration,
231
+ last progress, calls, operational failures, findings and recent events. The
232
+ selected URL is printed to **stderr**, so stdio MCP messages stay intact.
233
+ `ARGUS_MONITOR_PORT` is equivalent; monitoring is off by default.
234
+
235
+ | Route | Output |
236
+ |---|---|
237
+ | `/` | Local live dashboard |
238
+ | `/healthz` | HTTP process liveness |
239
+ | `/readyz` | Runtime initialized and not shutting down; 503 otherwise |
240
+ | `/api/status` | Versioned state snapshot, counts and capture drops |
241
+ | `/api/events` | Server-Sent Events, `Last-Event-ID` reconnect and gap notices |
242
+ | `/metrics` | Prometheus text counters and operation duration sums/counts |
243
+
244
+ The monitor binds only to `127.0.0.1`, rejects unrelated Host/Origin headers,
245
+ and has no action endpoints. It emits no page contents, URLs, typed values,
246
+ screenshots or tool arguments. It is **not an authenticated remote service**;
247
+ do not expose it through a public proxy. Event retention is bounded (512 by
248
+ default), with at most 32 simultaneous SSE subscribers.
249
+
250
+ Runtime settings are validated at startup. Explicit command-line options
251
+ override environment variables, which override defaults:
252
+
253
+ | Environment variable | Default |
254
+ |---|---:|
255
+ | `ARGUS_OPERATION_TIMEOUT_S` | 120 seconds |
256
+ | `ARGUS_QUEUE_TIMEOUT_S` | 5 seconds |
257
+ | `ARGUS_CLEANUP_TIMEOUT_S` | 10 seconds per backend |
258
+ | `ARGUS_EVENT_CAPACITY` | 512 events |
259
+ | `ARGUS_OUTPUT_DIR` | `./argus-reports` |
260
+
261
+ One runtime owns one active session. Actions and lifecycle changes are
262
+ serialized; an operation timeout cancels the action and closes the backend.
263
+ Side-effecting actions are never automatically retried. A separate MCP process
264
+ is the supported way to run another independently controlled session.
265
+
266
+ ### Regression gates and evidence privacy
267
+
268
+ ```bash
269
+ argus-regression http://localhost:3000 --output ./argus-reports
270
+ ```
271
+
272
+ Exit codes: `0` no known symptom reproduced (or no journal), `1` a known symptom
273
+ still reproduces, `2` operational/storage failure, `3` inconclusive. An exit of
274
+ zero is not proof of complete application correctness. Automatic regression
275
+ uses built-in text/HTTP checks, never write-performing replay.
276
+
277
+ Typed, pasted and selected input values are held in a session-local input vault,
278
+ not in action traces or exported replay steps. Exported steps that need input
279
+ are marked `requires_input`; they cannot be replayed as if a redacted value were
280
+ real. Capsules deliberately contain credentials and are saved with owner-only
281
+ file permissions on POSIX. Reports and screenshots can still contain visible
282
+ application data; see [Privacy](PRIVACY.md).
283
+
183
284
  ---
184
285
 
185
286
  ## Why Argus is different
@@ -278,7 +379,7 @@ uvx --from argus-testing argus-mcp --tool-profile full --list-tools
278
379
  |-------|---------|
279
380
  | `start_session` | Start an `exploratory`, `visual`, or `regression` browser review; optionally accept `goals`, `constraints`, and `time_budget_minutes`; return the one-time protocol and initial observation. |
280
381
  | `observe` | Return URL, title, description-keyed interactive elements, counts, visible feedback, ARIA tree, and viewport state. |
281
- | `coverage_update` | Mark a supplied goal `untested`, `in_progress`, `exercised`, or `blocked`; exercised and blocked states require concrete evidence. |
382
+ | `coverage_update` | Open a goal evidence window with `in_progress`, then mark it `exercised` or `blocked`; terminal states require an explanation and automatically link session evidence. |
282
383
  | `click_what` | Click the element best matching a natural-language description; return candidates instead of guessing when ambiguous. |
283
384
  | `type_into` · `select_into` | Resolve a field by description, then type text or select an option. |
284
385
  | `hover_what` · `press_key` | Exercise hover states and keyboard interactions against description-keyed targets. |
@@ -298,7 +399,7 @@ uvx --from argus-testing argus-mcp --tool-profile full --list-tools
298
399
 
299
400
  </details>
300
401
 
301
- Reports keep original screenshots as evidence and, by default, write compact WebP previews under `report-assets/` instead of base64-embedding every full-size PNG into the HTML. Set `ARGUS_PORTABLE_REPORT=1` when a single self-contained HTML file is more important than size. JSON output includes complete reproduction receipts, the coverage contract, constraints, review mode, tool-call and recorded-step counts, screenshot metadata, and qualitative observations. JUnit suite failure totals match the emitted `<failure>` nodes.
402
+ Reports keep original screenshots as evidence and, by default, write compact WebP previews under `report-assets/` instead of base64-embedding every full-size PNG into the HTML. Set `ARGUS_PORTABLE_REPORT=1` when a single self-contained HTML file is more important than size. JSON output includes complete reproduction receipts, the coverage contract and its structured evidence references, constraints, review mode, tool-call and recorded-step counts, screenshot metadata, and qualitative observations. JUnit suite failure totals match the emitted `<failure>` nodes.
302
403
 
303
404
  <details>
304
405
  <summary><b>Screen profile — 14 tools</b></summary>
@@ -388,18 +489,30 @@ The global instruction is intentionally tiny so it does not repeat a long QA pro
388
489
 
389
490
  ```
390
491
  argus/
391
- ├── mcp_server.py # tool surface + role instructions + reproduction-receipt engine
392
- ├── browser.py # Playwright backend: DOM/ARIA extraction, capsule/replay
393
- ├── resolver.py # description → element (web + screen)
394
- ├── reporter.py # HTML + JSON + JUnit + SARIF
395
- ├── detector.py # console + network capture (only)
396
- ├── cli.py # argus (explore) + argus-regression
397
- ├── bench/ # deterministic ceiling + real-LLM recall harness
398
- └── screen/ # macOS AX backend, permissions, safety
492
+ ├── mcp_server.py # process entry point and compatibility imports
493
+ ├── entrypoints/mcp/ # public tool catalog, profiles and MCP adaptation
494
+ ├── application/ # session manager and focused QA use cases
495
+ ├── domain/ # models, errors, states, replay and verification contracts
496
+ ├── adapters/ # monitoring, logs, file journal, report exporters, JS assets
497
+ ├── bootstrap.py # composition root: injected backend/repository factories
498
+ ├── ports.py # narrow lifecycle, observation, verification and storage protocols
499
+ ├── settings.py # validated, per-runtime configuration
500
+ ├── browser.py # Playwright adapter (public operations; private page ownership)
501
+ ├── screen/ # macOS AX adapter, permissions, safety
502
+ ├── reporter.py # atomic report orchestration and exporter registry
503
+ ├── resolver.py # description → element (web + screen)
504
+ ├── cli.py # autonomous exploration and shared regression entry point
505
+ └── bench/ # deterministic capability + optional real-LLM harness
399
506
  test-site/ # BuggyTasks (22 mechanical bugs)
400
507
  human-eye-fixture/ # DarkShop (12 human-eye bugs)
401
508
  ```
402
509
 
510
+ Start with [Architecture](docs/architecture.md), [design decisions](docs/decisions.md)
511
+ and [Contributing](CONTRIBUTING.md). The [interview guide](docs/interview-guide.md)
512
+ maps design claims to implementation, tests and explicit limitations. The
513
+ autonomous LiteLLM exploration loop remains a separate workflow; shared
514
+ regression does not import or mutate the MCP server.
515
+
403
516
  ---
404
517
 
405
518
  <div align="center">
@@ -0,0 +1,72 @@
1
+ # Privacy
2
+
3
+ Argus is a local-first testing tool. The project does not operate an Argus
4
+ cloud service, user account system, analytics endpoint, or telemetry collector.
5
+
6
+ ## Data Argus handles
7
+
8
+ During a test, Argus may process page text, accessibility data, URLs, browser
9
+ console and network events, testing goals and constraints, verification targets,
10
+ cookies or storage when the corresponding tools are called, screenshots,
11
+ downloaded-file metadata, and native macOS accessibility information in screen
12
+ mode. Coverage reports omit typed and pasted input values from action references,
13
+ but goals, constraints, verification targets, finding titles, and screenshots are
14
+ evidence and may contain application data; do not put secrets in those fields.
15
+
16
+ Reports, screenshots, reproduction receipts, state capsules, and regression
17
+ journals are written locally under `./argus-reports` by default. Set
18
+ `ARGUS_OUTPUT_DIR` to choose another location. `argus-cleanup` can plan and
19
+ remove complete old report runs while leaving journals and state capsules
20
+ untouched; it is a dry run unless `--apply` is passed.
21
+
22
+ Captured request headers, response headers, request bodies, and inspectable API
23
+ response bodies are redacted for common credential-bearing keys before they are
24
+ retained. Response bodies are bounded, and binary or oversized bodies are not
25
+ loaded for inspection. These safeguards reduce common exposure paths but cannot
26
+ recognize every application-specific secret format.
27
+
28
+ ## Where data can go
29
+
30
+ - The MCP host and its configured model provider receive the Argus tool inputs
31
+ and outputs that the host includes in a conversation. Their privacy terms
32
+ apply independently of Argus.
33
+ - Browser tests connect to the URLs the user or agent chooses to test, along
34
+ with resources those pages load.
35
+ - CLI mode uses LiteLLM and sends planner context to the model provider selected
36
+ by the user. MCP mode does not require an Argus API key or an Argus-operated
37
+ model service.
38
+ - Installing or upgrading through PyPI, `pip`, or `uvx` contacts those package
39
+ distribution services under their own policies.
40
+
41
+ Argus does not intentionally transmit test artifacts to the project maintainer.
42
+ Review reports and screenshots before sharing them because they can contain
43
+ sensitive application data.
44
+
45
+ ## Replay inputs and state capsules
46
+
47
+ Typed, pasted and selected values are stored in a per-session in-memory vault.
48
+ Action traces retain opaque references; exports omit those references and mark
49
+ input-dependent steps `requires_input`. Closing, replacing, cancelling or timing
50
+ out a session clears its vault. This is reference removal, not a guarantee of
51
+ cryptographic erasure from Python memory, swap or process dumps. The host already
52
+ knows the inputs it supplied. Page content, human-authored evidence, prompts,
53
+ console messages and screenshots may independently reveal the same information.
54
+
55
+ State capsules intentionally contain raw cookies and browser storage. They use
56
+ atomic writes, schema validation, owner-only files on POSIX, and a defensive
57
+ `.gitignore`. They are not encrypted. They persist until explicitly deleted by
58
+ the user; ordinary report cleanup does not remove them. Do not share them.
59
+
60
+ ## Optional local monitor and diagnostic logs
61
+
62
+ `--monitor-port` enables a read-only HTTP dashboard on `127.0.0.1` only. Status,
63
+ SSE events and metrics contain operation names, timestamps, state, error codes,
64
+ run IDs and counts, not tool arguments, page URLs, page text, input values or
65
+ images. The event ring is bounded and process-local, not durable audit storage.
66
+ Host/Origin validation reduces cross-site access; there is no authentication
67
+ against other local processes. Do not expose the port publicly.
68
+
69
+ Structured Argus diagnostics go to stderr, never the MCP stdout channel.
70
+ Operation diagnostics use allowlisted metadata rather than raw arguments or
71
+ exception tracebacks. Dependency diagnostics and explicit tool outputs have
72
+ their own formats. Review host logs before sharing them.