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
28 changes: 20 additions & 8 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ subprocess. The division of responsibility:
AST analysis
- **Scope analysis**: Python `symtable` module (stdlib) for
global/nonlocal detection
- **Inference** (planned): [Astroid](https://github.com/pylint-dev/astroid)
for name resolution, type inference, cross-module imports
- **Inference**: [Astroid](https://github.com/pylint-dev/astroid) `>=3.0,<4`
(shipped) for caller-count inference in `analysis/inference.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 @@ -91,13 +91,24 @@ snake-eyes/
│ ├── protocol.py # Request/response types
│ ├── discovery.py # File discovery (os.walk)
│ ├── coverage.py # Coverage data parser (coverage.json / .coverage)
│ └── analysis/
│ ├── analysis/
│ │ ├── __init__.py
│ │ ├── _shared.py # Shared helpers (safe file reader, package derivation)
│ │ ├── effects.py # 48-type SideEffectType taxonomy
│ │ ├── models.py # Effect / FunctionRecord data models
│ │ ├── 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
│ ├── _shared.py # Shared helpers (safe file reader, package derivation)
│ ├── effects.py # 48-type SideEffectType taxonomy
│ ├── models.py # Effect / FunctionRecord data models
│ ├── detector.py # Python side-effect detector (analyze method)
│ └── complexity.py # McCabe cyclomatic complexity (complexity method)
│ ├── _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)
├── tests/
├── .github/workflows/ # CI: ruff, mypy, pytest gates
├── pyproject.toml
Expand All @@ -107,6 +118,7 @@ snake-eyes/
└── NOTICE
```
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.

## Shell Commands

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

Capability flags advertised at handshake: `discover` is `true`;
`test_mapping`, `classify_signals`, and `streaming` are `false`.
Side-effect detection is implemented. coverage.py (`>=7.0,<8`) is a
runtime dependency (shipped). Astroid (name inference) is planned for
a later issue. `radon` is not used — cyclomatic complexity is computed
via a lifted McCabe implementation (no radon dependency).
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
implementation (no radon dependency).

## Installation

Expand Down Expand Up @@ -56,21 +58,33 @@ snake-eyes/
│ ├── protocol.py # Request/response types
│ ├── discovery.py # File discovery (os.walk)
│ ├── coverage.py # Coverage data parser (coverage.json / .coverage)
│ └── analysis/
│ ├── analysis/
│ │ ├── __init__.py
│ │ ├── _shared.py # Shared helpers (safe file reader, package derivation)
│ │ ├── effects.py # 48-type SideEffectType taxonomy
│ │ ├── models.py # Effect / FunctionRecord data models
│ │ ├── 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
│ ├── _shared.py # Shared helpers (safe file reader, package derivation)
│ ├── effects.py # 48-type SideEffectType taxonomy
│ ├── models.py # Effect / FunctionRecord data models
│ ├── detector.py # Python side-effect detector (analyze method)
│ └── complexity.py # McCabe cyclomatic complexity (complexity method)
│ ├── 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)
├── tests/
├── pyproject.toml
└── NOTICE
```

Delivered in issue #4: `detector.py`, `complexity.py`, `coverage.py`, `_shared.py`,
and the `analyze`, `complexity`, and `coverage` JSON-RPC methods.
Planned later: astroid-based name inference.
Delivered in issue #5: the `signals/` extractors, `analysis/inference.py`
(astroid caller-count inference), and the `classify_signals` JSON-RPC method.

## Limits & Troubleshooting

Expand All @@ -94,6 +108,8 @@ invalid, the `coverage` method returns an empty result (`[]`), never an error.

## License

Apache 2.0 -- see [LICENSE](LICENSE). Portions of `detector.py` and
`complexity.py` are lifted from gaze-py under Apache-2.0; see [NOTICE](NOTICE)
for attribution.
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
attribution.
2 changes: 2 additions & 0 deletions openspec/changes/classify-signals/.openspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-08-29
Loading
Loading