bugcap 0.5.0__tar.gz → 0.5.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 (84) hide show
  1. {bugcap-0.5.0/src/bugcap.egg-info → bugcap-0.5.1}/PKG-INFO +14 -9
  2. {bugcap-0.5.0 → bugcap-0.5.1}/README.md +12 -8
  3. {bugcap-0.5.0 → bugcap-0.5.1}/pyproject.toml +12 -2
  4. bugcap-0.5.1/src/bugcap/__init__.py +1 -0
  5. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap/cli.py +4 -4
  6. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap/live.py +1 -1
  7. {bugcap-0.5.0 → bugcap-0.5.1/src/bugcap.egg-info}/PKG-INFO +14 -9
  8. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap.egg-info/requires.txt +1 -0
  9. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_backends.py +0 -1
  10. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_cli_init_capture_list.py +1 -1
  11. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_cli_live_headless.py +5 -1
  12. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_cli_media.py +2 -2
  13. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_cli_no_image_delete.py +1 -1
  14. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_cli_setup.py +9 -0
  15. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_cli_triage.py +0 -1
  16. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_drafts.py +2 -1
  17. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_github_media_sync.py +2 -1
  18. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_github_sync.py +1 -1
  19. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_ingest.py +4 -2
  20. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_mcp.py +0 -1
  21. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_mcp_logging.py +0 -1
  22. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_recorder_run.py +3 -3
  23. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_refs_validate_rewrite.py +3 -1
  24. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_regression_output.py +1 -1
  25. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_repo_values.py +0 -1
  26. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_sync_consent.py +0 -3
  27. bugcap-0.5.0/src/bugcap/__init__.py +0 -1
  28. {bugcap-0.5.0 → bugcap-0.5.1}/LICENSE +0 -0
  29. {bugcap-0.5.0 → bugcap-0.5.1}/setup.cfg +0 -0
  30. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap/agent_api.py +0 -0
  31. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap/backends.py +0 -0
  32. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap/capture.py +0 -0
  33. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap/config.py +0 -0
  34. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap/dashboard/__init__.py +0 -0
  35. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap/dashboard/api.py +0 -0
  36. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap/dashboard/media.py +0 -0
  37. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap/dashboard/server.py +0 -0
  38. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap/dashboard/static/app.css +0 -0
  39. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap/dashboard/static/app.js +0 -0
  40. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap/dashboard/static/index.html +0 -0
  41. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap/drafts.py +0 -0
  42. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap/errors.py +0 -0
  43. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap/ghcli.py +0 -0
  44. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap/ingest.py +0 -0
  45. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap/live_session.py +0 -0
  46. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap/logs.py +0 -0
  47. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap/mcp_server.py +0 -0
  48. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap/paths.py +0 -0
  49. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap/recorder.py +0 -0
  50. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap/refs.py +0 -0
  51. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap/repo.py +0 -0
  52. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap/service.py +0 -0
  53. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap/store.py +0 -0
  54. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap/sync.py +0 -0
  55. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap/tomlio.py +0 -0
  56. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap/validation.py +0 -0
  57. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap.egg-info/SOURCES.txt +0 -0
  58. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap.egg-info/dependency_links.txt +0 -0
  59. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap.egg-info/entry_points.txt +0 -0
  60. {bugcap-0.5.0 → bugcap-0.5.1}/src/bugcap.egg-info/top_level.txt +0 -0
  61. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_agent_api.py +0 -0
  62. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_capture.py +0 -0
  63. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_cli_attach.py +1 -1
  64. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_cli_dashboard.py +0 -0
  65. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_cli_record.py +0 -0
  66. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_dashboard_api.py +0 -0
  67. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_dashboard_media.py +0 -0
  68. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_dashboard_mutations.py +0 -0
  69. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_dashboard_security.py +0 -0
  70. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_dashboard_ui_static.py +0 -0
  71. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_ghcli.py +0 -0
  72. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_github_pull.py +0 -0
  73. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_image_refs.py +0 -0
  74. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_ingest_url.py +0 -0
  75. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_live_session.py +1 -1
  76. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_paths.py +0 -0
  77. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_recorder_argv.py +0 -0
  78. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_recorder_devices.py +0 -0
  79. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_recorder_media_real.py +0 -0
  80. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_refs.py +0 -0
  81. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_repo_config.py +0 -0
  82. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_service_media.py +0 -0
  83. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_service_refs.py +0 -0
  84. {bugcap-0.5.0 → bugcap-0.5.1}/tests/test_store_migration.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bugcap
3
- Version: 0.5.0
3
+ Version: 0.5.1
4
4
  Summary: Local-first, agent-readable bug capture: annotated screenshots + notes, stored locally, synced to trackers on your own schedule.
5
5
  Author: Konrad Tagnon Amen ALAHASSA
6
6
  License: MIT
@@ -12,10 +12,11 @@ Provides-Extra: mcp
12
12
  Requires-Dist: mcp<2,>=1.2; extra == "mcp"
13
13
  Provides-Extra: dev
14
14
  Requires-Dist: pytest>=7; extra == "dev"
15
+ Requires-Dist: ruff>=0.6; extra == "dev"
15
16
  Dynamic: license-file
16
17
 
17
18
  <p align="center">
18
- <img src="docs/assets/logo.svg" alt="bugcap" width="96">
19
+ <img src="https://raw.githubusercontent.com/amenalahassa/bugcap/master/docs/assets/logo.svg" alt="bugcap" width="96">
19
20
  </p>
20
21
 
21
22
  <h1 align="center">bugcap</h1>
@@ -28,7 +29,7 @@ Dynamic: license-file
28
29
  <p align="center">
29
30
  <a href="https://github.com/amenalahassa/bugcap/actions/workflows/release.yml"><img alt="tests" src="https://github.com/amenalahassa/bugcap/actions/workflows/release.yml/badge.svg"></a>
30
31
  <img alt="python" src="https://img.shields.io/badge/python-3.10%2B-3776ab?logo=python&logoColor=white">
31
- <a href="LICENSE"><img alt="license" src="https://img.shields.io/badge/license-MIT-green"></a>
32
+ <a href="https://github.com/amenalahassa/bugcap/blob/master/LICENSE"><img alt="license" src="https://img.shields.io/badge/license-MIT-green"></a>
32
33
  <a href="https://amenalahassa.github.io/bugcap/"><img alt="docs" src="https://img.shields.io/badge/docs-website-d9480f"></a>
33
34
  </p>
34
35
 
@@ -37,11 +38,11 @@ Dynamic: license-file
37
38
  <a href="https://amenalahassa.github.io/bugcap/usage.html">Usage guide</a> ·
38
39
  <a href="#quick-start">Quick start</a> ·
39
40
  <a href="#connect-your-agent-mcp">Agents (MCP)</a> ·
40
- <a href="CHANGELOG.md">Changelog</a>
41
+ <a href="https://github.com/amenalahassa/bugcap/blob/master/CHANGELOG.md">Changelog</a>
41
42
  </p>
42
43
 
43
44
  <p align="center">
44
- <img src="docs/assets/demo.gif" alt="bugcap capturing an annotated bug and listing the report" width="760">
45
+ <img src="https://raw.githubusercontent.com/amenalahassa/bugcap/master/docs/assets/demo.gif" alt="bugcap live: screenshot a broken page, file a bug with a note, then read it back with bugcap show" width="760">
45
46
  </p>
46
47
 
47
48
  ---
@@ -120,7 +121,7 @@ the error toast"*. It can read the picture because it's a local file, not a CDN
120
121
  Working. Roadmap items 1–5, 7 and 8 are implemented and tested, along with spec 002 (images,
121
122
  `@` references, recording, live mode and the dashboard). S3/R2 object storage (item 6) and other
122
123
  trackers (item 9) are deferred. The `Destination` seam is in place, so they can be added without
123
- changing the CLI. See [ROADMAP.md](ROADMAP.md).
124
+ changing the CLI. See [ROADMAP.md](https://github.com/amenalahassa/bugcap/blob/master/ROADMAP.md).
124
125
 
125
126
  ## Installation
126
127
 
@@ -150,9 +151,13 @@ Notes on the more involved behaviour:
150
151
  - **Repo values** (`init`, `sync`, `config repo set`) are checked for format and, with `gh`, for existence. Changing the repo identity offers to move existing reports.
151
152
  - **Media sync** over `[sync] max_upload_mb` (default 25) is skipped with a warning.
152
153
 
154
+ ## Contributing
155
+
156
+ Contributions are welcome. Read [CONTRIBUTING.md](https://github.com/amenalahassa/bugcap/blob/master/CONTRIBUTING.md) for the workflow and project rules, and the [Code of Conduct](https://github.com/amenalahassa/bugcap/blob/master/CODE_OF_CONDUCT.md). Report security issues privately, see [SECURITY.md](https://github.com/amenalahassa/bugcap/blob/master/SECURITY.md).
157
+
153
158
  ## Development
154
159
 
155
- See [DEVELOPMENT.md](DEVELOPMENT.md). Run the tests with:
160
+ See [DEVELOPMENT.md](https://github.com/amenalahassa/bugcap/blob/master/DEVELOPMENT.md). Run the tests with:
156
161
 
157
162
  ```bash
158
163
  uv run --extra dev --extra mcp pytest -q
@@ -203,7 +208,7 @@ succeeds, so a re-run skips what is already recorded.
203
208
 
204
209
  ## Roadmap
205
210
 
206
- See [ROADMAP.md](ROADMAP.md).
211
+ See [ROADMAP.md](https://github.com/amenalahassa/bugcap/blob/master/ROADMAP.md).
207
212
 
208
213
  ## Design notes / deliberate non-goals
209
214
 
@@ -222,4 +227,4 @@ See [ROADMAP.md](ROADMAP.md).
222
227
 
223
228
  ## License
224
229
 
225
- MIT — see [LICENSE](LICENSE).
230
+ MIT — see [LICENSE](https://github.com/amenalahassa/bugcap/blob/master/LICENSE).
@@ -1,5 +1,5 @@
1
1
  <p align="center">
2
- <img src="docs/assets/logo.svg" alt="bugcap" width="96">
2
+ <img src="https://raw.githubusercontent.com/amenalahassa/bugcap/master/docs/assets/logo.svg" alt="bugcap" width="96">
3
3
  </p>
4
4
 
5
5
  <h1 align="center">bugcap</h1>
@@ -12,7 +12,7 @@
12
12
  <p align="center">
13
13
  <a href="https://github.com/amenalahassa/bugcap/actions/workflows/release.yml"><img alt="tests" src="https://github.com/amenalahassa/bugcap/actions/workflows/release.yml/badge.svg"></a>
14
14
  <img alt="python" src="https://img.shields.io/badge/python-3.10%2B-3776ab?logo=python&logoColor=white">
15
- <a href="LICENSE"><img alt="license" src="https://img.shields.io/badge/license-MIT-green"></a>
15
+ <a href="https://github.com/amenalahassa/bugcap/blob/master/LICENSE"><img alt="license" src="https://img.shields.io/badge/license-MIT-green"></a>
16
16
  <a href="https://amenalahassa.github.io/bugcap/"><img alt="docs" src="https://img.shields.io/badge/docs-website-d9480f"></a>
17
17
  </p>
18
18
 
@@ -21,11 +21,11 @@
21
21
  <a href="https://amenalahassa.github.io/bugcap/usage.html">Usage guide</a> ·
22
22
  <a href="#quick-start">Quick start</a> ·
23
23
  <a href="#connect-your-agent-mcp">Agents (MCP)</a> ·
24
- <a href="CHANGELOG.md">Changelog</a>
24
+ <a href="https://github.com/amenalahassa/bugcap/blob/master/CHANGELOG.md">Changelog</a>
25
25
  </p>
26
26
 
27
27
  <p align="center">
28
- <img src="docs/assets/demo.gif" alt="bugcap capturing an annotated bug and listing the report" width="760">
28
+ <img src="https://raw.githubusercontent.com/amenalahassa/bugcap/master/docs/assets/demo.gif" alt="bugcap live: screenshot a broken page, file a bug with a note, then read it back with bugcap show" width="760">
29
29
  </p>
30
30
 
31
31
  ---
@@ -104,7 +104,7 @@ the error toast"*. It can read the picture because it's a local file, not a CDN
104
104
  Working. Roadmap items 1–5, 7 and 8 are implemented and tested, along with spec 002 (images,
105
105
  `@` references, recording, live mode and the dashboard). S3/R2 object storage (item 6) and other
106
106
  trackers (item 9) are deferred. The `Destination` seam is in place, so they can be added without
107
- changing the CLI. See [ROADMAP.md](ROADMAP.md).
107
+ changing the CLI. See [ROADMAP.md](https://github.com/amenalahassa/bugcap/blob/master/ROADMAP.md).
108
108
 
109
109
  ## Installation
110
110
 
@@ -134,9 +134,13 @@ Notes on the more involved behaviour:
134
134
  - **Repo values** (`init`, `sync`, `config repo set`) are checked for format and, with `gh`, for existence. Changing the repo identity offers to move existing reports.
135
135
  - **Media sync** over `[sync] max_upload_mb` (default 25) is skipped with a warning.
136
136
 
137
+ ## Contributing
138
+
139
+ Contributions are welcome. Read [CONTRIBUTING.md](https://github.com/amenalahassa/bugcap/blob/master/CONTRIBUTING.md) for the workflow and project rules, and the [Code of Conduct](https://github.com/amenalahassa/bugcap/blob/master/CODE_OF_CONDUCT.md). Report security issues privately, see [SECURITY.md](https://github.com/amenalahassa/bugcap/blob/master/SECURITY.md).
140
+
137
141
  ## Development
138
142
 
139
- See [DEVELOPMENT.md](DEVELOPMENT.md). Run the tests with:
143
+ See [DEVELOPMENT.md](https://github.com/amenalahassa/bugcap/blob/master/DEVELOPMENT.md). Run the tests with:
140
144
 
141
145
  ```bash
142
146
  uv run --extra dev --extra mcp pytest -q
@@ -187,7 +191,7 @@ succeeds, so a re-run skips what is already recorded.
187
191
 
188
192
  ## Roadmap
189
193
 
190
- See [ROADMAP.md](ROADMAP.md).
194
+ See [ROADMAP.md](https://github.com/amenalahassa/bugcap/blob/master/ROADMAP.md).
191
195
 
192
196
  ## Design notes / deliberate non-goals
193
197
 
@@ -206,4 +210,4 @@ See [ROADMAP.md](ROADMAP.md).
206
210
 
207
211
  ## License
208
212
 
209
- MIT — see [LICENSE](LICENSE).
213
+ MIT — see [LICENSE](https://github.com/amenalahassa/bugcap/blob/master/LICENSE).
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "bugcap"
7
- version = "0.5.0"
7
+ version = "0.5.1"
8
8
  description = "Local-first, agent-readable bug capture: annotated screenshots + notes, stored locally, synced to trackers on your own schedule."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -14,7 +14,7 @@ dependencies = ["tomli>=2; python_version < '3.11'"]
14
14
 
15
15
  [project.optional-dependencies]
16
16
  mcp = ["mcp>=1.2,<2"]
17
- dev = ["pytest>=7"]
17
+ dev = ["pytest>=7", "ruff>=0.6"]
18
18
 
19
19
  [project.scripts]
20
20
  bugcap = "bugcap.cli:main"
@@ -27,3 +27,13 @@ bugcap = ["dashboard/static/*"]
27
27
 
28
28
  [tool.pytest.ini_options]
29
29
  testpaths = ["tests"]
30
+
31
+ [tool.ruff]
32
+ line-length = 120
33
+ target-version = "py310"
34
+
35
+ [tool.ruff.lint]
36
+ select = ["E4", "E7", "E9", "F", "I"]
37
+
38
+ [tool.ruff.lint.per-file-ignores]
39
+ "tests/*" = ["E702", "E731"]
@@ -0,0 +1 @@
1
+ __version__ = "0.5.1"
@@ -7,13 +7,12 @@ import threading
7
7
  from pathlib import Path
8
8
  from typing import Optional
9
9
 
10
- from . import backends, capture, config, ghcli, recorder, refs, repo, service, sync, validation
10
+ from . import __version__, backends, capture, config, ghcli, recorder, refs, repo, service, sync, validation
11
11
  from .capture import CaptureError
12
12
  from .errors import ServiceError
13
13
  from .ghcli import GhError
14
14
  from .store import STATUSES, Store
15
15
 
16
-
17
16
  # --- shared helpers (T014) ----------------------------------------------------
18
17
 
19
18
  def current_repo():
@@ -161,7 +160,7 @@ def print_report(report) -> None:
161
160
  print(f" repo: {report.repo}")
162
161
  print(f" tags: {', '.join(report.tags) or '(none)'}")
163
162
  print(f" notes: {refs.display_notes(report.notes, report.media) or '(none)'}")
164
- print(f" images:")
163
+ print(" images:")
165
164
  for path in report.image_paths:
166
165
  print(f" - {path}")
167
166
  detailed = [m for m in report.media if not (m.kind == "image" and m.source == "legacy")]
@@ -171,7 +170,7 @@ def print_report(report) -> None:
171
170
  where = m.path or f"({len(m.frames)} frames)"
172
171
  origin = f" (source: {m.source})" if m.source else ""
173
172
  print(f" {refs.media_token(m)} {m.kind:8s} {m.label or '-':12s} {where} {human_size(m.size_bytes)}{origin}")
174
- print(f" synced_refs:")
173
+ print(" synced_refs:")
175
174
  if report.synced_refs:
176
175
  for tracker, ref in report.synced_refs.items():
177
176
  print(f" - {tracker}: {ref}")
@@ -850,6 +849,7 @@ def build_parser() -> argparse.ArgumentParser:
850
849
  prog="bugcap",
851
850
  description="Local-first, agent-readable bug capture: annotated screenshots + notes.",
852
851
  )
852
+ parser.add_argument("--version", action="version", version=f"bugcap {__version__}")
853
853
  sub = parser.add_subparsers(dest="command", required=True)
854
854
 
855
855
  p = sub.add_parser("setup", help="Detect a capture tool, or recommend/install one.")
@@ -85,7 +85,7 @@ class _App:
85
85
 
86
86
  def style(self) -> None:
87
87
  """One consistent look for every window: a flat light theme with an accent button."""
88
- tk, ttk = self.tk, self.ttk
88
+ ttk = self.ttk
89
89
  import tkinter.font as tkfont
90
90
 
91
91
  base = tkfont.nametofont("TkDefaultFont")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bugcap
3
- Version: 0.5.0
3
+ Version: 0.5.1
4
4
  Summary: Local-first, agent-readable bug capture: annotated screenshots + notes, stored locally, synced to trackers on your own schedule.
5
5
  Author: Konrad Tagnon Amen ALAHASSA
6
6
  License: MIT
@@ -12,10 +12,11 @@ Provides-Extra: mcp
12
12
  Requires-Dist: mcp<2,>=1.2; extra == "mcp"
13
13
  Provides-Extra: dev
14
14
  Requires-Dist: pytest>=7; extra == "dev"
15
+ Requires-Dist: ruff>=0.6; extra == "dev"
15
16
  Dynamic: license-file
16
17
 
17
18
  <p align="center">
18
- <img src="docs/assets/logo.svg" alt="bugcap" width="96">
19
+ <img src="https://raw.githubusercontent.com/amenalahassa/bugcap/master/docs/assets/logo.svg" alt="bugcap" width="96">
19
20
  </p>
20
21
 
21
22
  <h1 align="center">bugcap</h1>
@@ -28,7 +29,7 @@ Dynamic: license-file
28
29
  <p align="center">
29
30
  <a href="https://github.com/amenalahassa/bugcap/actions/workflows/release.yml"><img alt="tests" src="https://github.com/amenalahassa/bugcap/actions/workflows/release.yml/badge.svg"></a>
30
31
  <img alt="python" src="https://img.shields.io/badge/python-3.10%2B-3776ab?logo=python&logoColor=white">
31
- <a href="LICENSE"><img alt="license" src="https://img.shields.io/badge/license-MIT-green"></a>
32
+ <a href="https://github.com/amenalahassa/bugcap/blob/master/LICENSE"><img alt="license" src="https://img.shields.io/badge/license-MIT-green"></a>
32
33
  <a href="https://amenalahassa.github.io/bugcap/"><img alt="docs" src="https://img.shields.io/badge/docs-website-d9480f"></a>
33
34
  </p>
34
35
 
@@ -37,11 +38,11 @@ Dynamic: license-file
37
38
  <a href="https://amenalahassa.github.io/bugcap/usage.html">Usage guide</a> ·
38
39
  <a href="#quick-start">Quick start</a> ·
39
40
  <a href="#connect-your-agent-mcp">Agents (MCP)</a> ·
40
- <a href="CHANGELOG.md">Changelog</a>
41
+ <a href="https://github.com/amenalahassa/bugcap/blob/master/CHANGELOG.md">Changelog</a>
41
42
  </p>
42
43
 
43
44
  <p align="center">
44
- <img src="docs/assets/demo.gif" alt="bugcap capturing an annotated bug and listing the report" width="760">
45
+ <img src="https://raw.githubusercontent.com/amenalahassa/bugcap/master/docs/assets/demo.gif" alt="bugcap live: screenshot a broken page, file a bug with a note, then read it back with bugcap show" width="760">
45
46
  </p>
46
47
 
47
48
  ---
@@ -120,7 +121,7 @@ the error toast"*. It can read the picture because it's a local file, not a CDN
120
121
  Working. Roadmap items 1–5, 7 and 8 are implemented and tested, along with spec 002 (images,
121
122
  `@` references, recording, live mode and the dashboard). S3/R2 object storage (item 6) and other
122
123
  trackers (item 9) are deferred. The `Destination` seam is in place, so they can be added without
123
- changing the CLI. See [ROADMAP.md](ROADMAP.md).
124
+ changing the CLI. See [ROADMAP.md](https://github.com/amenalahassa/bugcap/blob/master/ROADMAP.md).
124
125
 
125
126
  ## Installation
126
127
 
@@ -150,9 +151,13 @@ Notes on the more involved behaviour:
150
151
  - **Repo values** (`init`, `sync`, `config repo set`) are checked for format and, with `gh`, for existence. Changing the repo identity offers to move existing reports.
151
152
  - **Media sync** over `[sync] max_upload_mb` (default 25) is skipped with a warning.
152
153
 
154
+ ## Contributing
155
+
156
+ Contributions are welcome. Read [CONTRIBUTING.md](https://github.com/amenalahassa/bugcap/blob/master/CONTRIBUTING.md) for the workflow and project rules, and the [Code of Conduct](https://github.com/amenalahassa/bugcap/blob/master/CODE_OF_CONDUCT.md). Report security issues privately, see [SECURITY.md](https://github.com/amenalahassa/bugcap/blob/master/SECURITY.md).
157
+
153
158
  ## Development
154
159
 
155
- See [DEVELOPMENT.md](DEVELOPMENT.md). Run the tests with:
160
+ See [DEVELOPMENT.md](https://github.com/amenalahassa/bugcap/blob/master/DEVELOPMENT.md). Run the tests with:
156
161
 
157
162
  ```bash
158
163
  uv run --extra dev --extra mcp pytest -q
@@ -203,7 +208,7 @@ succeeds, so a re-run skips what is already recorded.
203
208
 
204
209
  ## Roadmap
205
210
 
206
- See [ROADMAP.md](ROADMAP.md).
211
+ See [ROADMAP.md](https://github.com/amenalahassa/bugcap/blob/master/ROADMAP.md).
207
212
 
208
213
  ## Design notes / deliberate non-goals
209
214
 
@@ -222,4 +227,4 @@ See [ROADMAP.md](ROADMAP.md).
222
227
 
223
228
  ## License
224
229
 
225
- MIT — see [LICENSE](LICENSE).
230
+ MIT — see [LICENSE](https://github.com/amenalahassa/bugcap/blob/master/LICENSE).
@@ -4,6 +4,7 @@ tomli>=2
4
4
 
5
5
  [dev]
6
6
  pytest>=7
7
+ ruff>=0.6
7
8
 
8
9
  [mcp]
9
10
  mcp<2,>=1.2
@@ -1,5 +1,4 @@
1
1
  """T011: backend detection, recommendation, install-command and guidance per simulated OS."""
2
- import os
3
2
 
4
3
  import pytest
5
4
 
@@ -1,7 +1,7 @@
1
1
  """T016: init writes config; capture scopes inside a repo; list filters; --all; legacy rows."""
2
- import pytest
3
2
 
4
3
  from fixtures.make_images import png_bytes
4
+
5
5
  from bugcap import cli, repo
6
6
  from bugcap.store import Store
7
7
 
@@ -20,8 +20,12 @@ def test_missing_tkinter_exits_3_with_install_hint(monkeypatch, capsys):
20
20
  assert "python3-tk" in capsys.readouterr().err
21
21
 
22
22
 
23
+ @pytest.mark.skipif(
24
+ sys.platform in ("win32", "darwin"),
25
+ reason="DISPLAY only means something on X11; elsewhere Tk opens a real window and blocks",
26
+ )
23
27
  def test_unreachable_display_exits_3(monkeypatch, capsys):
24
- tk = pytest.importorskip("tkinter")
28
+ pytest.importorskip("tkinter")
25
29
  monkeypatch.setenv("DISPLAY", ":99999")
26
30
  assert cli.main(["live"]) == 3
27
31
  assert "cannot open a window" in capsys.readouterr().err
@@ -1,8 +1,8 @@
1
- import pytest
1
+
2
+ from fixtures.make_v1_db import build
2
3
 
3
4
  from bugcap import capture, cli
4
5
  from bugcap.store import Store
5
- from fixtures.make_v1_db import build
6
6
 
7
7
 
8
8
  def _boom(*a, **k):
@@ -1,7 +1,7 @@
1
1
  """`capture --no-image` saves a text-only report; `delete` removes a report and its files."""
2
- import pytest
3
2
 
4
3
  from fixtures.make_images import png_bytes
4
+
5
5
  from bugcap import cli, service
6
6
  from bugcap.paths import resolve_data_path
7
7
  from bugcap.store import Store
@@ -79,3 +79,12 @@ def test_no_package_manager_prints_guidance(monkeypatch, record_run, capsys):
79
79
  assert cli.main(["setup"]) == 1
80
80
  assert "manually" in capsys.readouterr().err.lower()
81
81
  assert record_run == []
82
+
83
+
84
+ def test_version_flag(capsys):
85
+ from bugcap import __version__
86
+
87
+ with pytest.raises(SystemExit) as exc:
88
+ cli.main(["--version"])
89
+ assert exc.value.code == 0
90
+ assert capsys.readouterr().out.strip() == f"bugcap {__version__}"
@@ -1,5 +1,4 @@
1
1
  """T022: `bugcap edit` and `bugcap tag`."""
2
- import pytest
3
2
 
4
3
  from bugcap import cli
5
4
  from bugcap.store import Store
@@ -1,8 +1,9 @@
1
1
  import json
2
2
 
3
- from bugcap import drafts
4
3
  from fixtures.make_images import png_bytes
5
4
 
5
+ from bugcap import drafts
6
+
6
7
 
7
8
  def _png(tmp_path, name="s.png"):
8
9
  p = tmp_path / name
@@ -2,10 +2,11 @@
2
2
  import base64
3
3
  import json
4
4
 
5
+ from fixtures.make_images import png_bytes
6
+
5
7
  from bugcap import service, sync
6
8
  from bugcap.store import Store
7
9
  from bugcap.sync import GitHubDestination, ImagesTarget, SyncOptions
8
- from fixtures.make_images import png_bytes
9
10
 
10
11
 
11
12
  def _setup(fake_gh):
@@ -4,7 +4,7 @@ import json
4
4
 
5
5
  import pytest
6
6
 
7
- from bugcap import config, sync
7
+ from bugcap import sync
8
8
  from bugcap.store import Store
9
9
  from bugcap.sync import GitHubDestination, ImagesTarget, SyncOptions
10
10
 
@@ -1,8 +1,10 @@
1
+ from pathlib import Path
2
+
1
3
  import pytest
4
+ from fixtures.make_images import gif_bytes, jpeg_bytes, png_bytes, webp_bytes
2
5
 
3
6
  from bugcap import ingest
4
7
  from bugcap.errors import ServiceError
5
- from fixtures.make_images import gif_bytes, jpeg_bytes, png_bytes, webp_bytes
6
8
 
7
9
 
8
10
  def test_classify_sources(tmp_path):
@@ -54,7 +56,7 @@ def test_import_copies_into_store(bugcap_home, sample_images):
54
56
 
55
57
  def test_glob_sorted_and_no_match(sample_images):
56
58
  matches = ingest.resolve_glob(str(sample_images / "sample.*"))
57
- assert [m.rsplit("/", 1)[1] for m in matches] == ["sample.gif", "sample.jpg", "sample.png", "sample.webp"]
59
+ assert [Path(m).name for m in matches] == ["sample.gif", "sample.jpg", "sample.png", "sample.webp"]
58
60
  items = ingest.expand_sources([str(sample_images / "nope-*.png")])
59
61
  assert items[0].error.code == "not_found" and "nope-*.png" in items[0].error.message
60
62
 
@@ -17,7 +17,6 @@ EXPECTED_TOOLS = {
17
17
 
18
18
 
19
19
  def _seed_report(home) -> int:
20
- env = dict(os.environ, BUGCAP_HOME=str(home))
21
20
  os.environ["BUGCAP_HOME"] = str(home)
22
21
  from bugcap.store import Store
23
22
 
@@ -1,6 +1,5 @@
1
1
  """BUGS.md: `bugcap mcp-serve` logs startup, client initialize, tool calls and errors, never to stdout."""
2
2
  import asyncio
3
- import io
4
3
  import logging
5
4
  import os
6
5
  import subprocess
@@ -1,5 +1,6 @@
1
1
  import signal
2
2
  import subprocess
3
+ from pathlib import Path
3
4
 
4
5
  import pytest
5
6
 
@@ -156,11 +157,10 @@ def test_animated_runs_postprocess_and_removes_raw(env, tmp_path):
156
157
 
157
158
 
158
159
  def test_frames_result(env, tmp_path):
159
- frames_dir_files = []
160
160
 
161
161
  def runner(argv, **kw):
162
162
  pattern = argv[-1]
163
- folder = tmp_path / pattern.split("/")[-2]
163
+ folder = Path(pattern).parent
164
164
  for n in (1, 2, 3):
165
165
  (folder / f"frame-00{n}.png").write_bytes(b"x")
166
166
  return subprocess.CompletedProcess(argv, 0, "", "")
@@ -168,7 +168,7 @@ def test_frames_result(env, tmp_path):
168
168
  result = recorder.run_recording("ffmpeg", "frames", 5, 30, 25, tmp_path, lambda: True,
169
169
  **env.kwargs(runner=runner))
170
170
  assert result.kind == "frames" and len(result.frames) == 3 and result.path is None
171
- assert [p.rsplit("/", 1)[1] for p, _ in result.frames] == ["frame-001.png", "frame-002.png", "frame-003.png"]
171
+ assert [Path(p).name for p, _ in result.frames] == ["frame-001.png", "frame-002.png", "frame-003.png"]
172
172
 
173
173
 
174
174
  def test_macos_probes_screen_device(env, tmp_path):
@@ -2,7 +2,9 @@ import pytest
2
2
 
3
3
  from bugcap.errors import ServiceError
4
4
  from bugcap.refs import (
5
- display_notes, rewrite_references, validate_references,
5
+ display_notes,
6
+ rewrite_references,
7
+ validate_references,
6
8
  )
7
9
  from bugcap.store import Media
8
10
 
@@ -2,9 +2,9 @@
2
2
 
3
3
  The expected strings below are the exact pre-feature formats; the test fails if any
4
4
  scoping/repo change leaks into output when there is no .bugcap.toml in scope."""
5
- import pytest
6
5
 
7
6
  from fixtures.make_images import png_bytes
7
+
8
8
  from bugcap import cli
9
9
  from bugcap.store import Store
10
10
 
@@ -4,7 +4,6 @@ import pytest
4
4
  from bugcap import cli, ghcli, repo, validation
5
5
  from bugcap.store import Store
6
6
 
7
-
8
7
  # --- validation -------------------------------------------------------------------
9
8
 
10
9
  @pytest.mark.parametrize("slug", ["owner/repo", "my-org/my.repo_1", "a/b"])
@@ -1,9 +1,6 @@
1
1
  """T031: image-commit consent rules (FR-018a) and images-target resolution (FR-018b/R2)."""
2
- import base64
3
2
  import json
4
3
 
5
- import pytest
6
-
7
4
  from bugcap import config, repo, sync
8
5
  from bugcap.store import Store
9
6
  from bugcap.sync import GitHubDestination, ImagesTarget, SyncOptions, resolve_images_target
@@ -1 +0,0 @@
1
- __version__ = "0.5.0"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -1,7 +1,7 @@
1
1
  """T026: `bugcap attach`."""
2
2
  import pytest
3
-
4
3
  from fixtures.make_images import png_bytes
4
+
5
5
  from bugcap import backends, capture, cli
6
6
  from bugcap.store import Store
7
7
 
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -1,13 +1,13 @@
1
1
  from pathlib import Path
2
2
 
3
3
  import pytest
4
+ from fixtures.make_images import png_bytes
4
5
 
5
6
  from bugcap import drafts, live_session, recorder
6
7
  from bugcap.errors import ServiceError
7
8
  from bugcap.live_session import LiveSession, LiveState
8
9
  from bugcap.paths import images_dir, media_dir
9
10
  from bugcap.store import Store
10
- from fixtures.make_images import png_bytes
11
11
 
12
12
 
13
13
  class Cfg:
File without changes
File without changes
File without changes