uitrace 0.1.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.
Files changed (78) hide show
  1. uitrace-0.1.0/.github/workflows/ci.yml +43 -0
  2. uitrace-0.1.0/.github/workflows/publish.yml +105 -0
  3. uitrace-0.1.0/.gitignore +10 -0
  4. uitrace-0.1.0/.pre-commit-config.yaml +7 -0
  5. uitrace-0.1.0/.python-version +1 -0
  6. uitrace-0.1.0/.sisyphus/boulder.json +10 -0
  7. uitrace-0.1.0/.sisyphus/evidence/task-3-macos-window_from_point.txt +2 -0
  8. uitrace-0.1.0/.sisyphus/evidence/task-6-record-follow-any-regression.txt +2 -0
  9. uitrace-0.1.0/.sisyphus/evidence/task-6-record-follow-any.txt +2 -0
  10. uitrace-0.1.0/.sisyphus/evidence/task-8-player-wait_until.txt +2 -0
  11. uitrace-0.1.0/.sisyphus/notepads/2026-02-28-uitrace-mvp/decisions.md +3 -0
  12. uitrace-0.1.0/.sisyphus/notepads/2026-02-28-uitrace-mvp/issues.md +7 -0
  13. uitrace-0.1.0/.sisyphus/notepads/2026-02-28-uitrace-mvp/learnings.md +7 -0
  14. uitrace-0.1.0/.sisyphus/notepads/2026-02-28-uitrace-mvp/problems.md +1 -0
  15. uitrace-0.1.0/.sisyphus/notepads/publish-to-pypi-oidc/decisions.md +2 -0
  16. uitrace-0.1.0/.sisyphus/notepads/publish-to-pypi-oidc/issues.md +5 -0
  17. uitrace-0.1.0/.sisyphus/notepads/publish-to-pypi-oidc/learnings.md +17 -0
  18. uitrace-0.1.0/.sisyphus/notepads/publish-to-pypi-oidc/problems.md +1 -0
  19. uitrace-0.1.0/.sisyphus/plans/2026-02-28-uitrace-multi-window-capture.md +616 -0
  20. uitrace-0.1.0/.sisyphus/plans/2026-02-28-uitrace-mvp.md +976 -0
  21. uitrace-0.1.0/.sisyphus/plans/2026-03-01-uitrace-window-relative-replay.md +311 -0
  22. uitrace-0.1.0/.sisyphus/plans/publish-to-pypi-oidc.md +469 -0
  23. uitrace-0.1.0/CHANGELOG.md +60 -0
  24. uitrace-0.1.0/PKG-INFO +153 -0
  25. uitrace-0.1.0/README.md +142 -0
  26. uitrace-0.1.0/draft.md +553 -0
  27. uitrace-0.1.0/main.py +6 -0
  28. uitrace-0.1.0/pyproject.toml +43 -0
  29. uitrace-0.1.0/src/uitrace/__init__.py +1 -0
  30. uitrace-0.1.0/src/uitrace/cli.py +240 -0
  31. uitrace-0.1.0/src/uitrace/core/__init__.py +37 -0
  32. uitrace-0.1.0/src/uitrace/core/jsonl.py +94 -0
  33. uitrace-0.1.0/src/uitrace/core/models.py +204 -0
  34. uitrace-0.1.0/src/uitrace/errors.py +39 -0
  35. uitrace-0.1.0/src/uitrace/platform/__init__.py +17 -0
  36. uitrace-0.1.0/src/uitrace/platform/base.py +83 -0
  37. uitrace-0.1.0/src/uitrace/platform/macos.py +345 -0
  38. uitrace-0.1.0/src/uitrace/platform/unsupported.py +46 -0
  39. uitrace-0.1.0/src/uitrace/player/__init__.py +5 -0
  40. uitrace-0.1.0/src/uitrace/player/executor.py +102 -0
  41. uitrace-0.1.0/src/uitrace/player/observer.py +123 -0
  42. uitrace-0.1.0/src/uitrace/player/player.py +512 -0
  43. uitrace-0.1.0/src/uitrace/recorder/__init__.py +1 -0
  44. uitrace-0.1.0/src/uitrace/recorder/capture_macos.py +203 -0
  45. uitrace-0.1.0/src/uitrace/recorder/merge.py +164 -0
  46. uitrace-0.1.0/src/uitrace/recorder/normalize.py +63 -0
  47. uitrace-0.1.0/src/uitrace/recorder/recorder.py +618 -0
  48. uitrace-0.1.0/src/uitrace/tools/__init__.py +1 -0
  49. uitrace-0.1.0/src/uitrace/tools/doctor.py +166 -0
  50. uitrace-0.1.0/src/uitrace/tools/show.py +44 -0
  51. uitrace-0.1.0/src/uitrace/tools/validate.py +21 -0
  52. uitrace-0.1.0/tests/fixtures/trace_v1_invalid.jsonl +2 -0
  53. uitrace-0.1.0/tests/fixtures/trace_v1_multi_window.jsonl +13 -0
  54. uitrace-0.1.0/tests/fixtures/trace_v1_valid.jsonl +7 -0
  55. uitrace-0.1.0/tests/test_assertions_pure.py +79 -0
  56. uitrace-0.1.0/tests/test_cli_help.py +36 -0
  57. uitrace-0.1.0/tests/test_doctor_json.py +38 -0
  58. uitrace-0.1.0/tests/test_errors.py +17 -0
  59. uitrace-0.1.0/tests/test_executor_math.py +30 -0
  60. uitrace-0.1.0/tests/test_jsonl_io.py +15 -0
  61. uitrace-0.1.0/tests/test_list_json_schema.py +23 -0
  62. uitrace-0.1.0/tests/test_macos_centering_pure.py +109 -0
  63. uitrace-0.1.0/tests/test_models_roundtrip.py +103 -0
  64. uitrace-0.1.0/tests/test_platform_unsupported.py +18 -0
  65. uitrace-0.1.0/tests/test_play_command.py +111 -0
  66. uitrace-0.1.0/tests/test_play_multi_window_dry_run.py +51 -0
  67. uitrace-0.1.0/tests/test_player_assert_real.py +219 -0
  68. uitrace-0.1.0/tests/test_player_click_refresh_real.py +199 -0
  69. uitrace-0.1.0/tests/test_player_dry_run.py +184 -0
  70. uitrace-0.1.0/tests/test_player_wait_until_real.py +471 -0
  71. uitrace-0.1.0/tests/test_record_multi_window_pure.py +447 -0
  72. uitrace-0.1.0/tests/test_record_permissions_pure.py +58 -0
  73. uitrace-0.1.0/tests/test_record_pipeline_pure.py +33 -0
  74. uitrace-0.1.0/tests/test_recorder_merge.py +60 -0
  75. uitrace-0.1.0/tests/test_show_command.py +42 -0
  76. uitrace-0.1.0/tests/test_validate_command.py +19 -0
  77. uitrace-0.1.0/tests/test_window_hit_test_pure.py +143 -0
  78. uitrace-0.1.0/uv.lock +3116 -0
@@ -0,0 +1,43 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ test:
14
+ runs-on: macos-latest
15
+
16
+ steps:
17
+ - name: Checkout
18
+ uses: actions/checkout@v4
19
+
20
+ - name: Setup Python
21
+ uses: actions/setup-python@v5
22
+ with:
23
+ python-version-file: .python-version
24
+
25
+ - name: Setup uv
26
+ uses: astral-sh/setup-uv@v7
27
+ with:
28
+ enable-cache: true
29
+
30
+ - name: Sync
31
+ run: uv sync --group dev --frozen
32
+
33
+ - name: Ruff
34
+ run: uv run ruff check . --output-format github
35
+
36
+ - name: Mypy
37
+ run: uv run mypy src
38
+
39
+ - name: Pytest
40
+ run: uv run pytest -q
41
+
42
+ - name: Build (sdist+wheel)
43
+ run: uv build --no-sources
@@ -0,0 +1,105 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+ workflow_dispatch:
8
+ inputs:
9
+ dry_run:
10
+ description: "Dry run (skip publish to PyPI)"
11
+ required: false
12
+ type: boolean
13
+ default: true
14
+
15
+ concurrency:
16
+ group: publish-${{ github.ref }}
17
+ cancel-in-progress: false
18
+
19
+ jobs:
20
+ build:
21
+ runs-on: macos-latest
22
+ permissions:
23
+ contents: read
24
+
25
+ steps:
26
+ - name: Checkout
27
+ uses: actions/checkout@v4
28
+
29
+ - name: Setup Python
30
+ uses: actions/setup-python@v5
31
+ with:
32
+ python-version-file: .python-version
33
+
34
+ - name: Setup uv
35
+ uses: astral-sh/setup-uv@v7
36
+ with:
37
+ enable-cache: true
38
+
39
+ - name: Verify tag matches pyproject.toml version
40
+ if: github.event_name == 'push'
41
+ shell: bash
42
+ run: |
43
+ set -euo pipefail
44
+ TAG_VERSION="${GITHUB_REF_NAME#v}"
45
+ PYPROJECT_VERSION="$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")"
46
+ if [[ "$TAG_VERSION" != "$PYPROJECT_VERSION" ]]; then
47
+ echo "::error::Tag version v${TAG_VERSION} does not match pyproject.toml version ${PYPROJECT_VERSION}"
48
+ exit 1
49
+ fi
50
+
51
+ - name: Sync
52
+ run: uv sync --group dev --frozen
53
+
54
+ - name: Ruff
55
+ run: uv run ruff check . --output-format github
56
+
57
+ - name: Mypy
58
+ run: uv run mypy src
59
+
60
+ - name: Pytest
61
+ run: uv run pytest -q
62
+
63
+ - name: Build (sdist+wheel)
64
+ run: uv build --no-sources
65
+
66
+ - name: Smoke test wheel
67
+ shell: bash
68
+ run: |
69
+ set -euo pipefail
70
+ shopt -s nullglob
71
+ wheels=(dist/*.whl)
72
+ if [ ${#wheels[@]} -ne 1 ]; then
73
+ echo "Expected exactly 1 wheel in dist/, found: ${wheels[*]}"
74
+ exit 1
75
+ fi
76
+ uvx --from "${wheels[0]}" uitrace --help
77
+ uvx --from "${wheels[0]}" uitrace play --dry-run tests/fixtures/trace_v1_valid.jsonl
78
+
79
+ - name: Upload dists
80
+ uses: actions/upload-artifact@v4
81
+ with:
82
+ name: release-dists
83
+ path: dist/
84
+ if-no-files-found: error
85
+
86
+ publish:
87
+ if: ${{ !(github.event_name == 'workflow_dispatch' && inputs.dry_run) }}
88
+ runs-on: macos-latest
89
+ needs: build
90
+ permissions:
91
+ id-token: write
92
+ contents: read
93
+
94
+ steps:
95
+ - name: Download dists
96
+ uses: actions/download-artifact@v4
97
+ with:
98
+ name: release-dists
99
+ path: dist/
100
+
101
+ - name: Setup uv
102
+ uses: astral-sh/setup-uv@v7
103
+
104
+ - name: Publish
105
+ run: uv publish --trusted-publishing always dist/*
@@ -0,0 +1,10 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # Virtual environments
10
+ .venv
@@ -0,0 +1,7 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.15.4
4
+ hooks:
5
+ - id: ruff
6
+ args: [--fix, --exit-non-zero-on-fix]
7
+ - id: ruff-format
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,10 @@
1
+ {
2
+ "active_plan": "/Users/mark/MyProjects/uitrace/.sisyphus/plans/publish-to-pypi-oidc.md",
3
+ "started_at": "2026-03-01T13:23:09.000Z",
4
+ "session_ids": [
5
+ "ses_356970422ffeNuJcGYii4CCpI7",
6
+ "ses_3566bf565ffeIGk5T8T0tjztke"
7
+ ],
8
+ "plan_name": "publish-to-pypi-oidc",
9
+ "worktree_path": "/Users/mark/MyProjects/uitrace"
10
+ }
@@ -0,0 +1,2 @@
1
+ ....... [100%]
2
+ 7 passed in 0.04s
@@ -0,0 +1,2 @@
1
+ ..... [100%]
2
+ 5 passed in 0.04s
@@ -0,0 +1,2 @@
1
+ .............. [100%]
2
+ 14 passed in 0.05s
@@ -0,0 +1,2 @@
1
+ ..... [100%]
2
+ 5 passed in 0.11s
@@ -0,0 +1,3 @@
1
+ - 2026-02-28: Kept exact exit-code mapping from plan, including `UNSUPPORTED_PLATFORM = 11`.
2
+ - 2026-02-28: Used dataclass for `UitError` with typed optional `hint` and `details`.
3
+ - 2026-02-28: Preserved one-line `format_error` contract and wired CLI `main()` to handle `UitError` and `KeyboardInterrupt`.
@@ -0,0 +1,7 @@
1
+ - 2026-02-28: `@dataclass(slots=True)` + `Exception` with `super().__init__` raised `TypeError` in `__post_init__`.
2
+ - 2026-02-28: Resolved by using `Exception.__init__(self, self.message)` explicitly.
3
+ - 2026-02-28: Full test suite has pre-existing unrelated failures in `tests/test_cli_help.py` and `tests/test_models_roundtrip.py`.
4
+ - 2026-03-01: `Pyright reportMissingImports` still flags `import typer` in LSP diagnostics, while runtime import succeeds via `uv run python -c "import typer"`; treated as environment/indexer mismatch, not a blocker for Task 6 behavior.
5
+ - 2026-03-01: Subagent repeatedly drifted scope; strict session-resume prompts were required to force Task-13-only implementation.
6
+ - 2026-03-01: `show` was repeatedly missed by subagents; direct scoped implementation was required to close final TODO reliably.
7
+ - 2026-03-01: Local `lsp_diagnostics` reports `reportMissingImports` for `typer`/`rich`/package imports in this environment, but `uv run pytest tests/test_show_command.py -q` and `uv run uitrace show --json ...` pass; treated as non-blocking indexer mismatch.
@@ -0,0 +1,7 @@
1
+ - 2026-02-28: Task 3 introduces a unified error model via `ErrorCode` + `UitError`.
2
+ - 2026-02-28: `format_error` keeps one-line output with optional hint suffix.
3
+ - 2026-02-28: For TDD red-phase, adding a dataclass assertion on `UitError` exposed the gap correctly.
4
+ - 2026-03-01: Task 6 validate-path fix confirms command-level `except UitError` + `typer.Exit(code=int(e.code))` is the reliable way for `CliRunner.invoke` to surface exit code 40.
5
+ - 2026-03-01: Minimal `play` flow can satisfy acceptance by emitting strict JSONL `step_result` rows in dry-run and a fail-fast permission error row in non-dry-run.
6
+ - 2026-03-01: `show --json` summary is stable with keys `events_total`, `steps_total`, `ts_max`, `types`, and `steps_total` should count only playable event types.
7
+ - 2026-03-01: Task 7 `show` command is covered by CLI tests for both `--json` machine output and default human-readable summary; fixture `trace_v1_valid.jsonl` yields `events_total=7`, `steps_total=4`, `ts_max=1.0`.
@@ -0,0 +1 @@
1
+ - 2026-02-28: Unrelated repository test failures remain outside Task 3 scope (`test_cli_help`, `test_models_roundtrip`).
@@ -0,0 +1,2 @@
1
+ # Decisions
2
+ - F3 disposition: workflow safety posture is acceptable for release readiness; only optional hardening items remain (pin third-party actions by commit SHA, add tag protection for `v*`).
@@ -0,0 +1,5 @@
1
+ # Issues
2
+ - None encountered during preflight.
3
+ - No issues encountered while adding the CI workflow.
4
+ - No blockers encountered while implementing Task 3 publish workflow and generating evidence files.
5
+ - No issues encountered while documenting the release process in README.md.
@@ -0,0 +1,17 @@
1
+ # Learnings
2
+ - Package name `uitrace` is confirmed in `pyproject.toml`.
3
+ - `uv build` successfully generates both wheel and sdist using `hatchling` backend.
4
+ - `uitrace` is not currently on PyPI, so the name is available for this project.
5
+ - Added CI workflow in `.github/workflows/ci.yml` targeting `macos-latest`.
6
+ - CI uses `uv sync --frozen` to ensure lockfile consistency.
7
+ - Added `.github/workflows/publish.yml` with `push` tag trigger `v*`, separate `build`/`publish` jobs, and artifact handoff via `release-dists`.
8
+ - Publish workflow enforces tag-to-`pyproject.toml` version parity via `tomllib` and keeps publish command as `uv publish --trusted-publishing always dist/*`.
9
+ - Smoke-test step uses `nullglob` and single-wheel count guard before `uvx --from "${wheels[0]}" ...` to avoid glob ambiguity.
10
+ - Added `Release` section to `README.md` with concise steps for bumping version, local checks, building, and tagging.
11
+ - Documented PyPI Trusted Publishing setup with owner `mkdir700`, repository `uitrace`, and workflow `publish.yml`.
12
+ - Included a version guard note to ensure tag-to-version parity.
13
+ - F3 review: `ci.yml` uses top-level minimal permission `contents: read`, with no secrets/token/password references.
14
+ - F3 review: `publish.yml` keeps OIDC scope job-local (`publish` job `id-token: write`), and no long-lived PyPI token/secret dependency is present.
15
+ - F3 review: artifact handoff is correct (`upload-artifact` in `build` -> `download-artifact` in `publish`) and publish depends on `needs: build`.
16
+ - F3 review: release race is mitigated by `concurrency.group: publish-${{ github.ref }}` and `cancel-in-progress: false`.
17
+ - Plan bookkeeping synced: all remaining acceptance sub-checkboxes were marked complete after verification evidence review.