Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 20 additions & 12 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ subprocess. The division of responsibility:
- Python-specific classification signals
- Coverage data parsing (coverage.py)
- Cyclomatic complexity calculation (lifted gaze-py McCabe; no radon)
- Test-to-assertion mapping (pytest)
- Test-to-assertion mapping (pytest and unittest)
- File and project discovery

## Technology Stack
Expand All @@ -73,7 +73,8 @@ subprocess. The division of responsibility:
- **Scope analysis**: Python `symtable` module (stdlib) for
global/nonlocal detection
- **Inference**: [Astroid](https://github.com/pylint-dev/astroid) `>=3.0,<4`
(shipped) for caller-count inference in `analysis/inference.py`
(shipped) for caller-count inference in `analysis/inference.py` and
strategy-3 transitive-call pairing in `quality/pairing.py`
- **Complexity**: lifted gaze-py McCabe implementation; no radon dependency
- **Coverage**: [coverage.py](https://github.com/nedbat/coveragepy) `>=7.0,<8`
(shipped runtime dependency) for parsing `.coverage` data files
Expand All @@ -99,16 +100,22 @@ snake-eyes/
│ │ ├── detector.py # Python side-effect detector (analyze method)
│ │ ├── complexity.py # McCabe cyclomatic complexity (complexity method)
│ │ └── inference.py # astroid caller-count inference (classify_signals)
│ └── signals/
│ ├── __init__.py
│ ├── _routing.py # effect-type → category routing (reconstructed from gaze-py)
│ ├── _types.py # SignalResult value type
│ ├── interface.py # interface source extractor (reconstructed from gaze-py)
│ ├── visibility.py # visibility source extractor (reconstructed from gaze-py)
│ ├── caller.py # caller_count source extractor (reconstructed from gaze-py)
│ ├── naming.py # naming_convention source extractor (reconstructed from gaze-py)
│ ├── docstring.py # docstring source extractor (reconstructed from gaze-py)
│ └── adapter.py # extract_signals fan-out (classify_signals method)
│ ├── signals/
│ │ ├── __init__.py
│ │ ├── _routing.py # effect-type → category routing (reconstructed from gaze-py)
│ │ ├── _types.py # SignalResult value type
│ │ ├── interface.py # interface source extractor (reconstructed from gaze-py)
│ │ ├── visibility.py # visibility source extractor (reconstructed from gaze-py)
│ │ ├── caller.py # caller_count source extractor (reconstructed from gaze-py)
│ │ ├── naming.py # naming_convention source extractor (reconstructed from gaze-py)
│ │ ├── docstring.py # docstring source extractor (reconstructed from gaze-py)
│ │ └── adapter.py # extract_signals fan-out (classify_signals method)
│ └── quality/
│ ├── __init__.py # re-exports run_test_mapping
│ ├── pairing.py # test-function pairing (3 strategies, lifted from gaze-py)
│ ├── assertions.py # assertion detection & classification (lifted from gaze-py)
│ ├── mapping.py # side-effect-type inference (test_mapping method)
│ └── pipeline.py # run_test_mapping orchestration (test_mapping method)
├── tests/
├── .github/workflows/ # CI: ruff, mypy, pytest gates
├── pyproject.toml
Expand All @@ -119,6 +126,7 @@ snake-eyes/
```
Delivered in issue #4: `detector.py`, `complexity.py`, `coverage.py`, `_shared.py`, and the `analyze`, `complexity`, and `coverage` JSON-RPC methods.
Delivered in issue #5: the `signals/` extractors, `analysis/inference.py` (astroid caller-count inference), and the `classify_signals` JSON-RPC method.
Delivered in issue #6: the `quality/` package (`pairing.py`, `assertions.py`, `mapping.py`, `pipeline.py`), and the `test_mapping` JSON-RPC method.

## Shell Commands

Expand Down
51 changes: 31 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@ Snake Eyes is a Gaze-spawned subprocess. It speaks JSON-RPC 2.0 over stdin/stdou
| `complexity` | Implemented |
| `coverage` | Implemented |
| `classify_signals` | Implemented |

Capability flags advertised at handshake: `discover` and
`classify_signals` are `true`; `test_mapping` and `streaming` are `false`.
Side-effect detection and classification-signal extraction are
implemented. coverage.py (`>=7.0,<8`) and astroid (`>=3.0,<4`,
caller-count inference) are runtime dependencies (shipped). `radon` is
not used — cyclomatic complexity is computed via a lifted McCabe
| `test_mapping` | Implemented |

Capability flags advertised at handshake: `discover`, `classify_signals`,
and `test_mapping` are `true`; `streaming` is `false`.
Side-effect detection, classification-signal extraction, and
test-to-assertion mapping are implemented. coverage.py (`>=7.0,<8`) and
astroid (`>=3.0,<4`, caller-count inference and strategy-3 transitive-call
pairing in `quality/pairing.py`) are runtime dependencies (shipped).
`radon` is not used — cyclomatic complexity is computed via a lifted McCabe
implementation (no radon dependency).

## Installation
Expand Down Expand Up @@ -66,16 +68,22 @@ snake-eyes/
│ │ ├── detector.py # Python side-effect detector (analyze method)
│ │ ├── complexity.py # McCabe cyclomatic complexity (complexity method)
│ │ └── inference.py # astroid caller-count inference (classify_signals)
│ └── signals/
│ ├── __init__.py
│ ├── interface.py # interface source extractor (reconstructed from gaze-py)
│ ├── visibility.py # visibility source extractor (reconstructed from gaze-py)
│ ├── caller.py # caller_count source extractor (reconstructed from gaze-py)
│ ├── naming.py # naming_convention source extractor (reconstructed from gaze-py)
│ ├── docstring.py # docstring source extractor (reconstructed from gaze-py)
│ ├── _routing.py # effect-type → category routing (reconstructed from gaze-py)
│ ├── _types.py # SignalResult value type
│ └── adapter.py # extract_signals fan-out (classify_signals method)
│ ├── signals/
│ │ ├── __init__.py
│ │ ├── interface.py # interface source extractor (reconstructed from gaze-py)
│ │ ├── visibility.py # visibility source extractor (reconstructed from gaze-py)
│ │ ├── caller.py # caller_count source extractor (reconstructed from gaze-py)
│ │ ├── naming.py # naming_convention source extractor (reconstructed from gaze-py)
│ │ ├── docstring.py # docstring source extractor (reconstructed from gaze-py)
│ │ ├── _routing.py # effect-type → category routing (reconstructed from gaze-py)
│ │ ├── _types.py # SignalResult value type
│ │ └── adapter.py # extract_signals fan-out (classify_signals method)
│ └── quality/
│ ├── __init__.py # re-exports run_test_mapping
│ ├── pairing.py # test-function pairing (3 strategies, lifted from gaze-py)
│ ├── assertions.py # assertion detection & classification (lifted from gaze-py)
│ ├── mapping.py # side-effect-type inference (test_mapping method)
│ └── pipeline.py # run_test_mapping orchestration (test_mapping method)
├── tests/
├── pyproject.toml
└── NOTICE
Expand All @@ -85,6 +93,8 @@ Delivered in issue #4: `detector.py`, `complexity.py`, `coverage.py`, `_shared.p
and the `analyze`, `complexity`, and `coverage` JSON-RPC methods.
Delivered in issue #5: the `signals/` extractors, `analysis/inference.py`
(astroid caller-count inference), and the `classify_signals` JSON-RPC method.
Delivered in issue #6: the `quality/` package (`pairing.py`, `assertions.py`,
`mapping.py`, `pipeline.py`), and the `test_mapping` JSON-RPC method.

## Limits & Troubleshooting

Expand All @@ -109,7 +119,8 @@ invalid, the `coverage` method returns an empty result (`[]`), never an error.
## License

Apache 2.0 -- see [LICENSE](LICENSE). Portions of `detector.py`,
`complexity.py`, and the `signals/` extractors (`interface.py`, `visibility.py`,
`caller.py`, `naming.py`, `docstring.py`, `_routing.py`) are lifted or
reconstructed from gaze-py under Apache-2.0; see [NOTICE](NOTICE) for
`complexity.py`, `quality/pairing.py`, `quality/assertions.py`, and the
`signals/` extractors (`interface.py`, `visibility.py`, `caller.py`,
`naming.py`, `docstring.py`, `_routing.py`) are lifted or reconstructed from
gaze-py (Copyright Matt Peter, Apache 2.0); see [NOTICE](NOTICE) for
attribution.
2 changes: 2 additions & 0 deletions openspec/changes/test-mapping/.openspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-08-31
Loading
Loading