pytest-selective 0.1.0__tar.gz → 0.2.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 (142) hide show
  1. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/.github/dependabot.yml +4 -0
  2. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/.github/test-lanes.json +5 -1
  3. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/.github/workflows/ci.yml +16 -11
  4. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/.github/workflows/observe-ci.yml +1 -1
  5. pytest_selective-0.2.0/.github/workflows/pr-title.yml +45 -0
  6. pytest_selective-0.2.0/.github/workflows/public-actions.yml +54 -0
  7. pytest_selective-0.2.0/.github/workflows/release-please.yml +54 -0
  8. pytest_selective-0.2.0/.release-please-manifest.json +3 -0
  9. pytest_selective-0.2.0/AGENTS.md +58 -0
  10. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/CHANGELOG.md +18 -0
  11. pytest_selective-0.2.0/CLAUDE.md +1 -0
  12. pytest_selective-0.2.0/CONTRIBUTING.md +125 -0
  13. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/PKG-INFO +65 -17
  14. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/README.md +63 -16
  15. pytest_selective-0.2.0/RELEASING.md +114 -0
  16. pytest_selective-0.2.0/action.yml +106 -0
  17. pytest_selective-0.2.0/agentsync.toml +18 -0
  18. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/README.md +1 -0
  19. pytest_selective-0.2.0/docs/actions.md +42 -0
  20. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/agents.md +6 -12
  21. pytest_selective-0.2.0/docs/benchmarks/2026-10-23-windows-saleor/obligation-baseline.json +6266 -0
  22. pytest_selective-0.2.0/docs/benchmarks/2026-10-23-windows-saleor/selective-after-3.11.xml +1 -0
  23. pytest_selective-0.2.0/docs/benchmarks/2026-10-23-windows-saleor/selective-after-3.14.xml +1 -0
  24. pytest_selective-0.2.0/docs/benchmarks/2026-10-23-windows-saleor/selective-after.json +2901 -0
  25. pytest_selective-0.2.0/docs/benchmarks/2026-10-23-windows-saleor/selective-control-3.11.xml +1 -0
  26. pytest_selective-0.2.0/docs/benchmarks/2026-10-23-windows-saleor/selective-control-3.14.xml +1 -0
  27. pytest_selective-0.2.0/docs/benchmarks/2026-10-23-windows-saleor/selective-control.json +2901 -0
  28. pytest_selective-0.2.0/docs/benchmarks/2026-10-23-windows-saleor/selective-earlier.json +2901 -0
  29. pytest_selective-0.2.0/docs/benchmarks/2026-10-23-windows-saleor.md +108 -0
  30. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/ci-toolkit.md +16 -0
  31. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/ci.md +25 -5
  32. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/comparison-pytest-impacted.md +87 -10
  33. pytest_selective-0.2.0/docs/local-development.md +116 -0
  34. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/pytest-hygiene.md +2 -2
  35. pytest_selective-0.2.0/docs/selection-health.md +47 -0
  36. pytest_selective-0.2.0/docs/work-in-progress/tickets/codex-selector-correctness-performance-test-plan.md +16 -0
  37. pytest_selective-0.2.0/docs/work-in-progress/tickets/public-action-onboarding-test-plan.md +7 -0
  38. pytest_selective-0.2.0/plan-lanes/action.yml +33 -0
  39. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/pyproject.toml +5 -2
  40. pytest_selective-0.2.0/pytest-expansion/action.yml +35 -0
  41. pytest_selective-0.2.0/release-please-config.json +76 -0
  42. pytest_selective-0.2.0/scripts/benchmark_graph.py +67 -0
  43. pytest_selective-0.2.0/scripts/benchmark_rust.py +68 -0
  44. pytest_selective-0.2.0/scripts/public_actions.py +55 -0
  45. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/scripts/smoke_distribution.py +17 -2
  46. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/scripts/tutorial.py +17 -0
  47. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/skills/pytest-selective/SKILL.md +22 -1
  48. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/skills/pytest-selective/references/adoption.md +16 -2
  49. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/impact_graph.py +100 -60
  50. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/impact_models.py +8 -0
  51. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/impact_selection.py +6 -0
  52. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/local.py +6 -2
  53. pytest_selective-0.2.0/src/pytest_selective/parse_batch.py +72 -0
  54. pytest_selective-0.2.0/src/pytest_selective/plugin.py +189 -0
  55. pytest_selective-0.2.0/src/pytest_selective/pytest_plugins.py +108 -0
  56. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/pytest_sharding.py +10 -0
  57. pytest_selective-0.2.0/test-impact/action.yml +106 -0
  58. pytest_selective-0.2.0/tests/test_public_actions.py +30 -0
  59. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/test_repository_ci.py +2 -0
  60. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/testing/git_repo.py +3 -1
  61. pytest_selective-0.2.0/tests/testing/test_git_repo.py +24 -0
  62. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/testing/test_impact_graph.py +27 -0
  63. pytest_selective-0.2.0/tests/testing/test_parse_batch.py +43 -0
  64. pytest_selective-0.2.0/tests/testing/test_pytest_plugin.py +198 -0
  65. pytest_selective-0.2.0/tests/testing/test_pytest_plugins.py +168 -0
  66. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/testing/test_working_tree.py +2 -2
  67. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/uv.lock +3 -1
  68. pytest_selective-0.1.0/AGENTS.md +0 -23
  69. pytest_selective-0.1.0/CONTRIBUTING.md +0 -63
  70. pytest_selective-0.1.0/RELEASING.md +0 -63
  71. pytest_selective-0.1.0/docs/local-development.md +0 -51
  72. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/.gitattributes +0 -0
  73. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  74. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  75. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/.github/actions/plan-lanes/action.yml +0 -0
  76. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/.github/actions/pytest-expansion/action.yml +0 -0
  77. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/.github/actions/test-impact/action.yml +0 -0
  78. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/.github/workflows/release.yml +0 -0
  79. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/.github/workflows/windows-performance.yml +0 -0
  80. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/.gitignore +0 -0
  81. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/.pre-commit-config.yaml +0 -0
  82. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/LICENSE +0 -0
  83. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/PROVENANCE.md +0 -0
  84. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/benchmarks/2026-10-22-due-ci.json +0 -0
  85. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/benchmarks/2026-10-22-due-docs-ci.json +0 -0
  86. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/benchmarks/2026-10-22-due-docs-widget.json +0 -0
  87. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/benchmarks/2026-10-22-due-widget.json +0 -0
  88. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/benchmarks/2026-10-22-input-replays.json +0 -0
  89. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/benchmarks/2026-10-22-obligation-docs.json +0 -0
  90. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/benchmarks/2026-10-22-obligation.json +0 -0
  91. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/benchmarks/2026-10-22-routing.md +0 -0
  92. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/benchmarks/2026-10-22-selective-docs.json +0 -0
  93. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/benchmarks/2026-10-22.md +0 -0
  94. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/benchmarks/windows-runtime.md +0 -0
  95. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/configuration.md +0 -0
  96. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/evidence.md +0 -0
  97. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/pytest-impacted.md +0 -0
  98. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/tutorial.md +0 -0
  99. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/work-in-progress/tickets/codex-windows-git-performance-test-plan.md +0 -0
  100. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/work-in-progress/tickets/impacted-improvements-test-plan.md +0 -0
  101. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/scripts/benchmark_parsing.py +0 -0
  102. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/scripts/check_docs.py +0 -0
  103. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/scripts/check_metadata.py +0 -0
  104. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/scripts/compare_impacted.py +0 -0
  105. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/scripts/measure_ci_runs.py +0 -0
  106. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/skills/pytest-selective/agents/openai.yaml +0 -0
  107. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/__init__.py +0 -0
  108. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/__main__.py +0 -0
  109. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/ast_imports.py +0 -0
  110. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/ci.py +0 -0
  111. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/hygiene.py +0 -0
  112. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/impact_audit.py +0 -0
  113. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/impact_audit_plugin.py +0 -0
  114. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/impact_cli.py +0 -0
  115. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/impact_declarations.py +0 -0
  116. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/impact_explanation.py +0 -0
  117. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/impact_first_party.py +0 -0
  118. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/impact_name_scope.py +0 -0
  119. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/input_policy.py +0 -0
  120. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/py.typed +0 -0
  121. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/pytest_expansion.py +0 -0
  122. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/test_inventory.py +0 -0
  123. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/typecheck_scope.py +0 -0
  124. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/working_tree.py +0 -0
  125. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/__init__.py +0 -0
  126. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/test_ci_measurements.py +0 -0
  127. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/test_distribution_metadata.py +0 -0
  128. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/test_hygiene.py +0 -0
  129. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/test_pytest_expansion.py +0 -0
  130. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/test_repository_hygiene.py +0 -0
  131. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/test_tutorial.py +0 -0
  132. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/testing/__init__.py +0 -0
  133. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/testing/test_ast_imports.py +0 -0
  134. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/testing/test_ci.py +0 -0
  135. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/testing/test_global_inputs.py +0 -0
  136. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/testing/test_impact_audit.py +0 -0
  137. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/testing/test_impact_explanation.py +0 -0
  138. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/testing/test_impact_first_party.py +0 -0
  139. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/testing/test_impact_name_scope.py +0 -0
  140. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/testing/test_portability.py +0 -0
  141. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/testing/test_pytest_sharding.py +0 -0
  142. {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/testing/test_typecheck_scope.py +0 -0
@@ -2,6 +2,8 @@ version: 2
2
2
  updates:
3
3
  - package-ecosystem: github-actions
4
4
  directory: /
5
+ commit-message:
6
+ prefix: ci
5
7
  schedule:
6
8
  interval: weekly
7
9
  groups:
@@ -9,6 +11,8 @@ updates:
9
11
  patterns: ["*"]
10
12
  - package-ecosystem: uv
11
13
  directory: /
14
+ commit-message:
15
+ prefix: build
12
16
  schedule:
13
17
  interval: weekly
14
18
  groups:
@@ -33,6 +33,10 @@
33
33
  ".github/test-lanes.json",
34
34
  ".github/workflows/ci.yml",
35
35
  ".github/workflows/release.yml",
36
- ".github/actions/**"
36
+ ".github/actions/**",
37
+ "action.yml",
38
+ "*/action.yml",
39
+ "examples/**",
40
+ ".github/workflows/public-actions.yml"
37
41
  ]
38
42
  }
@@ -3,7 +3,7 @@ on:
3
3
  push:
4
4
  branches: [main]
5
5
  pull_request:
6
- types: [opened, synchronize, reopened, labeled, unlabeled]
6
+ types: [opened, synchronize, reopened]
7
7
  workflow_dispatch:
8
8
  workflow_call:
9
9
  permissions:
@@ -22,23 +22,23 @@ jobs:
22
22
  with:
23
23
  fetch-depth: 0
24
24
  - id: plan
25
- uses: ./.github/actions/plan-lanes
25
+ uses: ./plan-lanes
26
26
  with:
27
27
  config: .github/test-lanes.json
28
28
  base: ${{ github.event.pull_request.base.sha || github.event.before }}
29
- full: ${{ github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'test:full') }}
29
+ full: ${{ github.run_attempt > 1 || github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'test:full') }}
30
30
  quality:
31
31
  runs-on: ubuntu-latest
32
32
  steps:
33
33
  - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
34
- - uses: gigaverse-app/ci-esta/.github/actions/setup-cached-uv@966f25c4fac4c64bf4ff9df0404321f91f882293
34
+ - uses: gigaverse-app/ci-esta/.github/actions/setup-cached-uv@v0.1
35
35
  with:
36
36
  python-version: '3.14'
37
37
  - run: uv run --locked pre-commit run --all-files
38
38
  - name: Check aggregate gate against the execution lanes
39
39
  run: >-
40
40
  uv run --no-project --python 3.14
41
- --with "ci-esta @ https://github.com/gigaverse-app/ci-esta/archive/966f25c4fac4c64bf4ff9df0404321f91f882293.tar.gz"
41
+ --with "ci-esta>=0.1.0,<0.2.0"
42
42
  ci-esta check-workflow --workflow .github/workflows/ci.yml --lanes .github/test-lanes.json
43
43
  - name: Validate routing even when the platform matrix is skipped
44
44
  run: uv run --locked pytest -q tests/test_repository_ci.py
@@ -57,15 +57,20 @@ jobs:
57
57
  runs-on: ${{ matrix.os }}
58
58
  steps:
59
59
  - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
60
- - uses: gigaverse-app/ci-esta/.github/actions/setup-cached-uv@966f25c4fac4c64bf4ff9df0404321f91f882293
60
+ - uses: gigaverse-app/ci-esta/.github/actions/setup-cached-uv@v0.1
61
61
  with:
62
62
  python-version: ${{ matrix.python }}
63
63
  - name: Use native Git for Windows
64
- uses: gigaverse-app/ci-esta/.github/actions/native-windows-git@966f25c4fac4c64bf4ff9df0404321f91f882293
64
+ uses: gigaverse-app/ci-esta/.github/actions/native-windows-git@v0.1
65
65
  - name: Record coverage runtime
66
66
  run: uv run --locked python -m coverage --version
67
67
  - run: uv run --locked pytest -q -n 4 --durations=20 --junitxml=test-timings.xml --cov --cov-report=term-missing --cov-report=xml
68
- - uses: gigaverse-app/ci-esta/.github/actions/learn-test-timings@966f25c4fac4c64bf4ff9df0404321f91f882293
68
+ env:
69
+ # Keep temporary Git repositories beside the checkout on the work disk.
70
+ TMP: ${{ runner.temp }}
71
+ TEMP: ${{ runner.temp }}
72
+ TMPDIR: ${{ runner.temp }}
73
+ - uses: gigaverse-app/ci-esta/.github/actions/learn-test-timings@v0.1
69
74
  with:
70
75
  junit-pattern: test-timings.xml
71
76
  artifact-name: test-timings-${{ matrix.python }}-${{ matrix.os }}
@@ -84,7 +89,7 @@ jobs:
84
89
  runs-on: ubuntu-latest
85
90
  steps:
86
91
  - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
87
- - uses: gigaverse-app/ci-esta/.github/actions/setup-cached-uv@966f25c4fac4c64bf4ff9df0404321f91f882293
92
+ - uses: gigaverse-app/ci-esta/.github/actions/setup-cached-uv@v0.1
88
93
  with:
89
94
  python-version: '3.11'
90
95
  - run: uv pip install 'pytest==8.0.0'
@@ -93,7 +98,7 @@ jobs:
93
98
  runs-on: ubuntu-latest
94
99
  steps:
95
100
  - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
96
- - uses: gigaverse-app/ci-esta/.github/actions/setup-cached-uv@966f25c4fac4c64bf4ff9df0404321f91f882293
101
+ - uses: gigaverse-app/ci-esta/.github/actions/setup-cached-uv@v0.1
97
102
  with:
98
103
  python-version: '3.14'
99
104
  - run: uv build
@@ -112,7 +117,7 @@ jobs:
112
117
  if: ${{ !cancelled() }}
113
118
  runs-on: ubuntu-latest
114
119
  steps:
115
- - uses: gigaverse-app/ci-esta/.github/actions/validation-gate@966f25c4fac4c64bf4ff9df0404321f91f882293
120
+ - uses: gigaverse-app/ci-esta/.github/actions/validation-gate@v0.1
116
121
  with:
117
122
  needs: ${{ toJSON(needs) }}
118
123
  lanes: ${{ needs.select-tests.outputs.lanes || '{}' }}
@@ -13,7 +13,7 @@ permissions:
13
13
 
14
14
  jobs:
15
15
  report:
16
- uses: gigaverse-app/ci-esta/.github/workflows/report.yml@966f25c4fac4c64bf4ff9df0404321f91f882293
16
+ uses: gigaverse-app/ci-esta/.github/workflows/report.yml@v0.3.0
17
17
  with:
18
18
  run-id: ${{ github.event.workflow_run.id }}
19
19
  run-attempt: ${{ github.event.workflow_run.run_attempt }}
@@ -0,0 +1,45 @@
1
+ name: PR title
2
+
3
+ # Squash merges use this checked title as the Conventional Commit header.
4
+ on:
5
+ pull_request_target:
6
+ types: [opened, edited, synchronize, reopened, ready_for_review]
7
+
8
+ permissions:
9
+ pull-requests: read
10
+
11
+ jobs:
12
+ conventional-commit:
13
+ runs-on: ubuntu-latest
14
+ timeout-minutes: 5
15
+ steps:
16
+ # Only reads PR metadata. Never check out or execute PR code in this workflow.
17
+ - uses: amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50 # v6.1.1
18
+ with:
19
+ types: |
20
+ feat
21
+ fix
22
+ perf
23
+ revert
24
+ docs
25
+ style
26
+ refactor
27
+ test
28
+ build
29
+ ci
30
+ chore
31
+ requireScope: false
32
+ env:
33
+ GITHUB_TOKEN: ${{ github.token }}
34
+ - name: Explain how to repair the title
35
+ if: failure()
36
+ run: |
37
+ cat >> "$GITHUB_STEP_SUMMARY" <<'EOF'
38
+ Rename the PR to `type(optional-scope): description`, for example
39
+ `fix(parser): handle empty input` or `docs: clarify installation`.
40
+ Use `!` before the colon for a breaking change, for example
41
+ `feat(api)!: remove the deprecated argument`.
42
+ Choose the type that describes the change; do not hide features or fixes under `chore:`.
43
+ Editing the PR title reruns this check. No commit rewrite or replacement PR is needed.
44
+ If the title is already valid, inspect the action log for an API or runner failure.
45
+ EOF
@@ -0,0 +1,54 @@
1
+ name: Public action smoke
2
+ on:
3
+ pull_request:
4
+ push:
5
+ branches: [main]
6
+ workflow_dispatch:
7
+ permissions:
8
+ contents: read
9
+ jobs:
10
+ public-actions:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
14
+ with:
15
+ fetch-depth: 0
16
+ - name: Use the reviewed repository graph
17
+ run: |
18
+ python - <<'PY'
19
+ import json
20
+ from pathlib import Path
21
+ graph = json.loads(Path('.github/test-lanes.json').read_text())['graph']
22
+ Path('smoke-impact.json').write_text(json.dumps(graph))
23
+ PY
24
+ - uses: ./
25
+ id: impact
26
+ with:
27
+ config: smoke-impact.json
28
+ base: ${{ github.sha }}
29
+ full: 'true'
30
+ full-roots: tests
31
+ max-shards: '2'
32
+ explanation-artifact: ''
33
+ - name: Verify forwarded file-plan outputs
34
+ env:
35
+ MODE: ${{ steps.impact.outputs.mode }}
36
+ ROOTS: ${{ steps.impact.outputs.test_roots }}
37
+ run: |
38
+ test "$MODE" = full
39
+ test -n "$ROOTS"
40
+ - uses: ./plan-lanes
41
+ id: lanes
42
+ with:
43
+ config: .github/test-lanes.json
44
+ base: ${{ github.sha }}
45
+ full: 'true'
46
+ artifact-name: ''
47
+ - name: Verify forwarded lane outputs
48
+ env:
49
+ LANES: ${{ steps.lanes.outputs.lanes }}
50
+ run: |
51
+ python - <<'PY'
52
+ import json, os
53
+ assert json.loads(os.environ['LANES']) == {'tests': True}
54
+ PY
@@ -0,0 +1,54 @@
1
+ name: Release Please
2
+
3
+ # Release PRs accumulate changes; merging one is the publishing decision.
4
+ on:
5
+ workflow_run:
6
+ workflows: [CI]
7
+ branches: [main]
8
+ types: [completed]
9
+
10
+ permissions: {}
11
+
12
+ concurrency:
13
+ group: release-please
14
+ cancel-in-progress: false
15
+
16
+ jobs:
17
+ release-please:
18
+ if: >-
19
+ github.event.workflow_run.event == 'push'
20
+ && github.event.workflow_run.conclusion == 'success'
21
+ && github.event.workflow_run.head_repository.full_name == github.repository
22
+ runs-on: ubuntu-latest
23
+ environment: release-automation
24
+ timeout-minutes: 10
25
+ permissions:
26
+ contents: write
27
+ pull-requests: write
28
+ steps:
29
+ - name: Only process the tested main head
30
+ id: current
31
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
32
+ with:
33
+ script: |
34
+ const {data: branch} = await github.rest.repos.getBranch({...context.repo, branch: 'main'});
35
+ core.setOutput('matches', branch.commit.sha === context.payload.workflow_run.head_sha);
36
+ - name: Require release bot authentication
37
+ if: steps.current.outputs.matches == 'true'
38
+ env:
39
+ HAS_RELEASE_TOKEN: ${{ secrets.GV_CI_CROSS_REPO_TOKEN != '' }}
40
+ run: |
41
+ if [[ "$HAS_RELEASE_TOKEN" != "true" ]]; then
42
+ echo "::error::Share the organization GV_CI_CROSS_REPO_TOKEN secret with this repository."
43
+ exit 1
44
+ fi
45
+ - name: Prepare release PR or publish its GitHub release
46
+ if: steps.current.outputs.matches == 'true'
47
+ uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5.0.0
48
+ with:
49
+ # This credential triggers CI on release PRs and Publish on releases.
50
+ # GITHUB_TOKEN would suppress those follow-up workflow events.
51
+ token: ${{ secrets.GV_CI_CROSS_REPO_TOKEN }}
52
+ target-branch: main
53
+ config-file: release-please-config.json
54
+ manifest-file: .release-please-manifest.json
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.2.0"
3
+ }
@@ -0,0 +1,58 @@
1
+ # Working on pytest-selective
2
+
3
+ For adopting the tool in another repository, use
4
+ [the portable skill](skills/pytest-selective/SKILL.md). This file describes work
5
+ on pytest-selective itself.
6
+
7
+ - Read [CONTRIBUTING.md](CONTRIBUTING.md) for setup and validation. Use the locked
8
+ environment: `uv sync --locked`, `uv run pre-commit run --all-files`,
9
+ `uv run pytest -q -n 4`. For packaging changes also build, run strict Twine,
10
+ `scripts/check_metadata.py` and `scripts/smoke_distribution.py`.
11
+ - Reproduce selection bugs using real temporary Git repositories and existing
12
+ `tests/testing/git_repo.py` helpers. Cover base and head trees, deleted inputs,
13
+ explicit declarations and the relevant fallback. Do not mock away selection.
14
+ - Planning supports committed revisions and explicit working-tree snapshots. Preserve full execution on
15
+ operational uncertainty and diagnostics for invalid declarations. An empty
16
+ selection is not an empty pytest argument list.
17
+ - Keep consumer routing regressions in the always-running quality job. Update
18
+ `.github/test-lanes.json` when adding execution inputs; preserve full main/manual
19
+ checkpoints and the `test:full` override.
20
+ - The README's performance numbers are scenario-specific observations. Keep
21
+ claims linked to [raw evidence](docs/benchmarks/2026-10-22-routing.md); distinguish
22
+ runner-seconds, elapsed time and billing. Skill/example edits need usable links
23
+ and verified commands, not tests that merely assert prose wording.
24
+
25
+ ## Commits and pull requests
26
+
27
+ - Use Conventional Commits for commits you create and PR titles:
28
+ `type(optional-scope): description`, for example
29
+ `fix(parser): handle empty input`.
30
+ - Allowed types: `feat`, `fix`, `perf`, `revert`, `docs`, `style`,
31
+ `refactor`, `test`, `build`, `ci`, and `chore`. Choose the type for the
32
+ actual change. Mark breaking changes with `!` before the colon and explain
33
+ the migration in the PR body.
34
+ - Repair an invalid PR title in place. Preserve useful work; do not close or
35
+ replace the PR, or rewrite existing commits just to satisfy the title check.
36
+ - Squash merges use the checked PR title. Keep any `BREAKING CHANGE:` details
37
+ in the body. Follow [CONTRIBUTING.md](CONTRIBUTING.md) and
38
+ [RELEASING.md](RELEASING.md).
39
+
40
+ ## Releases
41
+
42
+ Release Please derives versions and changelogs from Conventional Commits. Let
43
+ it prepare the release PR; do not hand-edit versions for ordinary changes.
44
+ Merging a release PR authorizes PyPI publication after CI. Follow RELEASING.md.
45
+
46
+ ## Shared agent instructions
47
+
48
+ Edit this root `AGENTS.md` as the single source for Codex and Claude.
49
+ `CLAUDE.md` is an AgentSync-managed relative symlink to this file, not a
50
+ separate instruction document. The configuration is
51
+ [agentsync.toml](agentsync.toml). To restore and verify the link:
52
+
53
+ ```bash
54
+ npx --yes @dallay/agentsync@1.52.3 apply
55
+ npx --yes @dallay/agentsync@1.52.3 status
56
+ ```
57
+
58
+ Keep the symlink tracked in Git. See CONTRIBUTING.md for platform setup.
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.2.0](https://github.com/gigaverse-app/pytest-selective/compare/v0.1.1...v0.2.0) (2026-10-23)
4
+
5
+
6
+ ### Features
7
+
8
+ * add public action entry points and task-focused onboarding ([#41](https://github.com/gigaverse-app/pytest-selective/issues/41)) ([94da1e6](https://github.com/gigaverse-app/pytest-selective/commit/94da1e6d4088d9ded93ce491dc88993ac140e0ea))
9
+
10
+
11
+ ### Bug fixes
12
+
13
+ * **selection:** preserve plugin sessions and accelerate graph construction ([#42](https://github.com/gigaverse-app/pytest-selective/issues/42)) ([2994c88](https://github.com/gigaverse-app/pytest-selective/commit/2994c887d916a965b78f5ff8d48476abed705e37))
14
+
15
+ ## 0.1.1 (2026-10-23)
16
+
17
+ - Register a native pytest plugin: `pytest --selective`, ini defaults, optional existing impact JSON, an exact comparison base, and `--no-selective` for full execution.
18
+ - Reuse the existing working-tree snapshots and dependency planner; share one plan with xdist workers and preserve unknown collectors, doctests, normal pytest filtering and failure statuses.
19
+ - Install pytest as a runtime dependency; retain the audit extra and all CLI/CI interfaces.
20
+
3
21
  ## 0.1.0 (2026-10-23)
4
22
 
5
23
  First PyPI release.
@@ -0,0 +1 @@
1
+ AGENTS.md
@@ -0,0 +1,125 @@
1
+ # Contributing to pytest-selective
2
+
3
+ Use Python 3.11+, Git 2.24+, and uv. The planner operates on immutable Git trees;
4
+ tests should exercise real temporary repositories through the existing helpers
5
+ in `tests/testing/git_repo.py`.
6
+
7
+ ```bash
8
+ uv sync --locked
9
+ uv run pre-commit install
10
+ uv run pre-commit run --all-files
11
+ uv run pytest -q --cov --cov-report=term-missing
12
+ uv run python scripts/tutorial.py
13
+ uv build
14
+ uv run twine check --strict dist/*
15
+ uv run python scripts/smoke_distribution.py
16
+ ```
17
+
18
+ Ruff lint and formatting use the versions in `uv.lock`, both locally and in CI.
19
+ Hooks fix repairable lint and formatting issues; review and stage their edits.
20
+ The Markdown hook checks local file links. It does not check external URLs or
21
+ heading anchors. Tests run separately so normal commits stay quick.
22
+
23
+ ## Preserve selection safety
24
+
25
+ For a bug, first add a failing regression using an actual Git change. Assert the
26
+ selected paths and observable outcome. Include base and head behavior, invalid
27
+ inputs, and fallback handling when relevant. Prefer existing helpers over mocks
28
+ of Git or the selector. Do not weaken selection or add broad ignores to hide a
29
+ failure. Keep root conftests small: every importer inherits their dependencies.
30
+
31
+ Changes to collection policy, runtime auditing, or the composite action need tests
32
+ at that boundary. Update the tutorial when the public command contract changes.
33
+ Keep performance claims tied to reproducible measurements and their limitations.
34
+
35
+ ## CI and dependency maintenance
36
+
37
+ CI tests Python 3.11 and 3.14 on Linux, Windows, and macOS. A separate job checks
38
+ pytest 8.0.0 on Python 3.11, the plugin's lower bound. It also checks hooks, builds both distribution
39
+ formats, validates PyPI metadata, and installs each distribution in an isolated
40
+ environment on both Python versions. Evidence artifacts carry coverage and tutorial output on every platform and Python version.
41
+
42
+ Use `uv lock --upgrade-package NAME` for a targeted dependency update and run the
43
+ affected checks. Dependabot proposes weekly uv and GitHub Actions updates.
44
+ Actions are pinned to commits. Review their release notes before updating pins.
45
+
46
+ ## Pull requests
47
+
48
+ Explain the user-visible problem and the resulting behavior. Include the exact
49
+ validation commands, measured evidence where applicable, and any remaining
50
+ limitations. The pull request template provides a short checklist. See
51
+ [RELEASING.md](RELEASING.md) for package publication.
52
+
53
+
54
+ ## CI lane selection
55
+
56
+ This repository uses its own `plan-lanes` action. Documentation-only PRs keep
57
+ quality checks (including Markdown links) and distribution build/install checks,
58
+ while skipping the six-platform pytest matrix and minimum-pytest lane. Source,
59
+ tests, scripts, dependency/pytest policy and workflow changes run the complete
60
+ matrix. Main, manual/called runs and the `test:full` label run it in full; a
61
+ failed planner also runs all tests. Repository routing controls exercise the
62
+ committed config against real Git trees, including full and missing-history
63
+ controls. Add new non-import execution inputs to `.github/test-lanes.json`.
64
+
65
+ ## Conventional Commits
66
+
67
+ Use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/)
68
+ for commits you create and PR titles (the squash commit that lands on `main`):
69
+
70
+ ```text
71
+ fix(parser): handle empty input
72
+ feat: add a new output format
73
+ feat(api)!: remove the deprecated argument
74
+ docs: clarify installation
75
+ ```
76
+
77
+ Allowed types are `feat`, `fix`, `perf`, `revert`, `docs`, `style`,
78
+ `refactor`, `test`, `build`, `ci`, and `chore`. Scope is optional.
79
+ Use `!` before the colon for breaking changes and explain the migration in the
80
+ PR body. Choose the type for the actual change, since release tooling uses it.
81
+
82
+ The `conventional-commit` check uses
83
+ [amannn/action-semantic-pull-request](https://github.com/amannn/action-semantic-pull-request).
84
+ It reads PR metadata, including for forks, without checking out contributor code.
85
+ If it fails on a title, rename the PR; the edited event reruns the check.
86
+ Keep the existing PR and commits. Work-in-progress commits need not be rewritten.
87
+
88
+ Use **Squash and merge**, with the PR title as the commit title. Check the final
89
+ message before merging, including single-commit PRs, and preserve any
90
+ `BREAKING CHANGE:` explanation in the body. The repository's squash defaults
91
+ support this, but a maintainer can still edit the final message.
92
+ Release Please turns these commits into a release PR containing the version,
93
+ changelog, and lockfile update. Merging that PR authorizes PyPI publication after
94
+ CI. See [RELEASING.md](RELEASING.md) for the version rules and publishing.
95
+
96
+ ## Shared instructions for Codex and Claude
97
+
98
+ [AGENTS.md](AGENTS.md) is the canonical repository guidance. Codex reads it
99
+ directly; Claude reads the tracked `CLAUDE.md -> AGENTS.md` symlink. Edit
100
+ `AGENTS.md` once, including commit-policy changes, so both tools receive the
101
+ same instructions.
102
+
103
+ [dallay/agentsync](https://github.com/dallay/agentsync) manages that link through
104
+ [agentsync.toml](agentsync.toml). After cloning, or to repair a
105
+ missing or stale link, run these commands from the repository root with Node.js
106
+ 18+ and npm installed:
107
+
108
+ ```bash
109
+ npx --yes @dallay/agentsync@1.52.3 apply
110
+ npx --yes @dallay/agentsync@1.52.3 status
111
+ ```
112
+
113
+ The CLI version is pinned for reproducible setup. Review and update both commands
114
+ when upgrading AgentSync. The configuration disables managed gitignore changes
115
+ because we intentionally commit the relative link, following AgentSync's
116
+ [committed-destination workflow](https://dallay.github.io/agentsync/guides/gitignore-team-workflows/).
117
+ Ordinary instruction edits propagate immediately through the link.
118
+
119
+ On native Windows, enable Developer Mode and Git symlink support
120
+ (`git config core.symlinks true`), then run `apply` to repair a checkout that
121
+ materialized the link as plain text. Alternatively, use WSL for a checkout in
122
+ the Linux filesystem. See the
123
+ [Windows setup guide](https://dallay.github.io/agentsync/guides/windows-symlink-setup/).
124
+ If AgentSync backs up an existing `CLAUDE.md`, review and preserve any unique
125
+ guidance in `AGENTS.md`; do not commit the backup as another instruction source.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: pytest-selective
3
- Version: 0.1.0
3
+ Version: 0.2.0
4
4
  Summary: Explainable Python test impact analysis: select affected pytest files from Git changes
5
5
  Project-URL: Homepage, https://github.com/gigaverse-app/pytest-selective
6
6
  Project-URL: Documentation, https://github.com/gigaverse-app/pytest-selective/blob/main/docs/README.md
@@ -23,6 +23,7 @@ Classifier: Topic :: Software Development :: Testing
23
23
  Classifier: Typing :: Typed
24
24
  Requires-Python: >=3.11
25
25
  Requires-Dist: pydantic<3,>=2.11
26
+ Requires-Dist: pytest>=8
26
27
  Requires-Dist: pyyaml<7,>=6
27
28
  Provides-Extra: audit
28
29
  Requires-Dist: pytest>=8; extra == 'audit'
@@ -33,21 +34,17 @@ Description-Content-Type: text/markdown
33
34
  **Run affected Python tests. See why they matter.**
34
35
 
35
36
  [![CI](https://github.com/gigaverse-app/pytest-selective/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/gigaverse-app/pytest-selective/actions/workflows/ci.yml)
37
+ [![PyPI](https://img.shields.io/pypi/v/pytest-selective)](https://pypi.org/project/pytest-selective/)
36
38
  [![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-3776AB?logo=python&logoColor=white)](https://github.com/gigaverse-app/pytest-selective/blob/main/pyproject.toml)
37
39
  [![Typed](https://img.shields.io/badge/typing-py.typed-3776AB)](https://github.com/gigaverse-app/pytest-selective/blob/main/src/pytest_selective/py.typed)
38
40
  [![Ruff](https://img.shields.io/badge/code%20style-Ruff-D7FF64?logo=ruff&logoColor=black)](https://github.com/gigaverse-app/pytest-selective/blob/main/.pre-commit-config.yaml)
39
41
  [![Apache-2.0](https://img.shields.io/badge/license-Apache--2.0-blue)](https://github.com/gigaverse-app/pytest-selective/blob/main/LICENSE)
40
42
  [![Agent skill](https://img.shields.io/badge/Agent_Skill-ready-2563EB)](https://github.com/gigaverse-app/pytest-selective/blob/main/docs/agents.md)
41
43
 
42
- **Our README CI used 92.3% less runner time: 627s → 48s.** Elapsed time fell
43
- from 211s to 26s, with docs, routing and package checks preserved. One successful
44
- same-revision pair, not a universal speedup.
45
- [Inspect the runs and raw evidence](https://github.com/gigaverse-app/pytest-selective/blob/main/docs/benchmarks/2026-10-22-routing.md).
46
-
47
44
  pytest-selective is a **Python test impact analysis** tool for incremental testing
48
45
  with pytest. It follows dependencies through both sides of a Git change, selects
49
- the affected test files, and explains the result. Plan before collecting tests,
50
- importing your application, or starting databases and workers.
46
+ the affected test files, and explains the result. Use it directly as a pytest
47
+ plugin, or plan before collection and service startup with the CLI and CI actions.
51
48
 
52
49
  Built from the selector used in Gigaverse's backend, AI, and shared Python
53
50
  infrastructure. The API may change before 1.0.
@@ -67,6 +64,29 @@ used **49 instead of 105 runner-seconds (53.3% less)** while keeping quality,
67
64
  routing and package checks. Its reports now compute dependency critical paths
68
65
  and slack. [See the source runs and method](https://github.com/gigaverse-app/ci-esta/blob/main/docs/benchmarks/2026-10-23-toolkit.md).
69
66
 
67
+ ## Choose how to use it
68
+
69
+ | You want to… | Use | What it saves |
70
+ | --- | --- | --- |
71
+ | Test local edits with your existing pytest command | `uv add --dev pytest-selective`, then `uv run pytest --selective` | Unaffected test execution; staged, unstaged and untracked changes are included |
72
+ | Avoid expensive collection and application imports | `pytest-selective run --config .github/test-impact.json -- -q` | Collection/imports for unaffected files as well as execution |
73
+ | Plan affected files in GitHub Actions | `gigaverse-app/pytest-selective@main` | Plans before installing your application |
74
+ | Keep whole-suite coverage or conformance checks | `gigaverse-app/pytest-selective/plan-lanes@main` | Entire unaffected jobs, including their services and setup |
75
+ | Check assumptions about JSON, templates and other runtime inputs | Optional file-read recorder and dependency audit | Exposes observed reads missing from the declared graph |
76
+ | Keep selection narrow as the project grows | Explanations, startup-floor budgets, expansion and isolation guards | Makes broad new fixture/import dependencies visible |
77
+
78
+ Start with [local pytest](docs/local-development.md), [the complete CI recipe](docs/ci.md),
79
+ or [dependency audits and hygiene](docs/selection-health.md). The native plugin
80
+ collects normally; the pre-collection runner and CI planner can avoid that cost.
81
+ Keep full checkpoints and use complete lanes when partial suites cannot satisfy
82
+ your coverage contract.
83
+
84
+ **Public-path availability:** root and short action paths are new on `main`;
85
+ existing `v0.1` releases predate them. Evaluate with `@main`, or pin a reviewed
86
+ commit containing the public `action.yml`. Adopt a compatible release tag after
87
+ it includes these paths. Existing `.github/actions/...` paths remain supported.
88
+ [Public action API](docs/actions.md).
89
+
70
90
  ## Have your agent set it up
71
91
 
72
92
  Paste this into your coding agent in the Python project you want to improve:
@@ -128,7 +148,27 @@ including Due's widget benchmark, which selection skips entirely.
128
148
 
129
149
  ## Try it in two minutes
130
150
 
131
- Requires **Python 3.11+, Git 2.24+, and uv**. Use a planner Python version at
151
+ Install the plugin in your test environment, then use ordinary pytest:
152
+
153
+ ```bash
154
+ uv add --dev pytest-selective
155
+ uv run pytest --selective
156
+ uv run pytest --selective --selective-base origin/main -n auto
157
+ uv run pytest --no-selective
158
+ ```
159
+
160
+ Selection is opt-in. The default compares HEAD with staged, unstaged and
161
+ nonignored untracked files. `--selective-base` compares against the exact ref
162
+ you supply, including local edits. The plugin reuses the CLI's dependency graph,
163
+ deselects unaffected collected tests, and keeps doctests and unknown collectors.
164
+ Normal test paths, node IDs, `-k` and `-m` still apply. Missing history runs the
165
+ complete requested suite. [Plugin configuration and limits](docs/local-development.md).
166
+
167
+ For pre-collection selection, use `pytest-selective run`; for CI jobs with
168
+ expensive setup or whole-suite evidence requirements, use lane selection.
169
+
170
+ Requires **Python 3.11+ and Git 2.24+**. The examples use uv; the native plugin
171
+ also works in your existing pytest environment. Use a planner Python version at
132
172
  least as new as your source syntax; the CI action uses Python 3.14. Your test
133
173
  runtime can use a different Python version when planning runs separately.
134
174
  The optional audit recorder requires Python 3.11+ in the test environment.
@@ -152,13 +192,20 @@ hold. It uses a temporary repository and leaves your checkout untouched.
152
192
 
153
193
  ## Install in your project
154
194
 
155
- Until the first PyPI release, install from GitHub using Python 3.11+:
195
+ Install from PyPI using Python 3.11+:
196
+
197
+ ```bash
198
+ pip install "pytest-selective>=0.1.0,<0.2.0"
199
+ ```
200
+
201
+ For source development, GitHub installation is also available:
156
202
 
157
203
  ```bash
158
204
  pip install "pytest-selective @ git+https://github.com/gigaverse-app/pytest-selective.git"
159
205
  ```
160
206
 
161
- Pin a reviewed commit in CI. Then follow the
207
+ Use compatible package ranges; lockfiles retain exact resolved artifacts.
208
+ For action-path availability and release pins, see [the action API](docs/actions.md). Then follow the
162
209
  [configuration walkthrough](https://github.com/gigaverse-app/pytest-selective/blob/main/docs/configuration.md)
163
210
  to declare module roots, test roots, collection-policy fingerprints, and non-Python inputs.
164
211
 
@@ -168,7 +215,8 @@ pytest-selective affected --config .github/test-impact.json \
168
215
  --explanation-output explanation.json
169
216
  ```
170
217
 
171
- Planning reads **committed Git trees**. Uncommitted edits are outside the plan.
218
+ `affected` reads **committed Git trees** by default. Use `affected --working-tree`
219
+ or `pytest-selective run` to include uncommitted edits.
172
220
  The report distinguishes `scoped`, `full`, and `none`; an empty selection must
173
221
  skip pytest, because invoking pytest without paths runs the whole suite.
174
222
 
@@ -185,7 +233,7 @@ skip pytest, because invoking pytest without paths runs the whole suite.
185
233
  | Undeclared runtime reads | An opt-in pytest recorder and audit command |
186
234
 
187
235
  The CLI emits JSON for your runner. The
188
- [composite action](https://github.com/gigaverse-app/pytest-selective/blob/main/.github/actions/test-impact/action.yml)
236
+ [composite action](https://github.com/gigaverse-app/pytest-selective/blob/main/test-impact/action.yml)
189
237
  adds caching and falls back to complete test roots on operational planning
190
238
  failures. Invalid dependency declarations fail with a diagnostic that must be fixed.
191
239
 
@@ -210,9 +258,9 @@ and evidence checks.
210
258
  ## Choose the right tool
211
259
 
212
260
  [pytest-impacted](https://github.com/promptromp/pytest-impacted) offers a pytest-native
213
- `--impacted` workflow, including working-tree changes. pytest-selective focuses on
214
- committed revisions, inspectable JSON plans, runtime dependency audits, and
215
- planning before application startup. Both use static dependency analysis; choose
261
+ `--impacted` workflow, including working-tree changes. pytest-selective supports the same local edit/test loop and also offers
262
+ inspectable JSON plans, runtime dependency audits, and planning before application
263
+ startup. Both use static dependency analysis; choose
216
264
  based on your workflow, and validate selection against your own suite.
217
265
  See the [lessons from pytest-impacted](https://github.com/gigaverse-app/pytest-selective/blob/main/docs/pytest-impacted.md)
218
266
  for portability and Git-resolution improvements adopted from that comparison.
@@ -246,7 +294,7 @@ optional; pytest-selective does not depend on it.</sub>
246
294
 
247
295
  See the [CI toolkit integration](docs/ci-toolkit.md) for lane selection, validated
248
296
  environment caches, required gates and real dependency critical-path reports.
249
- # Optimize the work that still has to run
297
+ ## Optimize the work that still has to run
250
298
 
251
299
  Selection and execution solve different parts of slow CI. Once selection keeps
252
300
  the required tests, use [CI-esta's critical-path report](https://github.com/gigaverse-app/ci-esta/blob/main/docs/critical-path-optimizations.md)